Releases: questrail/sdfascii
Releases · questrail/sdfascii
Release list
v0.9.0
Added
- Continuous integration on GitHub Actions, replacing a
.travis.ymlthat
pointed at travis-ci.org and had not run in years. Every push and pull
request lints, checks formatting, type checks, and runs the suite on 3.12,
3.13, and 3.14, the versions the classifiers claim. A second job installs
the oldest numpypyproject.tomlallows, so the floor is a tested promise
rather than a hopeful one. A third audits the workflows with zizmor,
since they are the part of the repository that can mint a PyPI credential.
Coverage goes to Coveralls from the 3.13 leg. - Releases publish from a tag rather than from a laptop.
just release
refuses a dirty tree, a branch other thanmaster, amasterbehind its
upstream, an empty Unreleased section, or an existing tag; then lints and
tests; then shows the entries waiting to ship beside the version each kind
of bump would produce, and asks which to cut. It bumps the version, closes
out the CHANGELOG, commits, and tags. Pushing the tag is what publishes.
just release-checkruns the refusals on their own. - The release workflow waits on the whole CI run before it uploads anything,
confirms the tag sits onmasterand matches the version in
pyproject.toml, and authenticates to PyPI with trusted publishing, so
there is no API token to paste, store, or leak. It signs a PEP 740
attestation for each distribution against the same identity, and creates a
GitHub release carrying the CHANGELOG section for that version as its notes. - Dependabot keeps the pinned actions and the lock file moving. The actions in
both workflows are pinned to commit SHAs, so a fix published upstream does
not reach this repository the way it would behind a moving tag; without
something to move them, pinning would amount to staying on one commit
forever. It readspyproject.tomlanduv.locktogether as well, so a
dependency update arrives as a lock file change that CI checks with
uv sync --locked. scripts/smoke_test_wheel.py, which installs the built wheel wheresrc/
cannot be reached and checks the version,__version__, every name in
__all__,__main__.py, andpy.typed. Every other check runs against the
source tree, so this is the only one that can catch a packaging mistake.
just buildruns it after building.just cov, which runs the suite under coverage and writes both a terminal
summary andhtmlcov/, and thepytest-covit needs. A floor of 88%, what
the suite covers today, means uncovered code has to arrive with either a
test or a deliberate edit to that line.- Tests for the command line entry point, which had none: one that parses a
real SDF file to JSON and reads the result back, and one that pins the
refusal recorded below. py.typed, so that the type hints already written reach anyone installing
the package. Without the marker a type checker treats an installed package
as untyped and ignores its annotations.SDF_REVISION_1,SDF_REVISION_2, andSDF_REVISION_3, naming the three
values thesdf_revisionfield of a file header is compared against, beside
the record type constants that were already named.
Fixed
_decode_sdf_data_hdr()never boundtemp_data_hdron the revision 3
branch, so decoding a revision 3 data header raisedUnboundLocalErrorfrom
thereturnbelow rather than giving back the fields the revisions share.
The file and measurement header decoders beside it both cast to their V3
type; this one was the odd one out, in the branch and in the return
annotation. Found by pyright.read_sdf_file()raisedUnboundLocalErroron a file whose header reports
no y-data record. Every assignment tosdf_datasat inside the branch that
a negativeoffset_ydata_recordskips, so the guard written to let those
files through was the one thing that could not survive the return. It now
returnsNonefor the data, with the header decoded as before.read_ascii_files()reached numpy's record array constructor through
np.core, which numpy 2.0 renamed tonp._coreand left behind as a shim
that warns on every attribute access. It usesnp.rec, the supported
spelling.- The
zip()calls that pair a struct format string with the field names
beside it passstrict=True, so a format string and a key list that fall
out of step raise rather than silently producing a short dictionary.
Changed
- Moved to uv and a
pyproject.tomlbuilt by hatchling, replacing
setup.py,setup.cfg,requirements.txt, andMANIFEST.in. The sdist
names what it ships rather than taking hatchling's default of everything
.gitignoredoes not exclude, and leaves outPIC3KHZ.JPG, a 2.7 MB
photograph of the bench that is 99% of what the sdist would otherwise weigh
and that nothing in the suite reads. - Replaced the Invoke
tasks.pywith a justJustfile, matching the
recipes and groups used by the other questrail projects. Theexample1and
example2tasks become onejust examplesrecipe that regenerates both
files. - Swapped the tooling: ruff for pep8/pep8-naming, pytest for nose2, and
pyright for mypy. The code was reformatted by ruff, and theDictand
Unionannotations were rewritten in the built-in spellings. - Moved the module to a src layout at
src/sdfascii/__init__.py, and the
block that used to sit underif __name__ == "__main__":at the foot of it
tosrc/sdfascii/__main__.py. Under a package nothing would ever have
reached that block;python -m sdfasciiruns it now.import sdfasciiand
everything reached through it are unchanged. python -m sdfascii ascii ...is refused rather than accepted.asciiwas
a documented choice whose body was never written: a run named the file type,
passed the arguments, wrote nothing, and exited 0. Naming the one implemented
choice turns that silence into an argparse error.- The version is written in
pyproject.tomlrather than in the module, and
sdfascii.__version__now reads it back from the installed distribution
metadata. Its value is unchanged and every caller keeps working. The version
had to move foruv versionto be able to read or bump it, which is what the
release recipe is built on; uv refuses a project whose version is dynamic. - List
369937+matthewrankin@users.noreply.github.comas the author address in
pyproject.toml, replacing a work address. It is whatAuthor-emailcarries
in the built metadata and what PyPI shows on the project page, so it changes
there from the next release onward. - The license is declared as an SPDX expression with
license-files, which is
what replaced theLicense ::classifier that used to carry it. It is also
what putsLICENSE.txtintodist-info/licenses/. .python-versionis tracked, so that a contributor'suv syncbuilds
against the interpreter the release is built on rather than whatever uv
happens to find.- Every heading in this file carries an ISO date. The release workflow reads
the section for the version it is publishing out of this file and matches on
that shape, and half the headings were written18-Aug-23. - Raised the minimum Python to 3.12 and numpy to 2.2, and dropped the 3.8
through 3.11 classifiers.
Removed
AUTHORS.md, along with the pointer to it in the copyright notice. It listed
one author, no maintainers, and no contributors, and it does not travel in
the wheel:license-filescarriesLICENSE.txtintodist-info/licenses/
and nothing carries the other.git logis the record.invoke release --deploy, which tagged, pushed, built, and uploaded from a
laptop with whatever credentials were lying around, printing a checklist of
questions to answer from memory first. The release workflow replaces it.mypy.iniandunittest.cfg, whose tools are gone.- The Python 2 era
.pycfiles,sdfascii.egg-info/, and the stale
__pycache__directories that had been sitting in the working tree. One of
them, asdfascii.pyccompiled by Python 3.4, shadowed the package and made
the suite fail to import it.