Skip to content

Commit 520c592

Browse files
authored
Add OpenSSF Best Practices Badge, Address Warnings (#464)
### What kind of change does this PR introduce? * Adds the OpenSSF Best Practices badge (compliance is at 100%!) * Addresses several warnings from deprecated usages. ### Does this PR introduce a breaking change? It should not. ### Other information: https://www.bestpractices.dev/en/projects/10064
2 parents 280b5be + b082760 commit 520c592

File tree

8 files changed

+30
-20
lines changed

8 files changed

+30
-20
lines changed

CHANGELOG.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ v0.18.0 (unreleased)
88
* `ravenpy` now supports Python3.13. (PR #459)
99
* Updated `raven-hydro` to v0.4.0 (`RavenHydroFramework` v4.0.1). (PR #459)
1010
* Updated `xclim` to v0.54.0, `pint` to v0.24.4, and `numpy` to v1.24.0 (no longer pinned below v2.0). (PR #459)
11+
* `ravenpy` is now registered with the Open Source Security Foundation (OSSF) Best Practices initiative (`RavenPy OpenSSF-BP Status <https://www.bestpractices.dev/en/projects/10064>`_). (PR #464)
1112

1213
Bug fixes
1314
^^^^^^^^^
1415
* Fix bug in _MonthlyRecord class definition crashing the pydantic-autodoc serialization. (PR #458)
1516
* Fixed a small API bug in the `Comparing_hindcasts_and_ESP_forecasts.ipynb` notebook. (PR #463)
17+
* The `Raven` model previously always reported version "3.7", regardless of the installed `Raven` version. It now uses `raven-hydro`'s `__raven_version__` attribute. (PR #464)
1618

1719
Internal changes
1820
^^^^^^^^^^^^^^^^
@@ -22,6 +24,7 @@ Internal changes
2224
* Removed several `type: ignore` statements.
2325
* Spelling errors in documentation have been addressed.
2426
* GitHub Workflows now test `ravenpy` using macOS as well as Python3.13. (PR #459)
27+
* Several small deprecation and usage warnings as well as a few variable typing issues have been addressed. (PR #464)
2528

2629
v0.17.0 (2025-01-27)
2730
--------------------

README.rst

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ RavenPy |logo|
99
+----------------------------+-----------------------------------------------------+
1010
| Open Source | |license| |ossf-score| |
1111
+----------------------------+-----------------------------------------------------+
12-
| Coding Standards | |black| |isort| |ruff| |pre-commit| |
12+
| Coding Standards | |black| |isort| |ruff| |ossf-bp| |pre-commit| |
1313
+----------------------------+-----------------------------------------------------+
1414
| Development Status | |status| |build| |coveralls| |
1515
+----------------------------+-----------------------------------------------------+
@@ -87,10 +87,9 @@ This package was created with Cookiecutter_ and the `Ouranosinc/cookiecutter-pyp
8787
:target: https://github.com/CSHS-CWRA/RavenPy
8888
:alt: RavenPy Logo
8989

90-
..
91-
.. |ossf-bp| image:: https://bestpractices.coreinfrastructure.org/projects/9945/badge
92-
:target: https://bestpractices.coreinfrastructure.org/projects/9945
93-
:alt: Open Source Security Foundation Best Practices
90+
.. |ossf-bp| image:: https://bestpractices.coreinfrastructure.org/projects/10064/badge
91+
:target: https://bestpractices.coreinfrastructure.org/projects/10064
92+
:alt: Open Source Security Foundation Best Practices
9493

9594
.. |ossf-score| image:: https://api.securityscorecards.dev/projects/github.com/CSHS-CWRA/RavenPy/badge
9695
:target: https://securityscorecards.dev/viewer/?uri=github.com/CSHS-CWRA/RavenPy

src/ravenpy/config/defaults.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from raven_hydro import __raven_version__
2+
13
units = {
24
"PRECIP": "mm/d",
35
"PRECIP_DAILY_AVE": "mm/d",
@@ -58,11 +60,10 @@ def default_nc_attrs():
5860
import datetime as dt
5961

6062
now = dt.datetime.now().isoformat(timespec="seconds")
61-
# TODO: get version from shared library
62-
version = "3.7"
63+
version = __raven_version__
6364

6465
return {
6566
"history": f"Created on {now} by Raven {version}",
6667
"references": "Craig, J.R., and the Raven Development Team, Raven user's and developer's manual "
67-
f"(Version {version}), URL: http://raven.uwaterloo.ca/ (2023).",
68+
f"(Version {version}), URL: https://raven.uwaterloo.ca/ (2025).",
6869
}

src/ravenpy/config/rvs.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
from typing import Any, Optional, Union
66

77
import cftime
8-
from pydantic import ConfigDict, Field, ValidationInfo, field_validator, model_validator
8+
from pydantic import ConfigDict, Field, ValidationInfo, field_validator
9+
from raven_hydro import __raven_version__
910

1011
from ..config import commands as rc
1112
from ..config import options as o
@@ -29,9 +30,9 @@ class RVI(RV):
2930

3031
run_name: Optional[str] = optfield(alias="RunName")
3132
calendar: Optional[o.Calendar] = optfield(alias="Calendar")
32-
start_date: Optional[date] = optfield(alias="StartDate")
33+
start_date: Optional[Union[str, date]] = optfield(alias="StartDate")
3334
assimilation_start_time: Optional[date] = optfield(alias="AssimilationStartTime")
34-
end_date: Optional[date] = optfield(alias="EndDate")
35+
end_date: Optional[Union[str, date]] = optfield(alias="EndDate")
3536
duration: Optional[float] = optfield(alias="Duration")
3637
time_step: Optional[Union[float, str]] = optfield(alias="TimeStep")
3738
interpolation: Optional[o.Interpolation] = optfield(alias="Interpolation")
@@ -138,6 +139,8 @@ def dates2cf(cls, v, info):
138139
).value.lower()
139140

140141
obj = cftime._cftime.DATE_TYPES[calendar]
142+
if isinstance(v, str):
143+
v = dt.datetime.fromisoformat(v)
141144

142145
return obj(*v.timetuple()[:6])
143146

@@ -258,15 +261,14 @@ class RVE(RV):
258261
class Config(RVI, RVC, RVH, RVT, RVP, RVE):
259262
__rv__ = None
260263

261-
def header(self, rv):
264+
@staticmethod
265+
def header(rv):
262266
"""Return the header to print at the top of each RV file."""
263-
import datetime as dt
264267
from textwrap import dedent
265268

266269
import ravenpy
267270

268-
# TODO: Better mechanism to fetch version
269-
version = "3.7"
271+
version = __raven_version__
270272

271273
return dedent(
272274
f"""
@@ -512,11 +514,11 @@ def zip(
512514
return zip
513515

514516

515-
def is_symbolic(params: dict) -> bool:
517+
def is_symbolic(params: Union[dict, Any]) -> bool:
516518
"""Return True if parameters include a symbolic variable."""
517519
from pymbolic.primitives import Variable
518520

519-
if is_dataclass(params):
521+
if is_dataclass(params) and not isinstance(params, type):
520522
params = {field.name: getattr(params, field.name) for field in fields(params)}
521523

522524
return any([isinstance(v, Variable) for v in params.values()])

src/ravenpy/extractors/routing_product.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from osgeo import ogr, osr
1515
from shapely import wkt
1616

17+
osr.UseExceptions()
1718
except (ImportError, ModuleNotFoundError) as e:
1819
msg = gis_import_error_message.format(Path(__file__).stem)
1920
raise ImportError(msg) from e

src/ravenpy/utilities/analysis.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@
1010

1111
try:
1212
import rasterio
13-
from osgeo.gdal import Dataset, DEMProcessing
13+
from osgeo.gdal import Dataset, DEMProcessing, UseExceptions
1414
from shapely.geometry import GeometryCollection, MultiPolygon, Polygon, shape
15+
16+
UseExceptions()
1517
except (ImportError, ModuleNotFoundError) as e:
1618
msg = gis_import_error_message.format(Path(__file__).stem)
1719
raise ImportError(msg) from e

src/ravenpy/utilities/forecasting.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,9 @@ def ensemble_prediction(
374374

375375
# Run the model for each year
376376
ensemble = []
377-
forecast_ds = xr.open_dataset(forecast, use_cftime=True)
377+
378+
time_coder = xr.coders.CFDatetimeCoder(use_cftime=True)
379+
forecast_ds = xr.open_dataset(forecast, decode_times=time_coder)
378380

379381
for member in range(0, len(forecast_ds[ens_dim])):
380382
# Prepare model instance

tests/test_geoserver.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def test_hydrobasins_upstream_aggregate(self, tmp_path):
7676
aggregated = self.geoserver.hydrobasins_aggregate(gdf_upstream)
7777

7878
assert len(aggregated) == 1
79-
assert float(aggregated.SUB_AREA.values) == 4977.8
79+
assert aggregated.SUB_AREA.values[0] == 4977.8
8080
np.testing.assert_equal(
8181
aggregated.geometry.bounds.values,
8282
np.array([[-83.8167, 8.7625, -82.7125, 9.5875]]),

0 commit comments

Comments
 (0)