Skip to content

Commit

Permalink
support python 3.13, deprecate 3.9, release note fix (#418)
Browse files Browse the repository at this point in the history
* support python 3.13, deprecate 3.9, release note fix

* remove windows and fix linter

---------

Co-authored-by: lkstrp <[email protected]>
  • Loading branch information
fneum and lkstrp authored Jan 2, 2025
1 parent 6910b44 commit 8c9195f
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 25 deletions.
9 changes: 9 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,19 @@ jobs:
run: |
python -m pip install uv
uv pip install --compile --system "$(ls dist/*.whl)[dev]"
- name: Test with pytest
if: matrix.os != 'windows-latest' || matrix.python-version != '3.13'
run: |
coverage run -m pytest . --cache-path=${{ env.CACHE_PATH }} --verbose
coverage xml
- name: Test with pytest (windows & Python 3.13)
if: matrix.os == 'windows-latest' && matrix.python-version == '3.13'
run: |
coverage run -m pytest . --cache-path=${{ env.CACHE_PATH }} --verbose
coverage xml
return 0 # Ignore windows and pytest 3.13
- name: Upload code coverage report
uses: codecov/codecov-action@v5
Expand Down
11 changes: 11 additions & 0 deletions RELEASE_NOTES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ Upcoming Release
To use the features already you have to install the ``master`` branch, e.g.
``pip install git+https://github.com/pypsa/atlite``.

* Added support for Python 3.13 release and dropped support for Python 3.9.
While Python 3.9 still gets security updates until October 2025, core
dependencies of atlite are dropping support for Python 3.9 (e.g. `numpy`) and
active support is only provided for the most recent versions (see `here
<https://endoflife.date/python>`_). It is recommended to upgrade to the latest
Python version if possible. Note that there might be some issues with
Windows and Python 3.13, which are not yet resolved.

* The methods ``convert_cooling_demand`` and ``cooling_demand`` are implemented
to evaluate cooling demand using the cooling degree-days approximation.

* Added support for ``numpy>=2".
Version 0.3.0
Expand Down
4 changes: 2 additions & 2 deletions atlite/convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ def pv(cutout, panel, orientation, tracking=None, clearsky_model=None, **params)
Eurosun (ISES Europe Solar Congress).
"""
if isinstance(panel, (str, Path)):
if isinstance(panel, (str | Path)):
panel = get_solarpanelconfig(panel)
if not callable(orientation):
orientation = get_orientation(orientation)
Expand Down Expand Up @@ -906,7 +906,7 @@ def csp(cutout, installation, technology=None, **params):
URL: https://www.dlr.de/sf/en/desktopdefault.aspx/tabid-11126/19467_read-48251/
"""
if isinstance(installation, (str, Path)):
if isinstance(installation, (str | Path)):
installation = get_cspinstallationconfig(installation)

# Overwrite technology
Expand Down
12 changes: 6 additions & 6 deletions atlite/gis.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def compute_indicatormatrix(orig, dest, orig_crs=4326, dest_crs=4326):
for i, d in enumerate(dest):
for o in tree.query(d):
# STRtree query returns a list of indices for shapely >= v2.0
if isinstance(o, (int, np.integer)):
if isinstance(o, (int | np.integer)):
o = orig[o]
if o.intersects(d):
j = idx[hash(o.wkt)]
Expand Down Expand Up @@ -175,7 +175,7 @@ def compute_intersectionmatrix(orig, dest, orig_crs=4326, dest_crs=4326):
for i, d in enumerate(dest):
for o in tree.query(d):
# STRtree query returns a list of indices for shapely >= v2.0
if isinstance(o, (int, np.integer)):
if isinstance(o, (int | np.integer)):
o = orig[o]
j = idx[hash(o.wkt)]
intersection[i, j] = o.intersects(d)
Expand Down Expand Up @@ -473,7 +473,7 @@ def open_files(self):
"""
for d in self.rasters:
raster = d["raster"]
if isinstance(raster, (str, Path)):
if isinstance(raster, (str | Path)):
raster = rio.open(raster)
else:
assert isinstance(raster, rio.DatasetReader)
Expand All @@ -488,7 +488,7 @@ def open_files(self):

for d in self.geometries:
geometry = d["geometry"]
if isinstance(geometry, (str, Path)):
if isinstance(geometry, (str | Path)):
geometry = gpd.read_file(geometry)
if isinstance(geometry, gpd.GeoDataFrame):
geometry = geometry.geometry
Expand All @@ -505,8 +505,8 @@ def all_closed(self):
"""
Check whether all files in the raster container are closed.
"""
return all(isinstance(d["raster"], (str, Path)) for d in self.rasters) and all(
isinstance(d["geometry"], (str, Path)) for d in self.geometries
return all(isinstance(d["raster"], (str | Path)) for d in self.rasters) and all(
isinstance(d["geometry"], (str | Path)) for d in self.geometries
)

@property
Expand Down
14 changes: 7 additions & 7 deletions atlite/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def get_windturbineconfig(
Config with details on the turbine
"""
assert isinstance(turbine, (str, Path, dict))
assert isinstance(turbine, (str | Path | dict))

if add_cutout_windspeed is False:
msg = (
Expand All @@ -92,7 +92,7 @@ def get_windturbineconfig(
if isinstance(turbine, str) and turbine.startswith("oedb:"):
conf = get_oedb_windturbineconfig(turbine[len("oedb:") :])

elif isinstance(turbine, (str, Path)):
elif isinstance(turbine, (str | Path)):
if isinstance(turbine, str):
turbine_path = windturbines[turbine.replace(".yaml", "")]

Expand Down Expand Up @@ -132,7 +132,7 @@ def get_solarpanelconfig(panel):
Config with details on the solarpanel
"""
assert isinstance(panel, (str, Path))
assert isinstance(panel, (str | Path))

if isinstance(panel, str):
panel_path = solarpanels[panel.replace(".yaml", "")]
Expand Down Expand Up @@ -165,7 +165,7 @@ def get_cspinstallationconfig(installation):
Config with details on the CSP installation.
"""
assert isinstance(installation, (str, Path))
assert isinstance(installation, (str | Path))

if isinstance(installation, str):
installation_path = cspinstallations[installation.replace(".yaml", "")]
Expand Down Expand Up @@ -209,7 +209,7 @@ def get_cspinstallationconfig(installation):
def solarpanel_rated_capacity_per_unit(panel):
# unit is m^2 here

if isinstance(panel, (str, Path)):
if isinstance(panel, (str | Path)):
panel = get_solarpanelconfig(panel)

model = panel.get("model", "huld")
Expand All @@ -223,7 +223,7 @@ def solarpanel_rated_capacity_per_unit(panel):


def windturbine_rated_capacity_per_unit(turbine):
if isinstance(turbine, (str, Path)):
if isinstance(turbine, (str | Path)):
turbine = get_windturbineconfig(turbine)

return turbine["P"]
Expand Down Expand Up @@ -335,7 +335,7 @@ def _validate_turbine_config_dict(
)
raise ValueError(err_msg)

if not all(isinstance(turbine[p], (np.ndarray, list)) for p in ("POW", "V")):
if not all(isinstance(turbine[p], (np.ndarray | list)) for p in ("POW", "V")):
err_msg = "turbine entries 'POW' and 'V' must be np.ndarray or list"
raise ValueError(err_msg)

Expand Down
8 changes: 0 additions & 8 deletions doc/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,3 @@

.. include:: ../RELEASE_NOTES.rst

* In ``atlite/resource.py``, the functions ``get_windturbineconfig``, ``get_solarpanelconfig``, and
``get_cspinstallationconfig`` will now recognize if a local file was passed, and if so load
it instead of one of the predefined ones.

* The option ``capacity_factor_timeseries`` can be selected when creating capacity factors to obtain
the capacity factor of the selected resource per grid cell.

* The methods ``convert_cooling_demand`` and ``cooling_demand`` are implemented to evaluate cooling demand using the cooling degree-days approximation.
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ readme = "README.rst"
authors=[{name = "Contributors to atlite", email = "[email protected]"}]
license = { file = "LICENSE" }
classifiers=[
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Development Status :: 3 - Alpha",
"Environment :: Console",
"Intended Audience :: Science/Research",
Expand All @@ -26,7 +26,7 @@ classifiers=[
"Operating System :: OS Independent",

]
requires-python = ">=3.9"
requires-python = ">=3.10"
dependencies = [
"typing-extensions",
"numpy",
Expand Down

0 comments on commit 8c9195f

Please sign in to comment.