Skip to content

Modernize packaging, CI and PyPI release workflow - #51

Merged
dparrini merged 5 commits into
masterfrom
modernize-packaging
Oct 21, 2026
Merged

dparrini merged 5 commits into
masterfrom
modernize-packaging

Conversation

@dparrini

Copy link
Copy Markdown
Owner

Summary

Packaging now lives in this repository instead of a separate one, and releases are published to PyPI from GitHub Actions.

  • Packaging: pyproject.toml (hatchling) builds the same py3-none-any wheel and sdist that are on PyPI today. The version comes from comtrade.__version__, so copying comtrade.py on its own still works. New optional extras: comtrade[numpy] and comtrade[pandas].
  • Breaking: requires Python >= 3.11 (the currently supported versions; 3.10 reached end of life on 2026-10-01). The version is bumped to 0.2.0. Users on older Pythons keep getting 0.1.2 from pip.
  • Tests: tests/tests.py is renamed to tests/test_comtrade.py and run with pytest. The old python -m unittest tests/tests.py breaks when another tests package is installed.
  • CI (ci.yml, replaces test.yml): ruff, tests on 3.11–3.15 on Ubuntu plus 3.15 on Windows and macOS, and a build + twine check + wheel smoke test. Actions are pinned to commit SHAs, and Dependabot keeps them up to date.
  • Release (release.yml): publishing a GitHub Release runs CI, checks that the tag matches __version__, then uploads to PyPI via Trusted Publishing, with no API token.
  • Small ruff fixes: an unused variable, an unused import, and type(x) == bytes changed to is bytes. No behaviour change.

Before the first release

Add a trusted publisher at https://pypi.org/manage/project/comtrade/settings/publishing/ → GitHub:

Field Value
Owner dparrini
Repository python-comtrade
Workflow release.yml
Environment pypi

After merging, run gh release create 0.2.0 --generate-notes.

Testing

Run locally on Windows:

  • 128 tests pass on every Python from 3.9 to 3.15. Python 3.10 is now refused by requires-python.
  • uv build, twine check --strict, and a check of the wheel's contents and metadata.
  • actionlint and zizmor on the workflows.
  • load_as_dataframe checked by hand against pandas 3.0.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EPnfFrvYTuVEM9uDp81XiD

dparrini and others added 2 commits October 21, 2026 12:51
- Add pyproject.toml (hatchling) so the package is built from this
  repository; the version is read from comtrade.__version__
- Add numpy and pandas extras
- Require Python >= 3.11 (the currently supported versions), bump to 0.2.0
- Rename tests/tests.py to tests/test_comtrade.py and run it with pytest
- Replace the test workflow with CI: ruff, tests on Python 3.11-3.15
  (plus Windows and macOS) and a build/twine check
- Add a release workflow that publishes to PyPI via Trusted Publishing
- Add Dependabot for GitHub Actions updates
- Fix ruff findings (unused variables/import, type comparison)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EPnfFrvYTuVEM9uDp81XiD
- Compute sample times across multiple sample rate segments: each
  segment continues from the last sample of the previous one, instead
  of (n - 1) / samp with the segment's own rate (see #45)
- Accept a blank (non-critical) timestamp in ASCII DAT files and
  compute it from the sample rate (#48)
- Fix loading binary DAT files with status channels only (#49)
- Add Comtrade.analog_time with each analog channel's time plus its
  time skew (#29)
- Read ASCII DAT files in blocks and unpack binary DAT fields for all
  rows at once (numpy is used when use_numpy_arrays is set), replacing
  the struct row-by-row reader
- Update README supported features table and add tests

Fixes #48, fixes #49, fixes #29

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VXtokXPfpX3vJri639eqXo
dparrini and others added 3 commits October 21, 2026 14:05
- Compute sample times across multiple sample rate segments: each
  segment continues from the last sample of the previous one, instead
  of (n - 1) / samp with the segment's own rate (see #45)
- Accept a blank (non-critical) timestamp in ASCII DAT files and
  compute it from the sample rate (#48)
- Fix loading binary DAT files with status channels only (#49)
- Add Comtrade.analog_time with each analog channel's time plus its
  time skew (#29)
- Update README supported features table and add tests

Fixes #48, fixes #49, fixes #29

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VXtokXPfpX3vJri639eqXo
- Unpack each binary DAT field (sample number, timestamp, analog
  channel, 16-bit status group) for all rows at once with strided byte
  slices, replacing the struct row-by-row reader
- Scale binary analog values and extract status bits with numpy when
  use_numpy_arrays is set
- Read ASCII DAT files in blocks of lines (up to 1M values), converting
  each channel of a block at once
- Binary DAT files ending in a partial row load their whole rows
  instead of failing with struct.error
- Add tests for ASCII block reading, DAT files with more or fewer rows
  than the CFG samples and numpy arrays reading

Loading the issue's sample (ASCII, 2212 analog channels, 10000
samples) drops from 3.6 s to 2.0 s. Binary files with 2212 channels
load about 2x faster, and 5.5 to 10x faster with use_numpy_arrays.

Fixes #24

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XUdNv59jhgaaRKFfZmRMwQ
@dparrini
dparrini merged commit 08bc997 into master Oct 21, 2026
36 checks passed
@dparrini
dparrini deleted the modernize-packaging branch October 21, 2026 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant