Skip to content

Commit

Permalink
Merge pull request #3223 from dopplershift/support-3.12
Browse files Browse the repository at this point in the history
Support Python 3.12
  • Loading branch information
dcamron authored Nov 6, 2023
2 parents 3b23de0 + 84ccdb5 commit 17d915f
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 35 deletions.
11 changes: 8 additions & 3 deletions .github/actions/install-pypi/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ inputs:
python-version:
description: 'What version of Python to use'
required: true
old-build:
description: 'Whether to enable old builds for shapely and cartopy'
required: false
default: 'false'

runs:
using: composite
Expand All @@ -30,13 +34,13 @@ runs:
ci/extra_requirements.txt
# This installs the stuff needed to build and install Shapely and CartoPy from source.
- name: Install CartoPy build dependencies
if: ${{ inputs.need-extras == 'true' }}
- name: Install CartoPy/Shapely build dependencies
if: ${{ inputs.old-build == 'true' }}
shell: bash
run: sudo apt-get install libgeos-dev

- name: Disable Shapely Wheels
if: ${{ inputs.need-extras == 'true' }}
if: ${{ inputs.old-build == 'true' }}
shell: bash
run: echo "PIP_NO_BINARY=shapely" >> $GITHUB_ENV

Expand All @@ -57,6 +61,7 @@ runs:
-c ci/${{ inputs.version-file }} -c ci/${{ inputs.type }}_requirements.txt -c ci/extra_requirements.txt
- name: Install additional test tools
if: ${{ inputs.type == 'test' }}
shell: bash
run: >
python -m pip install coverage
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/docs-conda.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ jobs:
os: Windows
- python-version: 3.11
os: macOS
- python-version: 3.12
os: macOS

steps:
- name: Checkout source
Expand Down
14 changes: 5 additions & 9 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,16 @@ jobs:
# Build our docs on Linux against multiple Pythons
#
Docs:
name: ${{ matrix.python-version }} ${{ matrix.dep-versions }}
name: "Linux ${{ matrix.python-version }}"
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: [3.9, '3.10', 3.11]
check-links: [false]
include:
- python-version: 3.9
check-links: false
dep-versions: requirements.txt
- python-version: '3.10'
check-links: false
dep-versions: requirements.txt
- python-version: 3.11
- python-version: 3.12
check-links: true
dep-versions: requirements.txt
outputs:
doc-version: ${{ steps.build-docs.outputs.doc-version }}

Expand All @@ -52,6 +47,7 @@ jobs:
with:
type: 'doc'
python-version: ${{ matrix.python-version }}
need-extras: true

- name: Build docs
id: build-docs
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/nightly-builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ on:
- main
paths:
- .github/workflows/nightly-builds.yml
- .github/workflows/unstable-builds.yml
pull_request:
paths:
- .github/workflows/nightly-builds.yml
- .github/workflows/unstable-builds.yml

jobs:
Builds:
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/tests-conda.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,13 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.9, '3.10', 3.11]
python-version: [3.9, 3.12]
os: [macOS, Windows]
include:
- python-version: '3.10'
os: macOS
- python-version: 3.11
os: Windows

steps:
- name: Checkout source
Expand Down Expand Up @@ -66,3 +71,4 @@ jobs:
uses: codecov/codecov-action@v3
with:
name: ${{ github.workflow }}
fail_ci_if_error: true
7 changes: 5 additions & 2 deletions .github/workflows/tests-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.9, '3.10', 3.11]
python-version: [3.9, '3.10', 3.11, 3.12]
dep-versions: [Latest]
no-extras: ['']
include:
Expand All @@ -34,7 +34,8 @@ jobs:
- python-version: 3.9
dep-versions: Minimum
no-extras: 'No Extras'
- python-version: 3.11
- python-version: 3.12
dep-versions: Latest
no-extras: 'No Extras'

steps:
Expand Down Expand Up @@ -71,6 +72,7 @@ jobs:
need-extras: ${{ matrix.no-extras != 'No Extras' }}
type: 'test'
python-version: ${{ matrix.python-version }}
old-build: ${{ matrix.no-extras != 'No Extras' && matrix.dep-versions == 'Minimum' }}

- name: Run tests
uses: ./.github/actions/run-tests
Expand All @@ -94,3 +96,4 @@ jobs:
uses: codecov/codecov-action@v3
with:
name: ${{ github.workflow }}
fail_ci_if_error: true
4 changes: 2 additions & 2 deletions .github/workflows/unstable-builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
need-extras: true
type: test
version-file: Prerelease
python-version: 3.11
python-version: 3.12

- name: Run tests
id: tests
Expand Down Expand Up @@ -72,7 +72,7 @@ jobs:
with:
type: doc
version-file: Prerelease
python-version: 3.11
python-version: 3.12

- name: Build docs
id: build
Expand Down
9 changes: 4 additions & 5 deletions docs/api/references.rst
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,10 @@ References
.. [WMO8] WMO, 2020: Guide to Meteorological Instruments and Methods of Observation,
Volume 1: Measurement of Meteorological Variables.
`WMO No.8 <https://library.wmo.int/index.php?lvl=notice_display&id=12407>`_.
`WMO No.8 <https://library.wmo.int/idurl/4/41650>`_.
.. [WMO306] WMO, 2011: Manual on Codes - International Codes, Volume I.1, Annex II to the WMO
Technical Regulations: Part A - Alphanumeric Codes. `WMO No.306
<https://library.wmo.int/index.php?lvl=notice_display&id=13617>`_.
Technical Regulations: Part A - Alphanumeric Codes. `WMO No.306 <https://library.wmo.int/idurl/4/35713>`_.
.. [WMO1966] WMO, 1966: International Meteorological Tables, `WMO-No. 188.TP.94
<https://library.wmo.int/doc_num.php?explnum_id=7997>`_.
.. [WMO1966] WMO, 1966: International Meteorological Tables,
`WMO-No. 188.TP.94 <https://library.wmo.int/idurl/4/59923>`_.
12 changes: 8 additions & 4 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,9 @@
'reset_modules': [lambda conf, fname: sys.modules.pop('pint', None)]
}

