Skip to content

Release 4.0.0: modern engine by default, legacy frozen - #27

Merged
un33k merged 11 commits into
mainfrom
release/4.0.0-modern-default
Sep 22, 2026
Merged

un33k merged 11 commits into
mainfrom
release/4.0.0-modern-default

Conversation

@un33k

@un33k un33k commented Sep 22, 2026

Copy link
Copy Markdown
Owner

Summary

python-ipware 4.0.0. A new modern engine becomes the default; the 3.x algorithm is kept byte-for-byte as an explicit legacy option.

from python_ipware import IpWare

IpWare()                     # auto -> modern (default)
IpWare(algorithm="legacy")   # frozen 3.x behavior

What changed

  • Algorithm routerIpWare(algorithm="auto" | "modern" | "legacy"). auto is an alias for modern; legacy only when requested.
  • Legacy frozen — v3 engine moved to python_ipware/legacy/ and v3 tests to tests/legacy/, both as 100% renames. A runner checks the v3 suite against the legacy engine.
  • Modern engine — hardened IPv6 / bracketed-port / IPv4-mapped parsing, expanded default header list. Matches v3 on well-formed headers (v3 suite + a 3,000+ case legacy-vs-modern differential test). Documented differences on malformed input only: quoted addresses accepted, 1.2.3.4:80:90 rejected.
  • CIDR trusted proxiesproxy_list accepts networks like 100.64.0.0/10 and fd7a:115c:a1e0::/48 (modern only). Thanks @griffi-gh (Support for CIDR notation #26).
  • Fly.ioFly-Client-IP added to the modern defaults. Thanks @mdalp (Add Fly.io header to precedence list #23).
  • CDN-first docs — README shows how to put a CDN header first via precedence when all traffic comes through that CDN. Thanks @iloveitaly (fix: proxy-specific headers should have a higher precedent #25).
  • Python — 3.9+ with no upper cap; CI tests 3.9–3.14 and PyPy. Thanks @iloveitaly (ci: test py 3.13 #24).
  • Packaging — PEP 621 pyproject.toml with Hatchling, SPDX license, SECURITY.md in the sdist.
  • CI — current action versions, legacy suite step, build + twine check, pip cache keyed on pyproject.toml, non-fatal Coveralls, patched PyPI publish action (resolves Dependabot alert Add py.typed file for static type checking compatability #2).
  • Docs — README rewritten around the modern engine with Mermaid diagrams; v3 guide moved to python_ipware/legacy/README.md; SECURITY.md asks for private email reports.

Verification (local)

  • 113 tests + 86 v3 legacy tests pass on Python 3.11, 3.13 and 3.14 (deprecation warnings as errors)
  • ruff clean, including 3.9 target
  • all README Python examples run; README header list matches the code
  • build + twine check pass; clean wheel install works
  • Python 3.9, 3.10 and PyPy are covered by CI on this PR

No tag is pushed, so merging does not publish to PyPI. Publishing happens only when v4.0.0 is tagged.

🚀 Generated with Dojo ⛩️

un33k and others added 11 commits September 22, 2026 12:49
- Add an algorithm router: IpWare(algorithm="auto"|"modern"|"legacy").
  "auto" resolves to "modern"; "legacy" is available only when requested.
- Move the v3 algorithm to python_ipware/legacy/ unchanged (byte-identical),
  and the v3 tests to tests/legacy/ unchanged, with a runner that checks them
  against the legacy engine.
- Add the modern engine: hardened IPv6, bracketed-port and IPv4-mapped parsing,
  and an expanded default header list. The full v3 suite passes against it.
- Modernize packaging: PEP 621 pyproject with Hatchling, SPDX license,
  Python 3.9-3.13, ruff lint.* config.
- Fix CI: current action versions, supported Pythons, legacy suite step,
  twine check.
- Rewrite README around the modern engine with Mermaid diagrams, Maintained
  with Dojo badge and sponsors; move the v3 guide to the legacy folder.
- Modern engine: with leftmost=False, proxy_list validated the raw chain but
  picked the client from the reversed chain, so right-most networks with a
  trusted proxy list returned None. Put the chain in client-first order once,
  before validation, matching legacy.
- Strict mode now rejects empty entries (e.g. "1.2.3.4,, 5.6.7.8"), as v3 does.
- Tests: right-most + proxy_list regressions, strict empty-token tests, and a
  legacy-vs-modern differential test over 3,000+ well-formed combinations.
  These fail 211 times against the previous engine.
- Docs: replace "verified superset of v3" with the accurate claim and list the
  two remaining malformed-input differences (quoted addresses accepted,
  1.2.3.4:80:90 rejected).
- CI: key the pip cache on pyproject.toml (the default requirements.txt lookup
  would fail setup on every job); make Coveralls upload non-fatal.
- Packaging: include SECURITY.md in the sdist.
… docs (#25)

- Modern engine: proxy_list entries may be CIDR networks (IPv4/IPv6), matched
  by real network membership; plain prefixes still work. Invalid CIDR raises
  ValueError. Legacy unchanged. Requested by @griffi-gh in #26.
- Modern defaults: add Fly.io's Fly-Client-IP header. Suggested by @mdalp in #23.
- README: document CIDR entries and how to put a CDN header first via
  precedence when all traffic comes through that CDN. Suggested by
  @iloveitaly in #25.
- CHANGELOG: credit community contributions, including @iloveitaly's Python
  3.13 CI suggestion (#24).

Co-authored-by: mdalp <mdalp@users.noreply.github.com>
Co-authored-by: iloveitaly <iloveitaly@users.noreply.github.com>
Co-authored-by: griffi-gh <griffi-gh@users.noreply.github.com>
CI installed ruff 0.16.8, whose new PLC0207 rule flagged two lines in the
frozen v3 engine. Legacy must stay byte-identical, so exclude it (and its v3
tests) from linting instead of editing it, and pin ruff so future rule
additions cannot break CI unannounced.

🚀 Generated with [Dojo](https://heydojo.ai) ⛩️
twine (in [dev]) pulls nh3/cryptography, which need a Rust build on PyPy and
failed there. Test jobs only need ruff and coverage, so add a [test] extra
and use it in CI; [dev] now extends [test] with build and twine.

🚀 Generated with [Dojo](https://heydojo.ai) ⛩️
@coveralls

Copy link
Copy Markdown

Coverage Status

coverage: 95.189% (+0.03%) from 95.161% — release/4.0.0-modern-default into main

@un33k
un33k merged commit 9034c38 into main Sep 22, 2026
14 checks passed
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.

2 participants