Skip to content

Modernize project tooling and packaging#15

Merged
gmr merged 3 commits into
mainfrom
feature/modernize-repo
Mar 13, 2026
Merged

Modernize project tooling and packaging#15
gmr merged 3 commits into
mainfrom
feature/modernize-repo

Conversation

@gmr
Copy link
Copy Markdown
Owner

@gmr gmr commented Mar 13, 2026

Summary

  • Replace setup.py/setup.cfg with pyproject.toml using hatchling build backend
  • Replace flake8 (8 plugins) with ruff for linting and formatting
  • Add pre-commit configuration with ruff-format and ruff lint hooks
  • Switch documentation from Sphinx to mkdocs with Material theme
  • Add GitHub Pages docs deployment workflow
  • Switch CI/CD to use uv and modern GitHub Action versions (actions/checkout@v5, setup-uv@v6, codecov@v5)
  • Update deploy workflow to use trusted publishing (no more token-based auth)
  • Modernize Python source: list[]/tuple[] type hints, str | None unions, f-strings, Google-style docstrings
  • Convert README from RST to Markdown
  • Drop Python 3.8–3.10 support, require 3.11+
  • Remove CodeClimate integration and legacy VERSION file
  • Use frozenset + typing.ClassVar for immutable provider class attributes

Test plan

  • All 23 tests pass locally
  • ruff check + ruff format pass
  • mkdocs builds successfully with --strict
  • CI passes on all Python versions (3.11–3.14)
  • Configure GitHub Pages environment for docs deployment
  • Configure PyPI trusted publishing environment for deploy workflow

Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com

Summary by CodeRabbit

  • Documentation

    • Migrated to MkDocs with a new README, site navigation, API reference pages, and automated GitHub Pages deployment.
  • Python Support

    • Updated project metadata to require Python 3.11+ (docs and packaging updated).
  • Build & Tooling

    • Modernized packaging and developer tooling (pyproject/hatch, pre-commit hooks) and updated CI/build/test workflows.

- Replace setup.py/setup.cfg with pyproject.toml using hatchling
- Replace flake8 with ruff for linting and formatting
- Add pre-commit configuration
- Switch from Sphinx to mkdocs with Material theme
- Add GitHub Pages docs deployment workflow
- Switch CI/CD to use uv and modern action versions
- Update deploy workflow to use trusted publishing
- Modernize Python code: type hints, f-strings, Google docstrings
- Convert README from RST to Markdown
- Drop Python 3.8-3.10, require 3.11+
- Remove CodeClimate integration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 13, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eb373884-5715-4dfd-aaac-50e676e3a8c9

📥 Commits

Reviewing files that changed from the base of the PR and between f2bd3e1 and cbfe622.

📒 Files selected for processing (2)
  • README.md
  • docs/index.md

📝 Walkthrough

Walkthrough

This PR modernizes packaging, CI/CD, and docs: removes setuptools/setup.cfg and Sphinx artifacts, adds pyproject.toml/Hatchling and MkDocs, updates GitHub Actions to use astral-sh/setup-uv and uv-based commands, introduces pre-commit/ruff, and modernizes type hints and provider definitions across the library and tests.

Changes

