Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support python 3.13, deprecate 3.9, release note fix #418

Merged
merged 3 commits into from
Jan 2, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
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 @@
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 @@
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 @@
Config with details on the CSP installation.

"""
assert isinstance(installation, (str, Path))
assert isinstance(installation, (str | Path))

Check warning on line 168 in atlite/resource.py

View check run for this annotation

Codecov / codecov/patch

atlite/resource.py#L168

Added line #L168 was not covered by tests

if isinstance(installation, str):
installation_path = cspinstallations[installation.replace(".yaml", "")]
Expand Down Expand Up @@ -209,7 +209,7 @@
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 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 @@
)
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
Loading