Skip to content

Commit f430a74

Browse files
GillesFischerVAdamRJensenadriesse
authored
Fix CAMS message error handler (#1905)
* Fix CAMS message error handler - Issue#1799 * Fix CAMS message error handler - Issue#1799 * fix Python Flake8 Linter error * Fix associated UT and add contribution in WhatsNews * Fix line code length in test_sodapro.py * Fix typo in contributor ghuser * Update geographical coverage description * correction in maximum longitude available for CAMS Radiation * revert of last change * Add doc string changes from adriesse Co-authored-by: Anton Driesse <[email protected]> * Flake8 correction --------- Co-authored-by: Adam R. Jensen <[email protected]> Co-authored-by: Anton Driesse <[email protected]>
1 parent c18a004 commit f430a74

File tree

3 files changed

+23
-12
lines changed

3 files changed

+23
-12
lines changed

docs/sphinx/source/whatsnew/v0.10.3.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Enhancements
1818

1919
Bug fixes
2020
~~~~~~~~~
21+
* Fixed CAMS error message handler in
22+
:py:func:`pvlib.iotools.get_cams` (:issue:`1799`, :pull:`1905`)
2123
* Fix mapping of the dew point column to ``temp_dew`` when ``map_variables``
2224
is True in :py:func:`pvlib.iotools.get_psm3`. (:pull:`1920`)
2325

@@ -45,7 +47,8 @@ Contributors
4547
* Miguel Sánchez de León Peque (:ghuser:`Peque`)
4648
* Will Hobbs (:ghuser:`williamhobbs`)
4749
* Anton Driesse (:ghuser:`adriesse`)
50+
* Gilles Fischer (:ghuser:`GillesFischerV`)
51+
* Adam R. Jensen (:ghusuer:`AdamRJensen`)
4852
* :ghuser:`matsuobasho`
4953
* Harry Jack (:ghuser:`harry-solcast`)
50-
* Adam R. Jensen (:ghuser:`AdamRJensen`)
5154
* Kevin Anderson (:ghuser:`kandersolar`)

pvlib/iotools/sodapro.py

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ def get_cams(latitude, longitude, start, end, email, identifier='mcclear',
5757
Access: free, but requires registration, see [2]_
5858
5959
Requests: max. 100 per day
60+
6061
Geographical coverage: worldwide for CAMS McClear and approximately -66° to
61-
66° in both latitude and longitude for CAMS Radiation.
62+
66° in latitude and -66° to 180° in longitude for CAMS Radiation. See [3]_
63+
for a map of the geographical coverage.
6264
6365
Parameters
6466
----------
@@ -157,6 +159,9 @@ def get_cams(latitude, longitude, start, end, email, identifier='mcclear',
157159
<https://atmosphere.copernicus.eu/solar-radiation>`_
158160
.. [2] `CAMS Radiation Automatic Access (SoDa)
159161
<https://www.soda-pro.com/help/cams-services/cams-radiation-service/automatic-access>`_
162+
.. [3] A. R. Jensen et al., pvlib iotools — Open-source Python functions
163+
for seamless access to solar irradiance data. Solar Energy. 2023. Vol
164+
266, pp. 112092. :doi:`10.1016/j.solener.2023.112092`
160165
"""
161166
try:
162167
time_step_str = TIME_STEPS_MAP[time_step]
@@ -215,14 +220,16 @@ def get_cams(latitude, longitude, start, end, email, identifier='mcclear',
215220
res = requests.get(base_url + '?DataInputs=' + data_inputs, params=params,
216221
timeout=timeout)
217222

218-
# Invalid requests returns an XML error message and the HTTP staus code 200
219-
# as if the request was successful. Therefore, errors cannot be handled
220-
# automatic (e.g. res.raise_for_status()) and errors are handled manually
221-
if res.headers['Content-Type'] == 'application/xml':
223+
# Response from CAMS follows the status and reason format of PyWPS4
224+
# If an error occurs on server side, it will return error 400 - bad request
225+
# Additional information is available in the response text, so it is added
226+
# to the error displayed to facilitate users effort to fix their request
227+
if not res.ok:
222228
errors = res.text.split('ows:ExceptionText')[1][1:-2]
223-
raise requests.HTTPError(errors, response=res)
229+
res.reason = "%s: <%s>" % (res.reason, errors)
230+
res.raise_for_status()
224231
# Successful requests returns a csv data file
225-
elif res.headers['Content-Type'] == 'application/csv':
232+
else:
226233
fbuf = io.StringIO(res.content.decode('utf-8'))
227234
data, metadata = parse_cams(fbuf, integrated=integrated, label=label,
228235
map_variables=map_variables)

pvlib/tests/iotools/test_sodapro.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -248,20 +248,21 @@ def test_get_cams_bad_request(requests_mock):
248248
requests inputs. Also tests if the specified server url gets used"""
249249

250250
# Subset of an xml file returned for errornous requests
251-
mock_response_bad = """<?xml version="1.0" encoding="utf-8"?>
251+
mock_response_bad_text = """<?xml version="1.0" encoding="utf-8"?>
252252
<ows:Exception exceptionCode="NoApplicableCode" locator="None">
253253
<ows:ExceptionText>Failed to execute WPS process [get_mcclear]:
254254
Please, register yourself at www.soda-pro.com
255255
</ows:ExceptionText>"""
256256

257257
url_cams_bad_request = 'https://pro.soda-is.com/service/wps?DataInputs=latitude=55.7906;longitude=12.5251;altitude=-999;date_begin=2020-01-01;date_end=2020-05-04;time_ref=TST;summarization=PT01H;username=test%2540test.com;verbose=false&Service=WPS&Request=Execute&Identifier=get_mcclear&version=1.0.0&RawDataOutput=irradiation' # noqa: E501
258258

259-
requests_mock.get(url_cams_bad_request, text=mock_response_bad,
260-
headers={'Content-Type': 'application/xml'})
259+
requests_mock.get(url_cams_bad_request, status_code=400,
260+
text=mock_response_bad_text)
261261

262262
# Test if HTTPError is raised if incorrect input is specified
263263
# In the below example a non-registrered email is specified
264-
with pytest.raises(requests.HTTPError, match='Failed to execute WPS'):
264+
with pytest.raises(requests.exceptions.HTTPError,
265+
match='Failed to execute WPS process'):
265266
_ = sodapro.get_cams(
266267
start=pd.Timestamp('2020-01-01'),
267268
end=pd.Timestamp('2020-05-04'),

0 commit comments

Comments
 (0)