diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a7be9e8..0033404 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,7 +2,7 @@ name: Release on: push: tags: - - '*' + - "*" jobs: build: @@ -17,17 +17,17 @@ jobs: - name: Set up Python uses: actions/setup-python@v5 with: - python-version: '3.11' + python-version: "3.11" - name: Install dependencies run: | - python -m pip install -U pip - python -m pip install -U setuptools twine wheel + curl -LsSf https://astral.sh/uv/install.sh | sh + - name: Build package run: | - python setup.py --version - python setup.py sdist --format=gztar bdist_wheel - twine check dist/* + uv build + uvx twine check dist/* + - name: Upload packages to Jazzband if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') uses: pypa/gh-action-pypi-publish@v1.12.3 diff --git a/.github/workflows/test_suite.yml b/.github/workflows/test_suite.yml index 473be38..a883369 100644 --- a/.github/workflows/test_suite.yml +++ b/.github/workflows/test_suite.yml @@ -10,24 +10,31 @@ jobs: strategy: matrix: python-version: - - "3.8" - "3.9" - "3.10" - "3.11" - "3.12" + - "3.13" steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + uses: astral-sh/setup-uv@v5 with: - python-version: ${{ matrix.python-version }} + cache-dependency-glob: "pyproject.toml" + cache-suffix: ${{ matrix.python-version }} - - run: pip install tox tox-gh-actions codecov + - name: Install Python + run: uv python install ${{ matrix.python-version }} + env: + UV_PYTHON_PREFERENCE: only-managed - - run: tox + - run: uv pip install codecov + + - run: uvx tox + + - run: uvx codecov - - run: codecov check: runs-on: ubuntu-latest if: always() diff --git a/.gitignore b/.gitignore index 96ab35b..de762f3 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ build/ dist/ *.egg-info docs/_build + +uv.lock diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 2124f77..4b4f05f 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,16 +1,17 @@ version: 2 build: - os: ubuntu-20.04 + os: ubuntu-22.04 tools: - python: "3.9" + python: "3.11" + + commands: + - asdf plugin add uv + - asdf install uv latest + - asdf global uv latest + - mkdir -p $READTHEDOCS_OUTPUT/html/ + - uv sync --group docs --frozen + - uv run -m sphinx -T -b html -d docs/_build/doctrees -D language=en docs $READTHEDOCS_OUTPUT/html sphinx: configuration: docs/conf.py - -python: - install: - - method: pip - path: . - extra_requirements: - - docs diff --git a/django_fsm_log/models.py b/django_fsm_log/models.py index fc13d8e..e999145 100644 --- a/django_fsm_log/models.py +++ b/django_fsm_log/models.py @@ -16,7 +16,7 @@ class StateLog(models.Model): null=True, on_delete=models.SET_NULL, ) - source_state = models.CharField(max_length=255, db_index=True, null=True, blank=True, default=None) + source_state = models.CharField(max_length=255, db_index=True, null=True, blank=True, default=None) # noqa:DJ001 state = models.CharField("Target state", max_length=255, db_index=True) transition = models.CharField(max_length=255) @@ -24,7 +24,7 @@ class StateLog(models.Model): object_id = models.PositiveIntegerField(db_index=True) content_object = GenericForeignKey("content_type", "object_id") - description = models.TextField(blank=True, null=True) + description = models.TextField(blank=True, null=True) # noqa:DJ001 objects = StateLogManager() diff --git a/pyproject.toml b/pyproject.toml index d933e7c..80ec66d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,74 @@ -[tool.black] -line-length = 119 -target-version = ["py37"] -extend-exclude = "(^/django_fsm_log/migrations/.*$|^docs/.*$)" +[project] +license = { file = "LICENSE" } +description = "Transition's persistence for django-fsm" +name = "django-fsm-log" +dynamic = ["version"] +readme = "README.md" +requires-python = ">=3.9" +authors = [ + { name = "Gizmag", email = "tech@gizmag.com" }, + { name = "Various Contributors" }, +] +keywords = ["django", "django-fsm-2"] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Web Environment", + "Framework :: Django", + "Framework :: Django :: 4.2", + "Framework :: Django :: 5.0", + "Framework :: Django :: 5.1", + "Intended Audience :: Developers", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "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", + "Topic :: Software Development :: Libraries :: Python Modules", +] +dependencies = ["django>=4.2", "django-fsm-2", "django_appconf"] + +[dependency-groups] +dev = [ + "pytest", + "pytest-cov", + "pytest-django", + "pytest-mock", + "tox", + "tox-gh-actions>=3.2.0", + "tox-uv>=1.17.0", + "twine", +] +docs = ["sphinx", "sphinx_rtd_theme", "myst-parser"] + +[project.urls] +Documentation = "https://django-fsm-log.readthedocs.io/en/latest/" +Homepage = "https://github.com/jazzband/django-fsm-log" + +[build-system] +requires = ["setuptools>=64", "setuptools_scm>=8"] +build-backend = "setuptools.build_meta" + +[tool.setuptools] +include-package-data = true + +[tool.setuptools_scm] [tool.ruff] line-length = 119 -target-version = "py37" -select = ["E", "F", "I", "B", "C4", "T20", "TID", "UP"] -exclude = ["django_fsm_log/migrations", ".tox", "build"] +target-version = "py39" +extend-exclude = ["django_fsm_log/migrations/", ".tox/", "build/", "docs/"] + +[tool.ruff.lint] +select = ["E", "F", "I", "B", "C4", "T20", "TID", "UP", "DJ"] + +[tool.pytest.ini_options] +markers = [ + "ignore_article: Configure the settings DJANGO_FSM_LOG_IGNORED_MODELS to ignore Article Model.", + "pending_objects: Install PendingStateLogManager on StateLog", +] +testpaths = ["tests"] +pythonpath = ["."] +DJANGO_SETTINGS_MODULE = "tests.settings" diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index bb0248b..0000000 --- a/setup.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[tool:pytest] -DJANGO_SETTINGS_MODULE = tests.settings -testpaths = tests - -markers = - ignore_article: Configure the settings DJANGO_FSM_LOG_IGNORED_MODELS to ignore - Article Model. - pending_objects: Install PendingStateLogManager on StateLog diff --git a/setup.py b/setup.py deleted file mode 100644 index 5c2d428..0000000 --- a/setup.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python - -from setuptools import find_packages, setup - - -def readfile(filename): - with open(filename) as open_file: - return open_file.read() - - -setup( - name="django-fsm-log", - version="4.0.1", - description="Transition's persistence for django-fsm", - long_description=readfile("README.md"), - long_description_content_type="text/markdown", - author="Gizmag", - author_email="tech@gizmag.com", - url="https://github.com/jazzband/django-fsm-log", - license="MIT", - packages=find_packages(exclude=["tests"]), - install_requires=["django>=3.2", "django-fsm-2", "django_appconf"], - extras_require={ - "testing": [ - "pytest", - "pytest-cov", - "pytest-django", - "pytest-mock", - ], - "docs": [ - "sphinx", - "sphinx_rtd_theme", - "myst-parser", - ], - }, - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Environment :: Web Environment", - "Framework :: Django", - "Framework :: Django :: 4.2", - "Framework :: Django :: 5.0", - "Intended Audience :: Developers", - "License :: OSI Approved :: MIT License", - "Operating System :: OS Independent", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Topic :: Software Development :: Libraries :: Python Modules", - ], -) diff --git a/tests/models.py b/tests/models.py index 2a1698b..b743872 100644 --- a/tests/models.py +++ b/tests/models.py @@ -15,6 +15,9 @@ class Article(models.Model): state = FSMField(choices=STATES, default="draft", protected=True) + def __str__(self): + return f"pk={self.pk}" + @fsm_log_by @fsm_log_description @transition(field=state, source="draft", target="submitted") @@ -72,6 +75,9 @@ class ArticleInteger(models.Model): state = FSMIntegerField(choices=STATES, default=STATE_ONE) + def __str__(self): + return f"pk={self.pk}" + @fsm_log_by @transition(field=state, source=STATE_ONE, target=STATE_TWO) def change_to_two(self, by=None): diff --git a/tox.ini b/tox.ini index 843f6df..e656b59 100644 --- a/tox.ini +++ b/tox.ini @@ -4,6 +4,7 @@ envlist = py{310,311,312,313}-5.0 py{310,311,312,313}-5.1 py{310,311,312,313}-dj-master + lint [gh-actions] python = @@ -16,12 +17,17 @@ python = [testenv] usedevelop = true commands = pytest --cov=django_fsm_log --cov=tests {posargs} -extras = testing setenv= DJANGO_SETTINGS_MODULE = tests.settings - PYTHONPATH = {toxinidir} deps = dj-4.2: Django>=4.2,<5 dj-5.0: Django>=5,<5.1 dj-5.1: Django>=5.1,<5.2 dj-master: https://github.com/django/django/archive/master.tar.gz + +[testenv:lint] +basepython = python3 +deps = ruff +commands = + ruff check + ruff format --check