Skip to content

Commit 83ad840

Browse files
committed
Merge remote-tracking branch 'upstream/main' into pvsystem_racking
2 parents 3d5548c + c52e600 commit 83ad840

File tree

11 files changed

+341
-77
lines changed

11 files changed

+341
-77
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Update Top Ranked Issues
2+
3+
on:
4+
# For testing purposes (can be removed later)
5+
pull_request:
6+
schedule:
7+
# # Runs every day at 3:00 AM UTC
8+
# - cron: '0 3 * * *'
9+
- cron: '*/10 * * * *'
10+
11+
jobs:
12+
run-script:
13+
runs-on: ubuntu-latest
14+
15+
env:
16+
GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17+
18+
steps:
19+
- name: Check out the repository
20+
uses: actions/checkout@v4 # This ensures the repository code is available
21+
22+
- name: Set up Python
23+
uses: actions/setup-python@v5
24+
with:
25+
python-version: "3.12"
26+
27+
- name: Install dependencies
28+
run: |
29+
python -m pip install --upgrade pip
30+
pip install PyGithub
31+
32+
- name: Run update_top_ranking_issues.py
33+
run: |
34+
python ./scripts/update_top_ranking_issues.py

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ Contributing
8181
============
8282

8383
We need your help to make pvlib-python a great tool!
84-
Please see the [Contributing page](http://pvlib-python.readthedocs.io/en/stable/contributing.html) for more on how you can contribute.
84+
Please see the [Contributing page](https://pvlib-python.readthedocs.io/en/stable/contributing/index.html) for more on how you can contribute.
8585
The long-term success of pvlib-python requires substantial community support.
8686

8787

docs/sphinx/source/contributing/testing.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
.. _testing:
22

3-
Testing
4-
=======
3+
Testing and benchmarking
4+
========================
55

66
.. _overview:
77

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ Documentation
2222
racking model option, and various formatting edits for clarity.
2323
(:issue:`1942`, :pull:`2232`)
2424
:py:func:`~pvlib.pvsystem.dc_ohmic_losses` for clarity. (:issue:`1601`, :pull:`2229`)
25-
25+
* Updated :py:func:`~pvlib.irradiance.reindl` to include definitions of terms
26+
and a new "notes" section (:issue:`2183`, :pull:`2193`)
2627

2728
Testing
2829
~~~~~~~
@@ -32,8 +33,17 @@ Requirements
3233
~~~~~~~~~~~~
3334

3435

36+
Maintenance
37+
~~~~~~~~~~~
38+
* Added a decorator to deprecate renamed keyword arguments in functions,
39+
:py:func:`pvlib._deprecation.renamed_kwarg_warning`. (:pull:`2237`)
40+
41+
3542
Contributors
3643
~~~~~~~~~~~~
3744
* Cliff Hansen (:ghuser:`cwhanse`)
3845
* Rajiv Daxini (:ghuser:`RDaxini`)
3946

47+
* Mark Mikofski (:ghuser:`mikofski`)
48+
* matsuobasho (:ghuser:`matsuobasho`)
49+
* Echedey Luis (:ghuser:`echedey-ls`)

pvlib/_deprecation.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,3 +316,76 @@ def wrapper(*args, **kwargs):
316316
return finalize(wrapper, new_doc)
317317

318318
return deprecate
319+
320+
321+
def renamed_kwarg_warning(since, old_param_name, new_param_name, removal=""):
322+
"""
323+
Decorator to mark a possible keyword argument as deprecated and replaced
324+
with other name.
325+
326+
Raises a warning when the deprecated argument is used, and replaces the
327+
call with the new argument name. Does not modify the function signature.
328+
329+
.. warning::
330+
Ensure ``removal`` date with a ``fail_on_pvlib_version`` decorator in
331+
the test suite.
332+
333+
.. note::
334+
Not compatible with positional-only arguments.
335+
336+
.. note::
337+
Documentation for the function may updated to reflect the new parameter
338+
name; it is suggested to add a |.. versionchanged::| directive.
339+
340+
Parameters
341+
----------
342+
since : str
343+
The release at which this API became deprecated.
344+
old_param_name : str
345+
The name of the deprecated parameter.
346+
new_param_name : str
347+
The name of the new parameter.
348+
removal : str, optional
349+
The expected removal version, in order to compose the Warning message.
350+
351+
Examples
352+
--------
353+
>>> @renamed_kwarg_warning("1.4.0", "old_name", "new_name", "1.6.0")
354+
>>> def some_function(new_name=None):
355+
>>> pass
356+
>>> some_function(old_name=1)
357+
Parameter 'old_name' has been renamed since 1.4.0. and
358+
will be removed in 1.6.0. Please use 'new_name' instead.
359+
360+
>>> @renamed_kwarg_warning("1.4.0", "old_name", "new_name")
361+
>>> def some_function(new_name=None):
362+
>>> pass
363+
>>> some_function(old_name=1)
364+
Parameter 'old_name' has been renamed since 1.4.0. and
365+
will be removed soon. Please use 'new_name' instead.
366+
"""
367+
368+
def deprecate(func, old=old_param_name, new=new_param_name, since=since):
369+
def wrapper(*args, **kwargs):
370+
if old in kwargs:
371+
if new in kwargs:
372+
raise ValueError(
373+
f"{func.__name__} received both '{old}' and '{new}', "
374+
"which are mutually exclusive since they refer to the "
375+
f"same parameter. Please remove deprecated '{old}'."
376+
)
377+
warnings.warn(
378+
f"Parameter '{old}' has been renamed since {since}. "
379+
f"and will be removed "
380+
+ (f"in {removal}" if removal else "soon")
381+
+ f". Please use '{new}' instead.",
382+
_projectWarning,
383+
stacklevel=2,
384+
)
385+
kwargs[new] = kwargs.pop(old)
386+
return func(*args, **kwargs)
387+
388+
wrapper = functools.wraps(func)(wrapper)
389+
return wrapper
390+
391+
return deprecate

pvlib/data/variables_style_rules.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ ghi;global horizontal irradiance
1111
ghi_extra;horizontal irradiance at top of atmosphere (extraterrestrial)
1212
gri;ground-reflected irradiance
1313
ape;average photon energy
14-
aoi;angle of incidence between :math:`90\deg` and :math:`90\deg`
14+
aoi;angle of incidence. Angle between the surface normal vector and the vector pointing towards the sun's center
1515
aoi_projection;cos(aoi)
1616
airmass;airmass
1717
airmass_relative;relative airmass

pvlib/iam.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,8 @@ def martin_ruiz(aoi, a_r=0.16):
269269
270270
which is presented as :math:`AL(\alpha) = 1 - IAM` in equation 4 of [1]_,
271271
with :math:`\alpha` representing the angle of incidence AOI. Thus IAM = 1
272-
at AOI = 0, and IAM = 0 at AOI = 90. This equation is only valid for
273-
-90 <= aoi <= 90, therefore `iam` is constrained to 0.0 outside this
272+
at AOI = 0°, and IAM = 0 at AOI = 90°. This equation is only valid for
273+
<= aoi <= 90°, therefore `iam` is constrained to 0.0 outside this
274274
interval.
275275
276276
References
@@ -891,8 +891,8 @@ def schlick_diffuse(surface_tilt):
891891
implements only the integrated Schlick approximation.
892892
893893
Note also that the output of this function (which is an exact integration)
894-
can be compared with the output of :py:func:`marion_diffuse` which numerically
895-
integrates the Schlick approximation:
894+
can be compared with the output of :py:func:`marion_diffuse` which
895+
numerically integrates the Schlick approximation:
896896
897897
.. code::
898898

pvlib/irradiance.py

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -871,19 +871,14 @@ def haydavies(surface_tilt, surface_azimuth, dhi, dni, dni_extra,
871871
def reindl(surface_tilt, surface_azimuth, dhi, dni, ghi, dni_extra,
872872
solar_zenith, solar_azimuth):
873873
r'''
874-
Determine diffuse irradiance from the sky on a tilted surface using
875-
Reindl's 1990 model
876-
877-
.. math::
874+
Determine the diffuse irradiance from the sky on a tilted surface using
875+
the Reindl (1990) model.
878876
879-
I_{d} = DHI \left(A R_b + (1 - A) \left(\frac{1 + \cos\beta}{2}\right)
880-
\left(1 + \sqrt{\frac{I_{hb}}{I_h}} \sin^3(\beta/2)\right) \right)
881-
882-
Reindl's 1990 model determines the diffuse irradiance from the sky
883-
(ground reflected irradiance is not included in this algorithm) on a
884-
tilted surface using the surface tilt angle, surface azimuth angle,
877+
The Reindl (1990) model [1]_ [2]_ determines the diffuse irradiance from
878+
the sky on
879+
a tilted surface using the surface tilt angle, surface azimuth angle,
885880
diffuse horizontal irradiance, direct normal irradiance, global
886-
horizontal irradiance, extraterrestrial irradiance, sun zenith
881+
horizontal irradiance, extraterrestrial normal irradiance, sun zenith
887882
angle, and sun azimuth angle.
888883
889884
Parameters
@@ -905,7 +900,7 @@ def reindl(surface_tilt, surface_azimuth, dhi, dni, ghi, dni_extra,
905900
direct normal irradiance. [Wm⁻²]
906901
907902
ghi: numeric
908-
Global irradiance. [Wm⁻²]
903+
Global horizontal irradiance. [Wm⁻²]
909904
910905
dni_extra : numeric
911906
Extraterrestrial normal irradiance. [Wm⁻²]
@@ -925,23 +920,41 @@ def reindl(surface_tilt, surface_azimuth, dhi, dni, ghi, dni_extra,
925920
926921
Notes
927922
-----
928-
The poa_sky_diffuse calculation is generated from the Loutzenhiser et al.
929-
(2007) paper, equation 8. Note that I have removed the beam and ground
930-
reflectance portion of the equation and this generates ONLY the diffuse
931-
radiation from the sky and circumsolar, so the form of the equation
932-
varies slightly from equation 8.
923+
The Reindl (1990) model for the sky diffuse irradiance,
924+
:math:`I_d`, is as follows:
925+
926+
.. math::
927+
928+
I_{d} = DHI \left(A \cdot R_b + (1 - A)
929+
\left(\frac{1 + \cos\beta}{2}\right)
930+
\left(1 + \sqrt{\frac{BHI}{GHI}} \sin^3(\beta/2)\right) \right).
931+
932+
:math:`DHI`, :math:`BHI`, and :math:`GHI` are the diffuse horizontal, beam
933+
(direct) horizontal and global horizontal irradiances, respectively.
934+
:math:`A` is the anisotropy index, which is the ratio of the direct normal
935+
irradiance to the direct extraterrestrial irradiation, :math:`R_b` is the
936+
projection ratio, which is defined as the ratio of the cosine of the angle
937+
of incidence (AOI) to the cosine of the zenith angle, and :math:`\beta`
938+
is the tilt angle of the array.
939+
940+
Implementation is based on Loutzenhiser et al.
941+
(2007) [3]_, Equation 8. The beam and ground reflectance portion of the
942+
equation have been removed, therefore the model described here generates
943+
ONLY the diffuse radiation from the sky and circumsolar, so the form of the
944+
equation varies slightly from Equation 8 in [3]_.
933945
934946
References
935947
----------
936-
.. [1] Loutzenhiser P.G. et. al. "Empirical validation of models to
937-
compute solar irradiance on inclined surfaces for building energy
938-
simulation" 2007, Solar Energy vol. 81. pp. 254-267
939-
940-
.. [2] Reindl, D.T., Beckmann, W.A., Duffie, J.A., 1990a. Diffuse
948+
.. [1] Reindl, D. T., Beckmann, W. A., Duffie, J. A., 1990a. Diffuse
941949
fraction correlations. Solar Energy 45(1), 1-7.
942-
943-
.. [3] Reindl, D.T., Beckmann, W.A., Duffie, J.A., 1990b. Evaluation of
950+
:doi:`10.1016/0038-092X(90)90060-P`
951+
.. [2] Reindl, D. T., Beckmann, W. A., Duffie, J. A., 1990b. Evaluation of
944952
hourly tilted surface radiation models. Solar Energy 45(1), 9-17.
953+
:doi:`10.1016/0038-092X(90)90061-G`
954+
.. [3] Loutzenhiser P. G. et. al., 2007. Empirical validation of models to
955+
compute solar irradiance on inclined surfaces for building energy
956+
simulation. Solar Energy 81(2), 254-267
957+
:doi:`10.1016/j.solener.2006.03.009`
945958
'''
946959

947960
cos_tt = aoi_projection(surface_tilt, surface_azimuth,

pvlib/tests/test__deprecation.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
"""
2+
Test the _deprecation module.
3+
"""
4+
5+
import pytest
6+
7+
from pvlib import _deprecation
8+
from .conftest import fail_on_pvlib_version
9+
10+
import warnings
11+
12+
13+
@pytest.mark.xfail(strict=True,
14+
reason='fail_on_pvlib_version should cause test to fail')
15+
@fail_on_pvlib_version('0.0')
16+
def test_fail_on_pvlib_version():
17+
pass # pragma: no cover
18+
19+
20+
@fail_on_pvlib_version('100000.0')
21+
def test_fail_on_pvlib_version_pass():
22+
pass
23+
24+
25+
@pytest.mark.xfail(strict=True, reason='ensure that the test is called')
26+
@fail_on_pvlib_version('100000.0')
27+
def test_fail_on_pvlib_version_fail_in_test():
28+
raise Exception
29+
30+
31+
# set up to test using fixtures with function decorated with
32+
# conftest.fail_on_pvlib_version
33+
@pytest.fixture
34+
def some_data():
35+
return "some data"
36+
37+
38+
def alt_func(*args):
39+
return args
40+
41+
42+
@pytest.fixture
43+
def deprec_func():
44+
return _deprecation.deprecated(
45+
"350.8", alternative="alt_func", name="deprec_func", removal="350.9"
46+
)(alt_func)
47+
48+
49+
@fail_on_pvlib_version('350.9')
50+
def test_use_fixture_with_decorator(some_data, deprec_func):
51+
# test that the correct data is returned by the some_data fixture
52+
assert some_data == "some data"
53+
with pytest.warns(_deprecation.pvlibDeprecationWarning):
54+
# test for custom deprecation warning provided by pvlib
55+
deprec_func(some_data)
56+
57+
58+
@pytest.fixture
59+
def renamed_kwarg_func():
60+
"""Returns a function decorated by renamed_kwarg_warning.
61+
This function is called 'func' and has a docstring equal to 'docstring'.
62+
"""
63+
64+
@_deprecation.renamed_kwarg_warning(
65+
"0.1.0", "old_kwarg", "new_kwarg", "0.2.0"
66+
)
67+
def func(new_kwarg):
68+
"""docstring"""
69+
return new_kwarg
70+
71+
return func
72+
73+
74+
def test_renamed_kwarg_warning(renamed_kwarg_func):
75+
# assert decorated function name and docstring are unchanged
76+
assert renamed_kwarg_func.__name__ == "func"
77+
assert renamed_kwarg_func.__doc__ == "docstring"
78+
79+
# assert no warning is raised when using the new kwarg
80+
with warnings.catch_warnings():
81+
warnings.simplefilter("error")
82+
assert renamed_kwarg_func(new_kwarg=1) == 1 # as keyword argument
83+
assert renamed_kwarg_func(1) == 1 # as positional argument
84+
85+
# assert a warning is raised when using the old kwarg
86+
with pytest.warns(Warning, match="Parameter 'old_kwarg' has been renamed"):
87+
assert renamed_kwarg_func(old_kwarg=1) == 1
88+
89+
# assert an error is raised when using both the old and new kwarg
90+
with pytest.raises(ValueError, match="they refer to the same parameter."):
91+
renamed_kwarg_func(old_kwarg=1, new_kwarg=2)
92+
93+
# assert when not providing any of them
94+
with pytest.raises(
95+
TypeError, match="missing 1 required positional argument"
96+
):
97+
renamed_kwarg_func()

0 commit comments

Comments
 (0)