diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 66e8eda0..96a6c173 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -6,20 +6,17 @@ labels: assignees: - codingjoe body: - - type: markdown attributes: value: | Thank you for taking the time to report a bug. Please fill in as much of the template below as you're able. - - type: markdown attributes: value: | ## Security issues Please do not report security issues here. Instead, disclose them as described in our [security policy](https://github.com/codingjoe/django-select2/security). - - type: textarea id: bug-description attributes: @@ -28,7 +25,6 @@ body: placeholder: I found a bug validations: required: true - - type: textarea id: bug-steps attributes: @@ -41,7 +37,6 @@ body: 4. See error validations: required: true - - type: textarea id: bug-expected attributes: diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3f541100..37267004 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,14 +1,14 @@ version: 2 updates: -- package-ecosystem: pip - directory: "/" - schedule: - interval: daily -- package-ecosystem: npm - directory: "/" - schedule: - interval: daily -- package-ecosystem: github-actions - directory: "/" - schedule: - interval: daily + - package-ecosystem: pip + directory: "/" + schedule: + interval: daily + - package-ecosystem: npm + directory: "/" + schedule: + interval: daily + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: daily diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f01a32ba..4c702527 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,40 +4,17 @@ on: branches: - main pull_request: - jobs: - - lint: - runs-on: ubuntu-latest - strategy: - matrix: - lint-command: - - bandit -r . -x ./tests - - black --check --diff . - - flake8 . - - isort --check-only --diff . - - pydocstyle . - steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: "3.x" - cache: 'pip' - cache-dependency-path: 'linter-requirements.txt' - - run: python -m pip install -r linter-requirements.txt - - run: ${{ matrix.lint-command }} - dist: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: astral-sh/setup-uv@v7 + - run: uvx --from build pyproject-build --sdist --wheel + - run: uvx twine check dist/* + - uses: actions/upload-artifact@v6 with: - python-version: "3.x" - - run: python -m pip install --upgrade pip build wheel twine readme-renderer - - run: python -m build --sdist --wheel - - run: python -m twine check dist/* - + path: dist/* standardjs: runs-on: ubuntu-latest steps: @@ -47,21 +24,15 @@ jobs: node-version-file: '.nvmrc' - run: npm install -g standard - run: standard - docs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 - with: - python-version: "3.10" - run: sudo apt-get install -y gettext graphviz - - run: python -m pip install -e .[docs] - - run: python -m sphinx -W -b doctest -b html docs docs/_build - + - uses: astral-sh/setup-uv@v7 + - run: uv run sphinx-build -W -b doctest -b html docs docs/_build PyTest: needs: - - lint - standardjs strategy: matrix: @@ -76,22 +47,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: astral-sh/setup-uv@v7 with: python-version: ${{ matrix.python-version }} - - run: python -m pip install Django~="${{ matrix.django-version }}.0" - - run: python -m pip install -e .[test] - - run: python -m pytest -m "not selenium" + - run: uv run --with Django~=${{ matrix.django-version }}.0 pytest -m "not selenium" - uses: codecov/codecov-action@v5 - Selenium: needs: - - lint - standardjs - strategy: - matrix: - python-version: - - "3.x" runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 @@ -99,10 +62,6 @@ jobs: run: | curl -LsSfO https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb sudo dpkg -i google-chrome-stable_current_amd64.deb || sudo apt-get -f install -y - - uses: actions/setup-python@v6 - with: - python-version: ${{ matrix.python-version }} - - run: python -m pip install Django - - run: python -m pip install -e .[test,selenium] - - run: python -m pytest -m selenium + - uses: astral-sh/setup-uv@v7 + - run: uv run pytest -m selenium - uses: codecov/codecov-action@v5 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index cc22e328..728481ed 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,14 +1,11 @@ name: Release - on: release: types: [published] workflow_dispatch: - jobs: pypi-build: runs-on: ubuntu-latest - steps: - uses: actions/checkout@v6 - uses: actions/setup-python@v6 @@ -20,21 +17,18 @@ jobs: with: name: release-dists path: dist/ - pypi-publish: runs-on: ubuntu-latest needs: - pypi-build permissions: id-token: write - steps: - uses: actions/download-artifact@v7 with: name: release-dists path: dist/ - uses: pypa/gh-action-pypi-publish@release/v1 - npmjs: name: npmjs.org runs-on: ubuntu-latest diff --git a/.gitignore b/.gitignore index 8c43d48c..d0341cdf 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,6 @@ coverage.xml db.sqlite3 _version.py + +# uv +uv.lock diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..01f6a5e7 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,45 @@ +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: trailing-whitespace + - id: check-merge-conflict + - id: check-ast + - id: check-toml + - id: check-yaml + - id: check-symlinks + - id: debug-statements + - id: end-of-file-fixer + - id: no-commit-to-branch + args: [--branch, main] + - repo: https://github.com/asottile/pyupgrade + rev: v3.21.2 + hooks: + - id: pyupgrade + - repo: https://github.com/adamchainz/django-upgrade + rev: 1.29.1 + hooks: + - id: django-upgrade + - repo: https://github.com/hukkin/mdformat + rev: 1.0.0 + hooks: + - id: mdformat + additional_dependencies: + - mdformat-ruff + - mdformat-footnote + - mdformat-gfm + - mdformat-gfm-alerts + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.14.9 + hooks: + - id: ruff-check + args: [--fix, --exit-non-zero-on-fix] + - id: ruff-format + - repo: https://github.com/google/yamlfmt + rev: v0.20.0 + hooks: + - id: yamlfmt +ci: + autoupdate_schedule: weekly + skip: + - no-commit-to-branch diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 9b618d15..4a80c747 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -1,23 +1,16 @@ # .readthedocs.yaml # Read the Docs configuration file # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details - version: 2 - build: - os: ubuntu-20.04 + os: ubuntu-24.04 apt_packages: - graphviz tools: - python: "3.10" - -sphinx: - configuration: docs/conf.py - - -python: - install: - - method: pip - path: . - extra_requirements: - - docs + python: "3" + jobs: + install: + - curl -LsSf https://astral.sh/uv/install.sh | sh + build: + html: + - $HOME/.local/bin/uv run sphinx-build -b html docs $READTHEDOCS_OUTPUT/html diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index f4367f9c..67782599 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -9,19 +9,13 @@ you have binary dependencies installed:: # macOS brew install -y gettext graphviz google-chrome-stable -To install the package and its dependencies for development -including tests dependencies, please do: +You may run the tests via:: - python -m pip install -e .[test] - -You may ran the tests via:: - - python -m pytest + uv run pytest Documentation pull requests welcome. The Sphinx documentation can be compiled via:: - python -m pip install -e .[docs] - python -m sphinx -W -b doctest -b html docs docs/_build + uv run sphinx-build -W -b doctest -b html docs docs/_build/html Bug reports welcome, even more so if they include a correct patch. Much more so if you start your patch by adding a failing unit test, and correct diff --git a/MANIFEST.in b/MANIFEST.in index 45907113..371ff035 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,4 +2,3 @@ include django_select2/static/django_select2/django_select2.js include django_select2/static/django_select2/django_select2.css prune .github exclude .* - diff --git a/docs/conf.py b/docs/conf.py index 845ceecd..1dc16c21 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,7 +2,7 @@ import pathlib import sys -from pkg_resources import get_distribution +from django_select2 import __version__ as release BASE_DIR = pathlib.Path(__file__).resolve(strict=True).parent.parent @@ -20,12 +20,9 @@ project = "Django-Select2" -author = "Johannes Hoppe" -copyright = "2017-2020, Johannes Hoppe" -release = get_distribution("django_select2").version +author = "Johannes Maron" version = ".".join(release.split(".")[:2]) - master_doc = "index" # default in Sphinx v2 diff --git a/docs/extra.rst b/docs/extra.rst index 4de25275..6555189c 100644 --- a/docs/extra.rst +++ b/docs/extra.rst @@ -30,7 +30,7 @@ Here are our two models: Customizing a Form `````````````````` -Lets link two widgets via a *dependent_fields* dictionary. The key represents the name of +Lets link two widgets via a *dependent_fields* dictionary. The key represents the name of the field in the form. The value represents the name of the field in the model (used in `queryset`). .. code-block:: python @@ -122,4 +122,3 @@ Furthermore you may want to filter options on two or more select2 selections (so dependent_fields={'field1': 'field1', 'field2': 'field2'}, ) ) - diff --git a/example/manage.py b/example/manage.py index c6b69b9c..7aab30fd 100755 --- a/example/manage.py +++ b/example/manage.py @@ -1,5 +1,6 @@ #!/usr/bin/env python """Django's command-line utility for administrative tasks.""" + import os import sys diff --git a/pyproject.toml b/pyproject.toml index 2f0ff4da..efd8eb04 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,16 +35,17 @@ dependencies = [ "django-appconf>=0.6.0" ] -[project.optional-dependencies] +[dependency-groups] +dev = [ + { include-group = "test" }, + { include-group = "docs" }, +] test = [ "pytest", "pytest-cov", "pytest-django", "selenium", ] -selenium = [ - "selenium", -] docs = [ "sphinx", ] diff --git a/tests/test_forms.py b/tests/test_forms.py index 081f1ff6..36a61a27 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -271,9 +271,7 @@ def test_selected_option(self, db): in not_required_field.widget.render("primary_genre", 1) or '' in not_required_field.widget.render("primary_genre", 1) - ), not_required_field.widget.render( - "primary_genre", 1 - ) + ), not_required_field.widget.render("primary_genre", 1) def test_many_selected_option(self, db, genres): field = HeavySelect2MultipleWidgetForm().fields["genres"] @@ -296,9 +294,9 @@ def test_many_selected_option(self, db, genres): pk=2, value="Two" ) - assert ( - selected_option in widget_output or selected_option_a in widget_output - ), widget_output + assert selected_option in widget_output or selected_option_a in widget_output, ( + widget_output + ) assert selected_option2 in widget_output or selected_option2a in widget_output @pytest.mark.selenium @@ -412,9 +410,9 @@ def test_selected_option(self, db, genres): pk=genre2.pk, value=force_str(genre2) ) - assert ( - selected_option in widget_output or selected_option_a in widget_output - ), widget_output + assert selected_option in widget_output or selected_option_a in widget_output, ( + widget_output + ) assert unselected_option not in widget_output def test_selected_option_label_from_instance(self, db, genres):