# By default, only generate all the areas when running in CI
metpy_generate_all_areas = 'GITHUB_ACTIONS' in os.environ
# By default, only generate all the areas when running on a release CI job
metpy_generate_all_areas = (not os.environ.get('GITHUB_REF', '').startswith('refs/pull')
and sys.version_info < (3, 12))

# Turn off code and image links for embedded mpl plots
plot_html_show_source_link = False
Expand Down Expand Up @@ -431,7 +432,9 @@
r'https://doi\.org/10\.1289/ehp\.1206273',
# Couldn't fix these 403's with user agents
r'https://doi\.org/10\.1029/2010GL045777',
r'https://doi\.org/10\.1098/rspa\.2004\.1430'
r'https://doi\.org/10\.1098/rspa\.2004\.1430',
# Currently giving certificate errors on GitHub
r'https://library.wmo.int/.*'
]

# Dictionary of URL redirects allowed
Expand All @@ -440,7 +443,8 @@
r'https://conda.io/docs/': r'https://conda.io/en/latest/',
r'https://github.com/Unidata/MetPy/issues/new/choose': r'https://github.com/login.*choose',
r'https://doi.org/.*': r'https://.*',
r'https://gitter.im/Unidata/MetPy': r'https://app.gitter.im/.*MetPy.*'
r'https://gitter.im/Unidata/MetPy': r'https://app.gitter.im/.*MetPy.*',
r'https://library.wmo.int/idurl/.*': r'https://library.wmo.int/.*'
}

# Domain-specific HTTP headers for requests
Expand Down
2 changes: 2 additions & 0 deletions docs/make_areas.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def generate_area_file(app):
if area in states_provinces:
code = textwrap.dedent(f"""
.. plot::
:context: reset
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
Expand All @@ -75,6 +76,7 @@ def generate_area_file(app):
else:
code = textwrap.dedent(f"""
.. plot::
:context: reset
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ classifiers = [
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Scientific/Engineering",
"Topic :: Scientific/Engineering :: Atmospheric Science",
"Intended Audience :: Science/Research",
Expand Down
28 changes: 19 additions & 9 deletions src/metpy/io/_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def open_as_needed(filename, mode='rb'):
return open(filename, mode, **kwargs) # noqa: SIM115


class NamedStruct(Struct):
class NamedStruct:
"""Parse bytes using :class:`Struct` but provide named fields."""

def __init__(self, info, prefmt='', tuple_name=None):
Expand All @@ -73,7 +73,12 @@ def __init__(self, info, prefmt='', tuple_name=None):
elif not i[0]: # Skip items with no name
conv_off += 1
self._tuple = namedtuple(tuple_name, ' '.join(n for n in names if n))
super().__init__(prefmt + ''.join(f for f in fmts if f))
self._struct = Struct(prefmt + ''.join(f for f in fmts if f))

@property
def size(self):
"""Return the size of the struct in bytes."""
return self._struct.size

def _create(self, items):
if self.converters:
Expand All @@ -90,11 +95,11 @@ def make_tuple(self, *args, **kwargs):

def unpack(self, s):
"""Parse bytes and return a namedtuple."""
return self._create(super().unpack(s))
return self._create(self._struct.unpack(s))

def unpack_from(self, buff, offset=0):
"""Read bytes from a buffer and return as a namedtuple."""
return self._create(super().unpack_from(buff, offset))
return self._create(self._struct.unpack_from(buff, offset))

def unpack_file(self, fobj):
"""Unpack the next bytes from a file object."""
Expand All @@ -103,12 +108,12 @@ def unpack_file(self, fobj):
def pack(self, **kwargs):
"""Pack the arguments into bytes using the structure."""
t = self.make_tuple(**kwargs)
return super().pack(*t)
return self._struct.pack(*t)


# This works around times when we have more than 255 items and can't use
# NamedStruct. This is a CPython limit for arguments.
class DictStruct(Struct):
class DictStruct:
"""Parse bytes using :class:`Struct` but provide named fields using dictionary access."""

def __init__(self, info, prefmt=''):
Expand All @@ -118,18 +123,23 @@ def __init__(self, info, prefmt=''):
# Remove empty names
self._names = [n for n in names if n]

super().__init__(prefmt + ''.join(f for f in formats if f))
self._struct = Struct(prefmt + ''.join(f for f in formats if f))

@property
def size(self):
"""Return the size of the struct in bytes."""
return self._struct.size

def _create(self, items):
return dict(zip(self._names, items))

def unpack(self, s):
"""Parse bytes and return a dict."""
return self._create(super().unpack(s))
return self._create(self._struct.unpack(s))

def unpack_from(self, buff, offset=0):
"""Unpack the next bytes from a file object."""
return self._create(super().unpack_from(buff, offset))
return self._create(self._struct.unpack_from(buff, offset))


class Enum:
Expand Down

0 comments on commit 17d915f

Please sign in to comment.