Cohort / File(s) Summary
Build system & metadata
setup.py, setup.cfg, pyproject.toml, MANIFEST.in, VERSION
Removed legacy setuptools files and VERSION; added pyproject.toml with Hatchling and tooling configuration; simplified MANIFEST.in.
Documentation system
docs/... (docs/conf.py, docs/index.rst, docs/Makefile, docs/make.bat, docs/normalize.rst, docs/normalizer.rst, docs/result.rst, docs/mxrecords.rst, docs/requirements.txt, docs/_static/css/custom.css), docs/index.md, docs/api.md, mkdocs.yml, README.rst, README.md
Removed Sphinx config and many reST docs; added MkDocs config (mkdocs.yml) and Markdown docs (docs/index.md, docs/api.md); replaced README.rst with README.md.
CI / CD workflows
.github/workflows/testing.yaml, .github/workflows/deploy.yaml, .github/workflows/docs.yaml
Updated workflows to actions/checkout@v5, replaced container/Python setup with astral-sh/setup-uv, switched build/publish to uv commands, narrowed Python matrix, added docs deploy workflow and adjusted permissions.
Code quality & editor config
.pre-commit-config.yaml, .editorconfig, .codeclimate.yml, .gitignore
Added pre-commit hooks (pre-commit-hooks, ruff); changed YAML indent glob and indent_size to 2; removed Code Climate Python config; updated .gitignore docs path.
Contributing & developer docs
CONTRIBUTING.md
Replaced virtualenv/pip instructions with uv commands; updated lint/test examples to use ruff, pre-commit, and uv-based commands.
Library typing & API surface (annotations only)
email_normalize/__init__.py
Modernized type hints to builtin generics and PEP 604 unions (e.g., list[tuple[int,str]], `str
Provider definitions refactor
email_normalize/providers.py
Converted provider attributes to ClassVar, made MXDomains immutable frozenset[str], and replaced flag XORs with explicit OR combinations.
Tests
tests/test_normalize.py, tests/test_normalizer.py
Updated tests to modern type hints, switched to f-strings, reformatted mocks, and adjusted helper signatures to match typing changes.
Removed Sphinx artifacts
.codeclimate.yml, docs/* (Sphinx-specific)
Deleted Sphinx-only config and dependency entries (Sphinx, sphinx-autodoc-typehints, sphinx-material, typed_ast).

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

Poem

🐇 I hopped from setup.py to toml bright,

reST to Markdown under softer light,
ruff and pre-commit nibble lines just so,
frozensets snug where sets would grow,
uv hums softly — the rabbit says goodnight.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.59% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main objective of the changeset: modernizing the project's tooling and packaging infrastructure (setup.py/setup.cfg → pyproject.toml, flake8 → ruff, Sphinx → MkDocs, etc.).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/modernize-repo
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
email_normalize/providers.py (1)

34-35: Consider using | instead of ^ for flag combination.

The code uses XOR (^) to combine Rules flags, but the semantic intent appears to be combining (union) rather than toggling. While the result is identical for distinct enum.auto() values, using OR (|) better expresses the intent of "provider supports both features."

💡 Suggested clarification
 class Fastmail(MailboxProvider):
-    Flags = Rules.PLUS_ADDRESSING ^ Rules.LOCAL_PART_AS_HOSTNAME
+    Flags = Rules.PLUS_ADDRESSING | Rules.LOCAL_PART_AS_HOSTNAME
     MXDomains = frozenset({'messagingengine.com'})

Similarly for Google at line 39:

-    Flags = Rules.PLUS_ADDRESSING ^ Rules.STRIP_PERIODS
+    Flags = Rules.PLUS_ADDRESSING | Rules.STRIP_PERIODS
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@email_normalize/providers.py` around lines 34 - 35, The Flags assignment uses
XOR (^) which suggests toggling but the intent is a union of features; update
the Flags expressions to use bitwise OR (|) instead of XOR for clarity (e.g.,
change Flags = Rules.PLUS_ADDRESSING ^ Rules.LOCAL_PART_AS_HOSTNAME to use |)
and make the same change for the Google provider Flags so the code clearly
expresses "supports both" rather than toggling.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/deploy.yaml:
- Around line 11-12: The workflow's job-level permissions currently only include
id-token: write which prevents actions/checkout@v5 from working; update the
permissions block to include contents: read alongside id-token: write (i.e., add
contents: read under the permissions mapping) so checkout can access the
repository contents while retaining id-token: write for OIDC.

In `@docs/index.md`:
- Around line 3-4: Update the intro sentence for accuracy and readability:
change the description of the project name "email-normalize" to state it targets
Python 3.11+ (not just "Python 3") and hyphenate "mailbox-provider-specific
behaviors", e.g. reword to something like "email-normalize is a Python 3.11+
library that returns a normalized email address, stripping
mailbox-provider-specific behaviors such as plus addressing."

In `@README.md`:
- Around line 3-4: Update the README intro sentence to reflect supported Python
versions and correct hyphenation: change the Python version text from "Python 3"
to "Python 3.11+" and hyphenate "mailbox-provider-specific" in the phrase about
stripping provider behaviors (e.g., "stripping mailbox-provider-specific
behaviors such as 'Plus addressing'") so the first two lines align with Line 35
and use the correct hyphenation.

---

Nitpick comments:
In `@email_normalize/providers.py`:
- Around line 34-35: The Flags assignment uses XOR (^) which suggests toggling
but the intent is a union of features; update the Flags expressions to use
bitwise OR (|) instead of XOR for clarity (e.g., change Flags =
Rules.PLUS_ADDRESSING ^ Rules.LOCAL_PART_AS_HOSTNAME to use |) and make the same
change for the Google provider Flags so the code clearly expresses "supports
both" rather than toggling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 34b62087-1461-4841-bc65-340dad35c94a

📥 Commits

Reviewing files that changed from the base of the PR and between 259fead and 41225c1.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (32)
  • .codeclimate.yml
  • .editorconfig
  • .github/workflows/deploy.yaml
  • .github/workflows/docs.yaml
  • .github/workflows/testing.yaml
  • .gitignore
  • .pre-commit-config.yaml
  • CONTRIBUTING.md
  • MANIFEST.in
  • README.md
  • README.rst
  • VERSION
  • docs/Makefile
  • docs/_static/css/custom.css
  • docs/api.md
  • docs/conf.py
  • docs/index.md
  • docs/index.rst
  • docs/make.bat
  • docs/mxrecords.rst
  • docs/normalize.rst
  • docs/normalizer.rst
  • docs/requirements.txt
  • docs/result.rst
  • email_normalize/__init__.py
  • email_normalize/providers.py
  • mkdocs.yml
  • pyproject.toml
  • setup.cfg
  • setup.py
  • tests/test_normalize.py
  • tests/test_normalizer.py
💤 Files with no reviewable changes (15)
  • docs/mxrecords.rst
  • docs/Makefile
  • docs/result.rst
  • docs/requirements.txt
  • docs/conf.py
  • docs/normalizer.rst
  • docs/normalize.rst
  • docs/index.rst
  • VERSION
  • README.rst
  • setup.cfg
  • docs/_static/css/custom.css
  • setup.py
  • docs/make.bat
  • .codeclimate.yml

Comment thread .github/workflows/deploy.yaml
Comment thread docs/index.md Outdated
Comment thread README.md Outdated
gmr and others added 2 commits March 13, 2026 13:00
- Remove trailing blank line in .gitignore (end-of-file-fixer)
- Use | instead of ^ for combining Rules flags in providers
- Add contents: read permission to deploy workflow

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gmr gmr merged commit 5bf5014 into main Mar 13, 2026
1 check 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.

1 participant