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

Update for python 3.12 and linting #9

Merged
merged 3 commits into from
Feb 29, 2024
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
4 changes: 2 additions & 2 deletions .github/workflows/linting.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ jobs:
name: Flake8
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Set up Python 3
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: 3.x

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: [ 3.8, 3.9, '3.10', '3.11' ]
python-version: [ 3.9, '3.10', 3.11, 3.12 ]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

Expand Down
1 change: 1 addition & 0 deletions ci/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
numpy
pandas>=2.0.0
pyproj
setuptools; python_version >= '3.12'
xarray
27 changes: 12 additions & 15 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ authors = [
readme = 'README.md'
license = {file = 'LICENSE'}
dynamic = ['version']
requires-python = '>=3.8'
requires-python = '>=3.9'
dependencies = [
'numpy',
'pandas',
Expand All @@ -18,32 +18,23 @@ dependencies = [
[project.optional-dependencies]
lint = [
'flake8',
'ruff',
'pycodestyle',
'pyflakes',
'flake8-bugbear',
'flake8-builtins',
'flake8-comprehensions',
'flake8-continuation',
'flake8-copyright',
'flake8-isort',
'isort',
'flake8-mutable',
'flake8-pie',
'flake8-print',
'flake8-quotes',
'flake8-requirements',
'flake8-simplify',
'flake8-docstrings',
'pep8-naming',
'pydocstyle',
'pydocstyle'
]
test = [
'pytest',
]

[build-system]
requires = ['setuptools']
build-backend = "setuptools.build_meta"
build-backend = 'setuptools.build_meta'

[project.urls]
homepage = 'https://github.com/nawendt/gempakio'
Expand All @@ -64,13 +55,19 @@ combine_star = true
[tool.ruff]
line-length = 95
exclude = ['examples']
select = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'I', 'N', 'Q', 'R', 'S', 'T', 'U', 'W']
select = ['A', 'B', 'C', 'CPY001', 'D', 'E', 'E226', 'F', 'G', 'I', 'N', 'NPY', 'Q', 'R', 'S', 'SIM', 'T', 'U', 'W']
ignore = ['F405', 'I001', 'RET504', 'RET505', 'RET506', 'RET507', 'RUF100']
preview = true
explicit-preview-rules = true

[tool.ruff.per-file-ignores]
'src/gempakio/__init__.py' = ['F401']
'tests/*.py' = ['S101']

[tool.ruff.lint.flake8-copyright]
notice-rgx = '(?i)Copyright\s+(\(C\)\s+)?\d{4}'
author = 'Nathan Wendt'

[tool.ruff.flake8-quotes]
inline-quotes = 'single'
multiline-quotes = 'double'
Expand All @@ -87,7 +84,7 @@ combine-as-imports = true
max-complexity = 61

[tool.ruff.pydocstyle]
convention = "numpy"
convention = 'numpy'

[tool.setuptools]
zip-safe = true
Expand Down
23 changes: 7 additions & 16 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ zip_safe = True
package_dir=
=src
packages=find:
python_requires = >=3.8
python_requires = >=3.9
setup_requires =
setuptools
install_requires =
Expand All @@ -30,40 +30,31 @@ where = src
[options.extras_require]
line =
flake8
ruff
pycodestyle
pyflakes
flake8-bugbear
flake8-builtins
flake8-comprehensions
flake8-continuation
flake8-copyright
flake8-isort
isort
flake8-mutable
flake8-pie
flake8-print
flake8-quotes
flake8-requirements
flake8-simplify
flake8-docstrings
pep8-naming
pydocstyle
test =
pytest

[pycodestyle]
ignore = W503
max-line-length = 95

[flake8]
max-line-length = 95
application-import-names = gempakio
import-order-style = google
copyright-check = True
copyright-author = Nathan Wendt
inline-quotes = single
multiline-quotes = double
docstring-convention = numpy
select = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z B902
select = E301 E302 E303 E304 E305 E306 I R
ignore = F405 W503 RST902 SIM106
per-file-ignores =
__init__.py:F401
exclude =
examples/*.py

4 changes: 2 additions & 2 deletions src/gempakio/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Copyright (c) 2023 Nathan Wendt.
# Copyright (c) 2024 Nathan Wendt.
# Distributed under the terms of the BSD 3-Clause License.
# SPDX-License-Identifier: BSD-3-Clause
"""gempakIO."""

from gempakio.decode.gempak import GempakGrid, GempakSounding, GempakSurface
from gempakio.encode.gempak import GridFile, SoundingFile, SurfaceFile

__version__ = '1.0.0'
__version__ = '1.0.1'
25 changes: 8 additions & 17 deletions src/gempakio/decode/gempak.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2023 Nathan Wendt.
# Copyright (c) 2024 Nathan Wendt.
# Distributed under the terms of the BSD 3-Clause License.
# SPDX-License-Identifier: BSD-3-Clause
"""Classes for decoding various GEMPAK file formats."""
Expand Down Expand Up @@ -386,10 +386,7 @@ def _fortran_ishift(i, shift):
if shift > 0:
shifted = ctypes.c_int32(i << shift).value
elif shift < 0:
if i < 0:
shifted = (i & mask) >> abs(shift)
else:
shifted = i >> abs(shift)
shifted = (i & mask) >> abs(shift) if i < 0 else i >> abs(shift)
elif shift == 0:
shifted = i
else:
Expand Down Expand Up @@ -1944,10 +1941,7 @@ def snxarray(self, station_id=None, station_number=None,

sndno = [(s.DTNO, s.SNDNO) for s in matched]

if self.merged:
data = self._unpack_merged(sndno)
else:
data = self._unpack_unmerged(sndno)
data = self._unpack_merged(sndno) if self.merged else self._unpack_unmerged(sndno)

soundings = []
for snd in data:
Expand Down Expand Up @@ -2395,12 +2389,9 @@ def _process_report_text(report, values):
for param, txt in zip(['TEXT', 'SPCL'], [text, spcl]):
if txt:
station = METAR_STATION_RE.search(txt)
if station is None:
# If no station can be parsed, at least ensure the text
# will be kept with the report we return.
stnstr = '----'
else:
stnstr = station.groupdict()['station']
# If no station can be parsed, at least ensure the text
# will be kept with the report we return.
stnstr = '----' if station is None else station.groupdict()['station']

if txt.count(stnstr) > 1:
# GEMPAK sometimes has more than one text report attached. We can
Expand Down Expand Up @@ -2530,12 +2521,12 @@ def nearest_time(self, date_time, station_id=None, station_number=None, state=No
if country:
station_id = set()
for cty in country:
station_id.update(stn.ID for stn in self._sfinfo if stn.COUNTRY == cty)
station_id.update(stn.ID for stn in self._sfinfo if cty == stn.COUNTRY)

if state:
station_id = set()
for st in state:
station_id.update(stn.ID for stn in self._sfinfo if stn.STATE == st)
station_id.update(stn.ID for stn in self._sfinfo if st == stn.STATE)

time_matched = []
if station_id:
Expand Down
17 changes: 4 additions & 13 deletions src/gempakio/encode/gempak.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2023 Nathan Wendt.
# Copyright (c) 2024 Nathan Wendt.
# Distributed under the terms of the BSD 3-Clause License.
# SPDX-License-Identifier: BSD-3-Clause
"""Classes for encoding various GEMPAK file formats."""
Expand Down Expand Up @@ -138,10 +138,7 @@ def _fortran_ishift(i, shift):
if shift > 0:
shifted = ctypes.c_int32(i << shift).value
elif shift < 0:
if i < 0:
shifted = (i & mask) >> abs(shift)
else:
shifted = i >> abs(shift)
shifted = (i & mask) >> abs(shift) if i < 0 else i >> abs(shift)
elif shift == 0:
shifted = i
else:
Expand Down Expand Up @@ -720,15 +717,9 @@ def _pack_grib(self, grid, nbits=16):

out = np.zeros(lendat, dtype=np.int32)

if (grid == self._missing_float).any():
has_missing = True
else:
has_missing = False
has_missing = bool((grid == self._missing_float).any())

if (grid == self._missing_float).all():
all_missing = True
else:
all_missing = False
all_missing = bool((grid == self._missing_float).all())

if all_missing:
qmin = self._missing_float
Expand Down
12 changes: 3 additions & 9 deletions src/gempakio/gemcalc.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2021 Nathan Wendt.
# Copyright (c) 2024 Nathan Wendt.
# Distributed under the terms of the BSD 3-Clause License.
# SPDX-License-Identifier: BSD-3-Clause
"""GEMPAK calculations."""
Expand Down Expand Up @@ -359,10 +359,7 @@ def mixing_ratio(dwpc, pres, missing=-9999):
else:
corr = (1.001 + ((pres - 100.) / 900.) * 0.0034)
e = corr * vapr
if e > (0.5 * pres):
mixr = missing
else:
mixr = 0.62197 * (e / (pres - e)) * 1000.
mixr = missing if e > 0.5 * pres else 0.62197 * (e / (pres - e)) * 1000.0
return mixr


Expand Down Expand Up @@ -472,10 +469,7 @@ def vapor_pressure(dwpc, missing=-9999):
-----
See GEMPAK function PR_VAPR
"""
if dwpc == missing:
vapr = missing
else:
vapr = 6.112 * np.exp((17.67 * dwpc) / (dwpc + 243.5))
vapr = missing if dwpc == missing else 6.112 * np.exp(17.67 * dwpc / (dwpc + 243.5))
return vapr


Expand Down
19 changes: 12 additions & 7 deletions src/gempakio/tools.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Copyright (c) 2024 Nathan Wendt.
# Copyright (c) 2009,2016,2019 MetPy Developers.
# Copyright (c) 2021 Nathan Wendt.
# Distributed under the terms of the BSD 3-Clause License.
# SPDX-License-Identifier: BSD-3-Clause
"""Tools for reading GEMPAK files."""
Expand All @@ -10,8 +10,8 @@
import numpy as np


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

Class from MetPy.
"""
Expand All @@ -29,7 +29,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.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 @@ -46,11 +51,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 @@ -59,7 +64,7 @@ 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)


class IOBuffer:
Expand Down
6 changes: 3 additions & 3 deletions tests/test_surface_encode.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2023 Nathan Wendt.
# Copyright (c) 2024 Nathan Wendt.
# Distributed under the terms of the BSD 3-Clause License.
# SPDX-License-Identifier: BSD-3-Clause
"""Tests for encoding GEMPAK sounding files."""
Expand Down Expand Up @@ -56,9 +56,9 @@ def test_surface_write():
test_obj = in_sfc.sfjson()

for ob1, ob2 in zip(sfc_obj, test_obj):
for prop in ob1['properties'].keys():
for prop in ob1['properties']:
assert ob1['properties'][prop] == ob2['properties'][prop]
for param in ob1['values'].keys():
for param in ob1['values']:
assert ob1['values'][param] == ob2['values'][param]
finally:
gem.unlink()