Thanks for looking. A bug report with a minimal reproduction — the input
string, the SLUGIFY_PROCESSORS configured (if any), and the slug you
expected — is the most useful thing to send.
How this project writes prose — README, CHANGES, commit messages,
docstrings, and source comments — is set out separately in
WRITING.md. Read that before changing any of it. The
constraints every change is held to, and the map of what is where, are in
AGENTS.md.
You need git and uv. Install uv from the installation documentation if it is not already available.
Clone the repository:
$ git clone https://github.com/tony/django-slugify-processor.git$ cd django-slugify-processorInstall packages:
$ uv sync --all-extras --devRun them in this order: format, test, lint with fixes, type-check, then test again before finalizing a change.
Format:
$ uv run ruff format .Lint:
$ uv run ruff check . --fix --show-fixesType-check:
$ uv run mypyTest:
$ uv run py.testOr use the just helper for the same four:
$ just ruff-format$ just ruff$ just mypy$ just testDocumentation is a gate, not a courtesy. Docstring examples under src/,
and >>> sessions on docs/ pages, are executed by pytest; the doctest
flags live in pyproject.toml, so there is no separate doctest step and a
green uv run py.test is the proof. Which blocks qualify, and the one
mistake that silently removes a test, are in
WRITING.md.
Before claiming a test or a gate works, show it failing. A gate that has never been red is an assumption.
CI (.github/workflows/tests.yml) is the order of record: it runs
ruff check ., ruff format . --check, mypy ., and
py.test --cov=./ --cov-report=xml across the Python/Django matrix. Every
gate it runs has to pass before a change is done.
ruff handles linting, formatting, and import sorting; mypy runs in
strict mode (pyproject.toml, [tool.mypy]). Namespace imports
(import typing as t) are preferred over from module import *, and every
module opens with from __future__ import annotations — ruff's isort
config (required-imports) enforces the latter automatically. Docstrings
follow one enforced dialect (NumPy, via ruff's pydocstyle rules); see
WRITING.md for what to put in them.
Tests live in tests/ and run under pytest with pytest-django, using
DJANGO_SETTINGS_MODULE=tests.settings (set in pyproject.toml; the
module itself is tests/settings.py). There is no conftest.py anywhere
in this repository, so there are no project-specific fixtures — tests use
pytest-django's built-in settings fixture directly to set
SLUGIFY_PROCESSORS, INSTALLED_APPS, or TEMPLATES per test, and
@pytest.mark.django_db on tests that touch a model.
test_app/ at the repository root is an example Django app — models.py
has a model with an AutoSlugField, coding.py has the example processor
functions (slugify_programming, slugify_programming_languages,
slugify_language_suffix) that both tests/ and the docs/ examples
import. pythonpath = ". tests" in pyproject.toml puts the repository
root and tests/ on sys.path, which is what makes
test_app.coding.slugify_programming_languages and tests.settings
importable.
Run the full suite directly:
$ uv run py.testRun one file:
$ uv run py.test tests/test_text.pyAutomatically rerun tests on save with pytest-watcher:
$ just startOr with entr(1):
$ just watch-testIf a fix loops without progress, stop and say so. Minimize to the smallest reproduction, drop debugging cruft, and document the error, the reproduction, what you already tried, and your current hypothesis before continuing.
Default preview server: http://localhost:8030. sphinx-autobuild builds the docs, watches for file changes, and serves them.
From the repository root:
$ just start-docsFrom inside docs/:
$ just startBuild once without a server:
$ just build-docsRebuild on file change (requires entr(1)):
$ just watch-docsTwo pages are generated and must not be hand-edited: docs/history.md
{include}s CHANGES directly — edit CHANGES. The signatures and
docstring bodies on docs/api.md come from autofunction/autodata
directives reading src/ — edit the docstring, not the page, for
anything under one of those directives; the surrounding prose on that page
is hand-written and stays hand-written.
just build-docs catches a broken cross-reference; running the tests does
not — build the docs before committing a change that touches one. See
WRITING.md for the MyST roles this project
uses.
Never create tags. Never push tags. The owner handles tagging and tag pushes, because a tag triggers the publish workflow. See Release commits.
Releases publish to PyPI
via OIDC trusted publishing
from the release job in .github/workflows/tests.yml, triggered by a
pushed tag. Update
__version__ in src/django_slugify_processor/__about__.py and version
in pyproject.toml, then commit:
$ git commit -m 'Tag vX.Y.Z'The owner pushes the commit and the tag; CI builds and publishes from there. The full checklist is in docs/project/releasing.md.
One subject per pull request. Unrelated cleanup found along the way belongs in its own commit, and usually in its own pull request.
Discuss a substantial change via an issue before making it.
A pull request merges once it has the sign-off of one other developer. If you do not have merge permission, ask a maintainer to merge it for you.
Commit format is in WRITING.md.
- Participants will be tolerant of opposing views.
- Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks.
- When interpreting the words and actions of others, participants should always assume good intentions.
- Behaviour which can be reasonably considered harassment will not be tolerated.
Based on Ruby's Community Conduct Guideline.
Please do not open a public issue for a vulnerability. This repository has
no SECURITY.md; report privately through GitHub's security advisories
for this repository, or reach the maintainer through the contact listed in
pyproject.toml.