From 27e4fb1239d2dde53c2159cc8468eb6488336601 Mon Sep 17 00:00:00 2001 From: Kevin Anderson Date: Mon, 14 Mar 2022 14:35:26 -0400 Subject: [PATCH 01/11] deprecate pvlib.forecast classes --- pvlib/forecast.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pvlib/forecast.py b/pvlib/forecast.py index 634ae75ab2..1bd0b25565 100644 --- a/pvlib/forecast.py +++ b/pvlib/forecast.py @@ -15,6 +15,7 @@ from siphon.ncss import NCSS import warnings +from pvlib._deprecation import deprecated warnings.warn( @@ -22,7 +23,15 @@ 'The API may change, the functionality may be consolidated into an io ' 'module, or the module may be separated into its own package.') +_forecast_deprecated = deprecated( + since='0.9.1', + removal='a future release', + addendum='For details, see https://pvlib-python.readthedocs.io/en/stable/user_guide/forecasts.html' # noqa: E501 +) +# don't decorate the base class to prevent the subclasses from showing +# duplicate warnings: +#@_forecast_deprecated class ForecastModel: """ An object for querying and holding forecast model information for @@ -684,6 +693,7 @@ def gust_to_speed(self, data, scaling=1/1.4): return wind_speed +@_forecast_deprecated class GFS(ForecastModel): """ Subclass of the ForecastModel class representing GFS @@ -785,6 +795,7 @@ def process_data(self, data, cloud_cover='total_clouds', **kwargs): return data[self.output_variables] +@_forecast_deprecated class HRRR_ESRL(ForecastModel): # noqa: N801 """ Subclass of the ForecastModel class representing @@ -875,6 +886,7 @@ def process_data(self, data, cloud_cover='total_clouds', **kwargs): return data[self.output_variables] +@_forecast_deprecated class NAM(ForecastModel): """ Subclass of the ForecastModel class representing NAM @@ -956,6 +968,7 @@ def process_data(self, data, cloud_cover='total_clouds', **kwargs): return data[self.output_variables] +@_forecast_deprecated class HRRR(ForecastModel): """ Subclass of the ForecastModel class representing HRRR @@ -1044,6 +1057,7 @@ def process_data(self, data, cloud_cover='total_clouds', **kwargs): return data[self.output_variables] +@_forecast_deprecated class NDFD(ForecastModel): """ Subclass of the ForecastModel class representing NDFD forecast @@ -1112,6 +1126,7 @@ def process_data(self, data, **kwargs): return data[self.output_variables] +@_forecast_deprecated class RAP(ForecastModel): """ Subclass of the ForecastModel class representing RAP forecast model. From 6b69916df15de2258014d02c852ce0834a883971 Mon Sep 17 00:00:00 2001 From: Kevin Anderson Date: Mon, 14 Mar 2022 14:35:35 -0400 Subject: [PATCH 02/11] catch warnings in tests --- pvlib/tests/test_forecast.py | 41 ++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/pvlib/tests/test_forecast.py b/pvlib/tests/test_forecast.py index db2ed75154..657c03d463 100644 --- a/pvlib/tests/test_forecast.py +++ b/pvlib/tests/test_forecast.py @@ -14,6 +14,8 @@ ) from .conftest import RERUNS, RERUNS_DELAY +from pvlib._deprecation import pvlibDeprecationWarning + pytestmark = pytest.mark.skipif(not has_siphon, reason='requires siphon') @@ -90,7 +92,8 @@ def test_process_data(model): def test_bad_kwarg_get_data(): # For more information on why you would want to pass an unknown keyword # argument, see Github issue #745. - amodel = NAM() + with pytest.warns(pvlibDeprecationWarning): + amodel = NAM() data = amodel.get_data(_latitude, _longitude, _start, _end, bad_kwarg=False) assert not data.empty @@ -103,7 +106,8 @@ def test_bad_kwarg_get_data(): def test_bad_kwarg_get_processed_data(): # For more information on why you would want to pass an unknown keyword # argument, see Github issue #745. - amodel = NAM() + with pytest.warns(pvlibDeprecationWarning): + amodel = NAM() data = amodel.get_processed_data(_latitude, _longitude, _start, _end, bad_kwarg=False) assert not data.empty @@ -114,7 +118,8 @@ def test_bad_kwarg_get_processed_data(): @pytest.mark.remote_data @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY) def test_how_kwarg_get_processed_data(): - amodel = NAM() + with pytest.warns(pvlibDeprecationWarning): + amodel = NAM() data = amodel.get_processed_data(_latitude, _longitude, _start, _end, how='clearsky_scaling') assert not data.empty @@ -125,7 +130,8 @@ def test_how_kwarg_get_processed_data(): @pytest.mark.remote_data @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY) def test_vert_level(): - amodel = NAM() + with pytest.warns(pvlibDeprecationWarning): + amodel = NAM() vert_level = 5000 amodel.get_processed_data(_latitude, _longitude, _start, _end, vert_level=vert_level) @@ -136,7 +142,8 @@ def test_vert_level(): @pytest.mark.remote_data @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY) def test_datetime(): - amodel = NAM() + with pytest.warns(pvlibDeprecationWarning): + amodel = NAM() start = datetime.now(tz=timezone.utc) end = start + timedelta(days=1) amodel.get_processed_data(_latitude, _longitude, start, end) @@ -147,7 +154,8 @@ def test_datetime(): @pytest.mark.remote_data @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY) def test_queryvariables(): - amodel = GFS() + with pytest.warns(pvlibDeprecationWarning): + amodel = GFS() new_variables = ['u-component_of_wind_height_above_ground'] data = amodel.get_data(_latitude, _longitude, _start, _end, query_variables=new_variables) @@ -156,16 +164,19 @@ def test_queryvariables(): @requires_siphon def test_latest(): - GFS(set_type='latest') + with pytest.warns(pvlibDeprecationWarning): + GFS(set_type='latest') @requires_siphon def test_full(): - GFS(set_type='full') + with pytest.warns(pvlibDeprecationWarning): + GFS(set_type='full') def test_temp_convert(): - amodel = GFS() + with pytest.warns(pvlibDeprecationWarning): + amodel = GFS() data = pd.DataFrame({'temp_air': [273.15]}) data['temp_air'] = amodel.kelvin_to_celsius(data['temp_air']) @@ -183,27 +194,31 @@ def test_temp_convert(): def test_set_location(): - amodel = GFS() + with pytest.warns(pvlibDeprecationWarning): + amodel = GFS() latitude, longitude = 32.2, -110.9 time = 'UTC' amodel.set_location(time, latitude, longitude) def test_set_query_time_range_tzfail(): - amodel = GFS() + with pytest.warns(pvlibDeprecationWarning): + amodel = GFS() with pytest.raises(TypeError): amodel.set_query_time_range(datetime.now(), datetime.now()) def test_cloud_cover_to_transmittance_linear(): - amodel = GFS() + with pytest.warns(pvlibDeprecationWarning): + amodel = GFS() assert_allclose(amodel.cloud_cover_to_transmittance_linear(0), 0.75) assert_allclose(amodel.cloud_cover_to_transmittance_linear(100), 0.0) assert_allclose(amodel.cloud_cover_to_transmittance_linear(0, 0.5), 0.5) def test_cloud_cover_to_ghi_linear(): - amodel = GFS() + with pytest.warns(pvlibDeprecationWarning): + amodel = GFS() ghi_clear = 1000 offset = 25 out = amodel.cloud_cover_to_ghi_linear(0, ghi_clear, offset=offset) From f61055f9436dea768e34d711b4a7851595810128 Mon Sep 17 00:00:00 2001 From: Kevin Anderson Date: Mon, 14 Mar 2022 14:35:58 -0400 Subject: [PATCH 03/11] add warning admonition to forecasts.rst --- docs/sphinx/source/user_guide/forecasts.rst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/sphinx/source/user_guide/forecasts.rst b/docs/sphinx/source/user_guide/forecasts.rst index a89904eccd..d61b40387a 100644 --- a/docs/sphinx/source/user_guide/forecasts.rst +++ b/docs/sphinx/source/user_guide/forecasts.rst @@ -4,6 +4,25 @@ Forecasting *********** +.. warning:: + + The ``pvlib.forecast`` module is deprecated as of version ``0.9.1``. + + Because none of the current pvlib team members are able to continue + maintaining it, the functionality in ``pvlib.forecast`` is deprecated + and will be removed without replacement in a future version. If you + are interested in maintaining this functionality, please let us know. + + You can fetch forecast data yourself using ``siphon`` (see the + docs below this warning) and the code from pvlib v0.9.0 as a reference: + https://github.com/pvlib/pvlib-python/blob/v0.9.0/pvlib/forecast.py + + The `Solar Forecast Arbiter Core + `_ + offers similar (and more robust) forecast processing functionality + and may be a suitable replacement for some users. + + pvlib python provides a set of functions and classes that make it easy to obtain weather forecast data and convert that data into a PV power forecast. Users can retrieve standardized weather forecast data relevant From 1bd8bab2c0f29cdfd32cf9e74dabc1f69a0e5675 Mon Sep 17 00:00:00 2001 From: Kevin Anderson Date: Mon, 14 Mar 2022 14:36:04 -0400 Subject: [PATCH 04/11] whatsnew --- docs/sphinx/source/whatsnew/v0.9.1.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/sphinx/source/whatsnew/v0.9.1.rst b/docs/sphinx/source/whatsnew/v0.9.1.rst index 685a7880a4..7fb92f558a 100644 --- a/docs/sphinx/source/whatsnew/v0.9.1.rst +++ b/docs/sphinx/source/whatsnew/v0.9.1.rst @@ -16,6 +16,8 @@ Deprecations :py:meth:`pvlib.modelchain.ModelChain.with_sapm` for alternative simplified :py:class:`~pvlib.modelchain.ModelChain` interfaces, although note that the inputs do not directly translate. (:pull:`1401`) +* All functionality in the ``pvlib.forecasts`` module is deprecated. + For details, see :ref:`forecasts`. (:issue:`1057`, :pull:`1426`) Enhancements ~~~~~~~~~~~~ From 6584f798c9bc1b501f9612087732daf96860f105 Mon Sep 17 00:00:00 2001 From: Kevin Anderson Date: Mon, 14 Mar 2022 14:42:51 -0400 Subject: [PATCH 05/11] stickler --- pvlib/forecast.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/forecast.py b/pvlib/forecast.py index 1bd0b25565..ce80e0ad74 100644 --- a/pvlib/forecast.py +++ b/pvlib/forecast.py @@ -31,7 +31,7 @@ # don't decorate the base class to prevent the subclasses from showing # duplicate warnings: -#@_forecast_deprecated +# @_forecast_deprecated class ForecastModel: """ An object for querying and holding forecast model information for From 9891d0dcc45e0853de4f890881d83bf8453265c1 Mon Sep 17 00:00:00 2001 From: Kevin Anderson Date: Mon, 14 Mar 2022 14:46:32 -0400 Subject: [PATCH 06/11] pin pytest < 7.1.0 --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 7301f5eab6..609c96d34c 100755 --- a/setup.py +++ b/setup.py @@ -49,7 +49,8 @@ if sys.version_info.major == 3 and sys.version_info.minor == 6: INSTALL_REQUIRES.append('dataclasses') -TESTS_REQUIRE = ['nose', 'pytest', 'pytest-cov', 'pytest-mock', +# pytest<7.1.0 for https://stackoverflow.com/q/71466065 +TESTS_REQUIRE = ['nose', 'pytest<7.1.0', 'pytest-cov', 'pytest-mock', 'requests-mock', 'pytest-timeout', 'pytest-rerunfailures', 'pytest-remotedata'] EXTRAS_REQUIRE = { From cbb2b49e8fa59c7569e23feae601d2c0d9d767b6 Mon Sep 17 00:00:00 2001 From: Kevin Anderson Date: Mon, 14 Mar 2022 14:54:06 -0400 Subject: [PATCH 07/11] pin pytest in the right place this time --- ci/azure/posix.yml | 2 +- setup.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ci/azure/posix.yml b/ci/azure/posix.yml index 086f03dd69..65e43ac42b 100644 --- a/ci/azure/posix.yml +++ b/ci/azure/posix.yml @@ -23,7 +23,7 @@ jobs: versionSpec: '$(python.version)' - script: | - pip install pytest pytest-cov pytest-mock requests-mock pytest-timeout pytest-azurepipelines pytest-rerunfailures pytest-remotedata + pip install pytest==7.0.1 pytest-cov pytest-mock requests-mock pytest-timeout pytest-azurepipelines pytest-rerunfailures pytest-remotedata pip install -e . pytest pvlib --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html displayName: 'Test with pytest' diff --git a/setup.py b/setup.py index 609c96d34c..420345b97e 100755 --- a/setup.py +++ b/setup.py @@ -49,10 +49,10 @@ if sys.version_info.major == 3 and sys.version_info.minor == 6: INSTALL_REQUIRES.append('dataclasses') -# pytest<7.1.0 for https://stackoverflow.com/q/71466065 -TESTS_REQUIRE = ['nose', 'pytest<7.1.0', 'pytest-cov', 'pytest-mock', +TESTS_REQUIRE = ['nose', 'pytest', 'pytest-cov', 'pytest-mock', 'requests-mock', 'pytest-timeout', 'pytest-rerunfailures', 'pytest-remotedata'] + EXTRAS_REQUIRE = { 'optional': ['cython', 'ephem', 'netcdf4', 'nrel-pysam', 'numba', 'pvfactors', 'siphon', 'statsmodels', From 62b3df72ce059be336cb176e2da74ccc3e637fdd Mon Sep 17 00:00:00 2001 From: Kevin Anderson Date: Mon, 14 Mar 2022 15:07:26 -0400 Subject: [PATCH 08/11] more warning suppression in tests --- pvlib/tests/test_forecast.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pvlib/tests/test_forecast.py b/pvlib/tests/test_forecast.py index 657c03d463..4382666317 100644 --- a/pvlib/tests/test_forecast.py +++ b/pvlib/tests/test_forecast.py @@ -54,7 +54,8 @@ @requires_siphon @pytest.fixture(scope='module', params=_modelclasses) def model(request): - amodel = request.param() + with pytest.warns(pvlibDeprecationWarning): + amodel = request.param() try: raw_data = amodel.get_data(_latitude, _longitude, _start, _end) except Exception as e: From a652b93d20c07d9e2e023da5c0cd4543ea1c0700 Mon Sep 17 00:00:00 2001 From: Kevin Anderson Date: Tue, 15 Mar 2022 08:39:50 -0400 Subject: [PATCH 09/11] unpin pytest --- ci/azure/posix.yml | 2 +- setup.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ci/azure/posix.yml b/ci/azure/posix.yml index 65e43ac42b..086f03dd69 100644 --- a/ci/azure/posix.yml +++ b/ci/azure/posix.yml @@ -23,7 +23,7 @@ jobs: versionSpec: '$(python.version)' - script: | - pip install pytest==7.0.1 pytest-cov pytest-mock requests-mock pytest-timeout pytest-azurepipelines pytest-rerunfailures pytest-remotedata + pip install pytest pytest-cov pytest-mock requests-mock pytest-timeout pytest-azurepipelines pytest-rerunfailures pytest-remotedata pip install -e . pytest pvlib --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html displayName: 'Test with pytest' diff --git a/setup.py b/setup.py index 420345b97e..7301f5eab6 100755 --- a/setup.py +++ b/setup.py @@ -52,7 +52,6 @@ TESTS_REQUIRE = ['nose', 'pytest', 'pytest-cov', 'pytest-mock', 'requests-mock', 'pytest-timeout', 'pytest-rerunfailures', 'pytest-remotedata'] - EXTRAS_REQUIRE = { 'optional': ['cython', 'ephem', 'netcdf4', 'nrel-pysam', 'numba', 'pvfactors', 'siphon', 'statsmodels', From 749097b40f8be70c95b098a02bf43499d9a6d68f Mon Sep 17 00:00:00 2001 From: Kevin Anderson <57452607+kanderso-nrel@users.noreply.github.com> Date: Thu, 17 Mar 2022 11:27:43 -0600 Subject: [PATCH 10/11] Update docs/sphinx/source/whatsnew/v0.9.1.rst --- docs/sphinx/source/whatsnew/v0.9.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/sphinx/source/whatsnew/v0.9.1.rst b/docs/sphinx/source/whatsnew/v0.9.1.rst index 7fb92f558a..4622ed24ac 100644 --- a/docs/sphinx/source/whatsnew/v0.9.1.rst +++ b/docs/sphinx/source/whatsnew/v0.9.1.rst @@ -16,7 +16,7 @@ Deprecations :py:meth:`pvlib.modelchain.ModelChain.with_sapm` for alternative simplified :py:class:`~pvlib.modelchain.ModelChain` interfaces, although note that the inputs do not directly translate. (:pull:`1401`) -* All functionality in the ``pvlib.forecasts`` module is deprecated. +* All functionality in the ``pvlib.forecast`` module is deprecated. For details, see :ref:`forecasts`. (:issue:`1057`, :pull:`1426`) Enhancements From 9d4f893cbd9e55d7ee0d347fba6c01941764a3a2 Mon Sep 17 00:00:00 2001 From: Kevin Anderson Date: Thu, 17 Mar 2022 13:30:52 -0400 Subject: [PATCH 11/11] copy warning to reference/forecasting.rst --- docs/sphinx/source/reference/forecasting.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/sphinx/source/reference/forecasting.rst b/docs/sphinx/source/reference/forecasting.rst index ff4df7ed4d..8b1e125c8a 100644 --- a/docs/sphinx/source/reference/forecasting.rst +++ b/docs/sphinx/source/reference/forecasting.rst @@ -3,6 +3,12 @@ Forecasting =========== +.. warning:: + + All functionality in the ``pvlib.forecast`` module is deprecated as of + pvlib v0.9.1. For details, see :ref:`forecasts`. + + Forecast models ---------------