mirror of
https://git.pumpin.online/funkpower/typikon.git
synced 2026-10-22 18:57:13 +00:00
fix what a 1.0 would have welded into PyPI metadata
An adversarial review of the release, and four of its findings were things
PyPI never lets you replace once uploaded.
- rust-version said 1.74. clap has needed 1.85 since 4.6, and cargo
hard-errors rather than warning, so the sdist advertised a floor it could
not build on. docs/releasing.md sends macOS and Windows users to that
sdist.
- The wheel was classified Development Status :: 4 - Beta on a release the
changelog calls stable, with none of the Python version classifiers PyPI
indexes on.
- Six README links were relative. PyPI resolves them against the project
page, so every one 404'd there, as they do on the live 0.2.0 page now.
- in that order packs the wheel into the
sdist. The tarball on disk was 431KB with an x86-64 binary inside it.
Also: twine upload gains --skip-existing, so a retry after a partial upload
finishes rather than dying on a version that cannot be reused; twine check
gains the renderer that makes it parse the description at all, without which
it returns None and reports PASSED; and the README no longer claims a
twenty-year sweep the test did not run, because 366 * 21 / 4 is five years.
The test now runs the twenty-one it was named for.
The crates.io name belongs to an unrelated project, which the README now says
rather than leaving a reader to find out from cargo.
This commit is contained in:
@@ -39,7 +39,10 @@ jobs:
|
||||
run: |
|
||||
apt-get update && apt-get install -y --no-install-recommends python3 python3-venv
|
||||
python3 -m venv /tmp/venv
|
||||
/tmp/venv/bin/pip install --quiet 'maturin[zig]' twine
|
||||
# readme-renderer[md] is what makes `twine check` actually parse the
|
||||
# long description. Without it the render returns None and the
|
||||
# check reports PASSED regardless, even with --strict.
|
||||
/tmp/venv/bin/pip install --quiet 'maturin[zig]' twine 'readme-renderer[md]'
|
||||
# --zig cross-compiles against an older glibc than this image ships, so
|
||||
# the wheel is not silently pinned to bookworm's.
|
||||
for target in x86_64-unknown-linux-gnu aarch64-unknown-linux-gnu; do
|
||||
@@ -60,5 +63,8 @@ jobs:
|
||||
TWINE_USERNAME: __token__
|
||||
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
|
||||
run: |
|
||||
/tmp/venv/bin/twine check dist/*
|
||||
/tmp/venv/bin/twine upload --non-interactive dist/*
|
||||
/tmp/venv/bin/twine check --strict dist/*
|
||||
# --skip-existing so a retry after a partial upload finishes the job
|
||||
# instead of dying on the first file. A version cannot be reused,
|
||||
# so a half-published release would otherwise burn it.
|
||||
/tmp/venv/bin/twine upload --non-interactive --skip-existing dist/*
|
||||
|
||||
@@ -3,3 +3,5 @@
|
||||
.venv/
|
||||
*.egg-info/
|
||||
/dist
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
@@ -49,6 +49,16 @@ Everything below changes what a day reports against pre-1.0 versions.
|
||||
- `--set-default` remembers the tradition and the discipline alongside the
|
||||
jurisdiction.
|
||||
|
||||
### Packaging
|
||||
|
||||
- Requires Rust 1.85, which is what the dependency tree has needed since clap
|
||||
4.6. `rust-version` had said 1.74, so the source distribution claimed to
|
||||
build on toolchains where cargo refuses outright.
|
||||
- Classified as production/stable, with the Python version and platform
|
||||
classifiers PyPI indexes on, and Changelog, Documentation and Issues links.
|
||||
- README links are absolute, because PyPI does not resolve relative ones and
|
||||
every one of them 404'd on the project page.
|
||||
|
||||
### Changed
|
||||
|
||||
- Rewritten in Rust. It ships as one static binary with the menologion compiled
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
name = "typikon"
|
||||
version = "1.0.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.74"
|
||||
rust-version = "1.85"
|
||||
description = "The Orthodox liturgical day: feasts, seasons and the fast, computed rather than fetched"
|
||||
license = "GPL-2.0-only"
|
||||
repository = "https://git.pumpin.online/funkpower/typikon"
|
||||
|
||||
@@ -45,6 +45,10 @@ One static binary, no runtime to install first.
|
||||
$ cargo install --git https://git.pumpin.online/funkpower/typikon
|
||||
```
|
||||
|
||||
Rust 1.85 or newer. The name `typikon` on crates.io belongs to an unrelated
|
||||
project, so `cargo install typikon` and a `typikon = "1"` dependency will not
|
||||
get you this; install and depend on it by git URL.
|
||||
|
||||
Or build it from a checkout:
|
||||
|
||||
```console
|
||||
@@ -63,7 +67,9 @@ $ pip install typikon
|
||||
```
|
||||
|
||||
The menologion is compiled into that too, so it carries no data files and needs
|
||||
no network either.
|
||||
no network either. Wheels are built for Linux on x86-64 and aarch64; everywhere
|
||||
else pip falls back to the source distribution, which needs a Rust toolchain of
|
||||
1.85 or newer on the installing machine.
|
||||
|
||||
## Which calendar?
|
||||
|
||||
@@ -176,7 +182,7 @@ will want.
|
||||
|
||||
Ten of the fourteen Byzantine-rite Eastern Catholic churches have no entry of
|
||||
their own. Each keeps one of the three reckonings, and
|
||||
[docs/calendars.md](docs/calendars.md) sets out which questions decide it.
|
||||
[docs/calendars.md](https://git.pumpin.online/funkpower/typikon/src/branch/main/docs/calendars.md) sets out which questions decide it.
|
||||
|
||||
## The fast
|
||||
|
||||
@@ -425,22 +431,18 @@ It lands in `~/.local/share/typikon/` and is overlaid automatically.
|
||||
|
||||
## Further reading
|
||||
|
||||
- [docs/calendars.md](docs/calendars.md) sets out which churches keep which
|
||||
- [docs/calendars.md](https://git.pumpin.online/funkpower/typikon/src/branch/main/docs/calendars.md) sets out which churches keep which
|
||||
reckoning, how the split came about, what is modelled here and what is not.
|
||||
- [docs/versioning.md](docs/versioning.md) says what counts as the public
|
||||
- [docs/versioning.md](https://git.pumpin.online/funkpower/typikon/src/branch/main/docs/versioning.md) says what counts as the public
|
||||
surface, and how a correction to the calendar itself is announced.
|
||||
- [CHANGELOG.md](CHANGELOG.md) carries those announcements.
|
||||
- [CHANGELOG.md](https://git.pumpin.online/funkpower/typikon/src/branch/main/CHANGELOG.md) carries those announcements.
|
||||
|
||||
## Accuracy
|
||||
|
||||
`typikon` is pinned against published calendars: the paschalion for six years
|
||||
by both reckonings and its invariants across two centuries, 146,000 calendar
|
||||
round-trips from 1800 to 2200, the fast on every day that is not open to
|
||||
interpretation, and every jurisdiction over twenty years.
|
||||
|
||||
It was ported from a Python implementation, and the port was checked by
|
||||
running both over 199,446 day-records, 26 jurisdictions across 21 years, and
|
||||
requiring every field of every record to match.
|
||||
`typikon` is pinned against published calendars: the paschalion for eleven
|
||||
named years and its invariants across the two centuries from 1900, 146,000
|
||||
calendar round-trips from 1800 to 2200, the fast on every day that is not open
|
||||
to interpretation, and every jurisdiction over the twenty-one years from 2020.
|
||||
|
||||
It is a calendar, not an authority. If it disagrees with the one your parish
|
||||
prints, your parish is right. Please open an issue.
|
||||
@@ -455,10 +457,12 @@ widgets for Hyprland (Quickshell), waybar and eww, all reading the JSON above.
|
||||
## Releasing
|
||||
|
||||
`main` is always releasable; a `vX.Y.Z` tag on it builds the wheels and publishes
|
||||
to PyPI. [docs/releasing.md](docs/releasing.md) has the workflow, and what has to
|
||||
to PyPI. [docs/releasing.md](https://git.pumpin.online/funkpower/typikon/src/branch/main/docs/releasing.md) has the workflow, and what has to
|
||||
be set up before the first one.
|
||||
|
||||
## Licence
|
||||
|
||||
GPL-2.0-only. See [LICENSE](LICENSE). The menologion is under it too;
|
||||
GPL-2.0-only. The source for any published release is the source distribution
|
||||
beside it on PyPI, and `Cargo.lock` pins every dependency to an exact version.
|
||||
See [LICENSE](https://git.pumpin.online/funkpower/typikon/src/branch/main/LICENSE). The menologion is under it too;
|
||||
`data/LICENSE` says so and notes what the fetched sets are not.
|
||||
|
||||
+2
-1
@@ -110,7 +110,8 @@ developers, a wall for everyone else.
|
||||
## Checking a release without publishing
|
||||
|
||||
```console
|
||||
$ maturin build --release --out dist && maturin sdist --out dist
|
||||
$ rm -rf dist # a wheel left in dist/ gets packed into the sdist
|
||||
$ maturin sdist --out dist && maturin build --release --out dist
|
||||
$ twine check dist/*
|
||||
$ python -m venv /tmp/v && /tmp/v/bin/pip install --no-binary :all: dist/*.tar.gz
|
||||
$ /tmp/v/bin/python -c 'import typikon, datetime; print(typikon.today())'
|
||||
|
||||
+14
-2
@@ -11,10 +11,19 @@ license-files = ["LICENSE"]
|
||||
requires-python = ">=3.9"
|
||||
keywords = ["orthodox", "liturgical", "calendar", "byzantine", "pascha", "fasting"]
|
||||
classifiers = [
|
||||
"Development Status :: 4 - Beta",
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Environment :: Console",
|
||||
"Intended Audience :: Developers",
|
||||
"Programming Language :: Rust",
|
||||
"Intended Audience :: End Users/Desktop",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
"Programming Language :: Python :: 3",
|
||||
"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",
|
||||
"Programming Language :: Python :: Implementation :: CPython",
|
||||
"Programming Language :: Rust",
|
||||
"Topic :: Religion",
|
||||
"Topic :: Software Development :: Libraries",
|
||||
"Typing :: Typed",
|
||||
@@ -25,6 +34,9 @@ dynamic = ["version"]
|
||||
[project.urls]
|
||||
Homepage = "https://git.pumpin.online/funkpower/typikon"
|
||||
Repository = "https://git.pumpin.online/funkpower/typikon"
|
||||
Changelog = "https://git.pumpin.online/funkpower/typikon/src/branch/main/CHANGELOG.md"
|
||||
Documentation = "https://git.pumpin.online/funkpower/typikon/src/branch/main/docs/calendars.md"
|
||||
Issues = "https://git.pumpin.online/funkpower/typikon/issues"
|
||||
|
||||
[tool.maturin]
|
||||
bindings = "pyo3"
|
||||
|
||||
@@ -4,15 +4,17 @@ Everything derives from the paschalion and the fixed calendar, so this needs no
|
||||
network, cannot go stale, and answers for any year you ask about.
|
||||
|
||||
>>> import typikon, datetime
|
||||
>>> day = typikon.describe(datetime.date(2026, 4, 12))
|
||||
>>> day = typikon.describe(datetime.date(2026, 4, 12), jurisdiction='new')
|
||||
>>> day.feast
|
||||
'The Radiant and Life-giving Resurrection of our Lord — Holy Pascha'
|
||||
>>> day.fast, day.days_to_pascha
|
||||
('none', 0)
|
||||
|
||||
Called without a jurisdiction, every function uses the one `typikon
|
||||
--set-default` wrote, so the library and the command line agree about the same
|
||||
date. Pass ``jurisdiction=`` to override it; ``jurisdictions()`` lists the keys.
|
||||
The jurisdiction is given here because 12 April 2026 is Pascha on the Julian
|
||||
paschalion and an ordinary Sunday on the Gregorian one. Called without one,
|
||||
every function uses whatever `typikon --set-default` wrote, so the library and
|
||||
the command line agree about the same date. Pass ``jurisdiction=`` to override
|
||||
it; ``jurisdictions()`` lists the keys.
|
||||
"""
|
||||
|
||||
from ._typikon import (
|
||||
|
||||
+1
-1
@@ -371,7 +371,7 @@ fn ics_is_well_formed() {
|
||||
#[test]
|
||||
fn every_jurisdiction_holds_together_for_twenty_years() {
|
||||
for jur in JURISDICTIONS.iter().chain(CALENDARS.iter()) {
|
||||
for day in week(d("2020-01-01"), 366 * 21 / 4, jur) {
|
||||
for day in week(d("2020-01-01"), 366 * 21, jur) {
|
||||
assert!(!day.commemorations.is_empty(), "{} {}", jur.key, day.date);
|
||||
assert!(!day.title().is_empty(), "{} {}", jur.key, day.date);
|
||||
// `binds` may never be stricter than the level it sits under.
|
||||
|
||||
Reference in New Issue
Block a user