From c95031e6fe77b654f47e0639d73817b94ad0367c Mon Sep 17 00:00:00 2001 From: Dylan Verheul Date: Sun, 24 Dec 2023 10:19:07 +0100 Subject: [PATCH] Use setuptools, build and tox (#658) --- .github/workflows/test.yml | 108 ++++++++++++++++++++------------- .readthedocs.yml | 5 +- CONTRIBUTING.md | 4 +- Makefile | 36 +++++++---- docs/conf.py | 11 +--- docs/requirements.txt | 3 + pyproject.toml | 116 +++--------------------------------- requirements-dev.txt | 3 + requirements-test.txt | 3 + src/bootstrap4/__about__.py | 2 +- tests/test_forms.py | 4 +- tests/test_paginator.py | 4 +- tox.ini | 50 ++++++++++++++++ 13 files changed, 163 insertions(+), 186 deletions(-) create mode 100644 docs/requirements.txt create mode 100644 requirements-dev.txt create mode 100644 requirements-test.txt create mode 100644 tox.ini diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 14d02cca..7b82f668 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,68 +6,90 @@ concurrency: group: test-${{ github.head_ref }} cancel-in-progress: true -env: - PYTHONUNBUFFERED: "1" - FORCE_COLOR: "1" - jobs: - - static_tests: - name: Static Tests + ruff: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.11" - - name: Install latest pip and Hatch - run: pip install --upgrade pip hatch - - name: Lint - run: hatch run lint:all - - name: Docs - run: hatch run docs:build - - name: Build - run: hatch build + - uses: chartboost/ruff-action@v1 tests_matrix: - name: Python ${{ matrix.python-version }} runs-on: ubuntu-latest strategy: - fail-fast: false matrix: - python-version: ["3.8", "3.9", "3.10", "3.11"] + python-version: [3.8, 3.9, "3.10", 3.11, 3.12] + django-version: [3.2, 4.1, 4.2, 5.0, "main"] + exclude: + # Django 3.2 + - python-version: "3.10" + django-version: 3.2 + - python-version: 3.11 + django-version: 3.2 + - python-version: 3.12 + django-version: 3.2 - steps: - - uses: actions/checkout@v4 - - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} + # Django 4.1 + - python-version: 3.12 + django-version: 4.1 - - name: Install latest pip, Hatch and coveralls - run: pip install --upgrade pip hatch coveralls + # Django 4.2 + - python-version: 3.12 + django-version: 4.2 - - name: Install GDAL binaries - run: sudo apt-get install binutils libproj-dev gdal-bin + # Django 5.0 + - python-version: 3.8 + django-version: 5.0 + - python-version: 3.9 + django-version: 5.0 - - name: Run tests - run: hatch run test-cov + # Django main + - python-version: 3.8 + django-version: "main" + - python-version: 3.9 + django-version: "main" - - name: Coverage combine - run: coverage combine + steps: + - uses: actions/checkout@v4 + - name: Install GDAL binaries + run: sudo apt-get install binutils libproj-dev gdal-bin + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' + cache-dependency-path: requirements-test.txt + - run: python -m pip install -r requirements-test.txt + - run: python -m pip install -U Django==${{ matrix.django-version }} + if: matrix.django-version != 'main' + - run: python -m pip install -U https://github.com/django/django/archive/master.tar.gz + if: matrix.django-version == 'main' + - run: python -m pip install -e . + - run: coverage run manage.py test + - run: python -m pip install -U coveralls + - name: Upload coveralls (parallel) + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + COVERALLS_PARALLEL: true + run: coveralls --service=github - - name: Upload coveralls (parallel) - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - COVERALLS_PARALLEL: true - run: coveralls --service=github + docs: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + cache: 'pip' + cache-dependency-path: docs/requirements.txt + - name: Install and build + run: | + python -m pip install -r docs/requirements.txt + make docs tests: if: always() runs-on: ubuntu-latest - needs: [ static_tests, tests_matrix ] + needs: [ tests_matrix, ruff, docs ] steps: - name: Check tests matrix status if: needs.tests_matrix.result != 'success' diff --git a/.readthedocs.yml b/.readthedocs.yml index 636b846f..a34d6434 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -5,6 +5,7 @@ build: tools: python: "3.11" commands: - - pip install -U pip hatch - - hatch run docs:build + - pip install -U pip + - pip install -U -r docs/requirements.txt + - make docs - mv docs/_build $READTHEDOCS_OUTPUT diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8223fbd7..dcc644ac 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -45,8 +45,6 @@ Ready to contribute? Here\'s how to set up `django-bootstrap4` for local develop You will need some knowledge of git, github, and Python/Django development. Using a Python virtual environment is advised. -This project uses [Hatch](https://github.com/pypa/hatch) for environments and builds. - ### Local installation This section assumes you know about local Python versions and virtual environments. @@ -56,7 +54,7 @@ To clone the repository and install the requirements for local development: ```console git clone git://github.com/zostera/django-bootstrap4.git cd django-bootstrap4 -pip install -U pip hatch +pip install -U pip -r requirements-dev.txt pip install -e . ``` diff --git a/Makefile b/Makefile index 449eb848..cb64d796 100644 --- a/Makefile +++ b/Makefile @@ -1,35 +1,37 @@ -VERSION := $(shell hatch version) +VERSION := $(shell sed -n 's/^ *version.*=.*"\([^"]*\)".*/\1/p' pyproject.toml) .PHONY: test test: - hatch run test + coverage run manage.py test + coverage report .PHONY: tests tests: - hatch run all:test + tox .PHONY: reformat reformat: - hatch run lint:fmt + ruff --fix . + ruff format . .PHONY: lint lint: - hatch run lint:style + ruff . .PHONY: docs -docs: - hatch run docs:build +docs: clean + cd docs && sphinx-build -b html -d _build/doctrees . _build/html .PHONY: example example: - hatch run example:runserver + cd example && python manage.py runserver .PHONY: porcelain porcelain: ifeq ($(shell git status --porcelain),) @echo "Working directory is clean." else - @echo "Error - working directory is dirty. Commit those changes!"; + @echo "Error - working directory is dirty. Commit your changes."; @exit 1; endif @@ -38,17 +40,25 @@ branch: ifeq ($(shell git rev-parse --abbrev-ref HEAD),main) @echo "On branch main." else - @echo "Error - Not on branch main!" + @echo "Error - Not on branch main." @exit 1; endif .PHONY: build build: docs - rm -rf build dist src/*.egg-info - hatch build + python -m build .PHONY: publish publish: porcelain branch build - hatch publish + twine check dist/* + twine upload dist/* git tag -a v${VERSION} -m "Release ${VERSION}" git push origin --tags + +.PHONY: clean +clean: docs + rm -rf build dist src/*.egg-info .coverage* + +.PHONY: version +version: + @echo ${VERSION} diff --git a/docs/conf.py b/docs/conf.py index 00b46e05..46810fd5 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -import importlib from datetime import datetime import tomllib @@ -7,15 +6,7 @@ pyproject = tomllib.load(f) project = pyproject["project"]["name"] -conf = {"module": project.replace("-", "_")} - -try: - conf.update(pyproject["tool"]["sphinx"]["x-conf"]) -except KeyError: - pass - -module = importlib.import_module(conf["module"]) -release = module.__version__ +release = pyproject["project"]["version"] version = ".".join(release.split(".")[:2]) author = ", ".join(author["name"] for author in pyproject["project"]["authors"]) year = datetime.now().year diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 00000000..cb2e9af4 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,3 @@ +sphinx>=7.2.6 +sphinx-mdinclude>=0.5.3 +furo>=2023.05.20 diff --git a/pyproject.toml b/pyproject.toml index 0d1a74f1..fd66376e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [build-system] -build-backend = "hatchling.build" -requires = ["hatchling"] +build-backend = "setuptools.build_meta" +requires = ["setuptools"] [project] authors = [ @@ -13,6 +13,7 @@ classifiers = [ "Framework :: Django :: 3.2", "Framework :: Django :: 4.1", "Framework :: Django :: 4.2", + "Framework :: Django :: 5.0", "Intended Audience :: Developers", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", @@ -21,6 +22,7 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "Topic :: Software Development :: Libraries", "Topic :: Utilities", ] @@ -28,14 +30,12 @@ dependencies = [ "Django>=3.2", "beautifulsoup4>=4.8.0", ] -description = "Bootstrap 4 for Django" -dynamic = [ - "version", -] -license = "BSD-3-Clause" +description = "Django extensions by Zostera" +license = {file = "LICENSE"} name = "django-bootstrap4" readme = "README.md" requires-python = ">=3.8" +version = "23.6" [project.urls] Changelog = "https://github.com/zostera/django-bootstrap4/blob/main/CHANGELOG.md" @@ -44,102 +44,6 @@ Homepage = "https://github.com/zostera/django-bootstrap4" Issues = "https://github.com/zostera/django-bootstrap4/issues" Source = "https://github.com/zostera/django-bootstrap4" -[tool.hatch.version] -path = "src/bootstrap4/__about__.py" - -[tool.hatch.build.targets.sdist] -include = [ - "/src", -] - -[tool.hatch.build.targets.wheel] -packages = ["src/bootstrap4"] - -[tool.hatch.envs.default] -dependencies = [ - "coverage[toml]>=7.2.6", -] -matrix-name-format = "dj{value}" - -[tool.hatch.envs.default.scripts] -cov = [ - "test-cov", - "cov-report", -] -cov-report = [ - "- coverage combine", - "coverage report", -] -test = "python manage.py test {args:tests}" -test-cov = "coverage run manage.py test {args:tests}" - -[[tool.hatch.envs.all.matrix]] -django = ["3.2", "4.1", "4.2"] -python = ["3.8", "3.9"] - -[[tool.hatch.envs.all.matrix]] -django = ["3.2", "4.1", "4.2", "main"] -python = ["3.10"] - -[[tool.hatch.envs.all.matrix]] -django = ["4.1", "4.2", "main"] -python = ["3.11"] - -[tool.hatch.envs.all.overrides] -matrix.django.dependencies = [ - {value = "django~=3.2.0", if = ["3.2"]}, - {value = "django~=4.1.0", if = ["4.1"]}, - {value = "django~=4.2.0", if = ["4.2"]}, - {value = "django @ git+https://github.com/django/django.git", if = ["main"]}, -] - -[tool.hatch.envs.example] -dependencies = [ - "django>=3.2", -] -python = "3.11" -template = "example" - -[tool.hatch.envs.example.scripts] -runserver = [ - "cd example && python manage.py migrate && python manage.py runserver", -] - -[tool.hatch.envs.docs] -dependencies = [ - "sphinx>=7.0.1", - "sphinx-mdinclude>=0.5.3", - "furo>=2023.05.20", -] -python = "3.11" -template = "docs" - -[tool.hatch.envs.docs.scripts] -build = [ - "clean", - "cd docs && sphinx-build -b html -d _build/doctrees . _build/html", -] -clean = "rm -rf docs/_build" - -[tool.hatch.envs.lint] -dependencies = [ - "ruff>0.1", -] -detached = true - -[tool.hatch.envs.lint.scripts] -all = [ - "style", -] -fmt = [ - "ruff --fix {args:.}", - "ruff format {args:.}", - "style", -] -style = [ - "ruff {args:.}", -] - [tool.ruff] fix = false fixable = [ @@ -174,8 +78,7 @@ known-third-party = ["django"] [tool.coverage.run] branch = true -parallel = true -source = ["src"] +source = ["src", "tests"] [tool.coverage.paths] package = ["src/bootstrap4", "*/django_bootstrap4/src/bootstrap4"] @@ -183,6 +86,3 @@ package = ["src/bootstrap4", "*/django_bootstrap4/src/bootstrap4"] [tool.coverage.report] show_missing = true skip_covered = true - -[tool.sphinx.x-conf] -module = "bootstrap4" diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 00000000..9c8d1209 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,3 @@ +-r requirements-test.txt +-r docs/requirements.txt +twine==4.0.2 diff --git a/requirements-test.txt b/requirements-test.txt new file mode 100644 index 00000000..8405e71b --- /dev/null +++ b/requirements-test.txt @@ -0,0 +1,3 @@ +tox==4.11.4 +coverage==7.3.4 +ruff==0.1.9 diff --git a/src/bootstrap4/__about__.py b/src/bootstrap4/__about__.py index 961690fa..68ff86d0 100644 --- a/src/bootstrap4/__about__.py +++ b/src/bootstrap4/__about__.py @@ -1 +1 @@ -__version__ = "23.3.dev0" +__version__ = "23.3.dev1" diff --git a/tests/test_forms.py b/tests/test_forms.py index 8c28d779..b181cb0f 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -154,9 +154,7 @@ def test_input_group_addon_button(self): self.assertIn('
.00
', res) def test_input_group_addon_empty(self): - res = render_template_with_form( - '{% bootstrap_field form.subject addon_before=None addon_after="after" %}' - ) # noqa + res = render_template_with_form('{% bootstrap_field form.subject addon_before=None addon_after="after" %}') # noqa self.assertIn('class="input-group"', res) self.assertNotIn("input-group-prepend", res) self.assertIn('
after
', res) diff --git a/tests/test_paginator.py b/tests/test_paginator.py index 9a45dc69..a956f3cc 100644 --- a/tests/test_paginator.py +++ b/tests/test_paginator.py @@ -17,9 +17,7 @@ def bootstrap_pagination(self, page, extra=""): template = """ {% load bootstrap4 %} {% bootstrap_pagination page {extra} %} - """.replace( - "{extra}", extra - ) + """.replace("{extra}", extra) return render_template(template, {"page": page}) diff --git a/tox.ini b/tox.ini new file mode 100644 index 00000000..2501070a --- /dev/null +++ b/tox.ini @@ -0,0 +1,50 @@ +[tox] +args_are_paths = false +envlist = + py38-{3.2,4.1,4.2}, + py39-{3.2,4.1,4.2}, + py310-{3.2,4.1,4.2,5.0,main}, + py311-{4.1,4.2,5.0,main}, + py312-{4.2,5.0,main}, + docs, + lint, + +[testenv] +basepython = + py37: python3.7 + py38: python3.8 + py39: python3.9 + py310: python3.10 + py311: python3.11 + py312: python3.12 +usedevelop = true +pip_pre = true +setenv = + PYTHONPATH={toxinidir} + PYTHONWARNINGS=all +commands = + python manage.py test {posargs} +deps = + 3.2: Django==3.2.* + 4.0: Django==4.0.* + 4.1: Django==4.1.* + 4.2: Django==4.2.* + 5.0: Django==5.0.* + main: https://github.com/django/django/archive/main.tar.gz + -r{toxinidir}/requirements-test.txt + +[testenv:ruff] +basepython = python3.11 +allowlist_externals = ruff +deps = ruff +commands = ruff . + +[testenv:docs] +basepython = python3.11 +allowlist_externals = make +setenv = + PYTHONWARNINGS=default +commands = + make docs +deps = + -r{toxinidir}/docs/requirements.txt