diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml deleted file mode 100644 index 84128c0..0000000 --- a/.github/workflows/action.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: Python package - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - test: - runs-on: ubuntu-latest - strategy: - matrix: - python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] - django-version: ['3.2', '4.0', '4.1', '4.2', '5.0'] - services: - postgres: - image: postgres:12 - ports: - - 5432:5432 - options: >- - --health-cmd=pg_isready - --health-interval=10s - --health-timeout=5s - --health-retries=5 - env: - POSTGRES_DB: testdb - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres - mysql: - image: mysql:8 - ports: - - 3306:3306 - options: >- - --health-cmd="mysqladmin ping" - --health-interval=10s - --health-timeout=5s - --health-retries=5 - env: - MYSQL_USER: travis - MYSQL_PASSWORD: travis - MYSQL_ALLOW_EMPTY_PASSWORD: true - MYSQL_DATABASE: test_testdb - steps: - - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 - with: - python-version: ${{ matrix.python-version }} - - name: Test versions Python ${{ matrix.python-version }} Django ${{ matrix.django-version }} - shell: bash - run: | - if [[ "${{ matrix.python-version }}" == "3.8" && "${{ matrix.django-version }}" == "5.0" ]]; then - echo "Skipping unsupported Python/Django combination" - exit 0 - elif [[ "${{ matrix.python-version }}" == "3.9" && "${{ matrix.django-version }}" == "5.0" ]]; then - echo "Skipping unsupported Python/Django combination" - exit 0 - elif [[ "${{ matrix.python-version }}" == "3.11" && ( "${{ matrix.django-version }}" == "3.2" || "${{ matrix.django-version }}" == "4.0" ) ]]; then - echo "Skipping unsupported Python/Django combination" - exit 0 - elif [[ "${{ matrix.python-version }}" == "3.12" && ( "${{ matrix.django-version }}" == "3.2" || "${{ matrix.django-version }}" == "4.0" || "${{ matrix.django-version }}" == "4.1" ) ]]; then - echo "Skipping unsupported Python/Django combination" - exit 0 - fi - - pip install Django==${{ matrix.django-version }} mysqlclient psycopg2 - pip install flake8 pylint pytest pytest-django - - if [[ "${{ matrix.python-version }}" == "3.12" ]]; then - pip install setuptools - fi - - pip install -e . - python setup.py test - ./lint.sh \ No newline at end of file diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..9887549 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,89 @@ +name: Client Build, Publish, and Release + +on: + workflow_dispatch: + inputs: + tag: + description: "Release tag (for example: 1.1.1)" + required: true + type: string + release_name: + description: "Release name (defaults to tag if empty)" + required: false + default: "" + type: string + prerelease: + description: "Mark as prerelease" + required: true + default: false + type: boolean + +jobs: + build: + name: Build package distributions + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Install Poetry + run: | + make poetry + - name: Install dependencies + run: | + make install-build + - name: Build package + run: | + make build + - name: Upload dist artifacts + uses: actions/upload-artifact@v4 + with: + name: python-dist + path: dist/* + if-no-files-found: error + + pypi-publish: + name: Upload release to public PyPI + runs-on: ubuntu-latest + needs: build + environment: + name: pypi + url: https://pypi.org/p/django-livefield + permissions: + id-token: write + steps: + - name: Download dist artifacts + uses: actions/download-artifact@v4 + with: + name: python-dist + path: dist + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + + create-github-release: + name: Create GitHub release + runs-on: ubuntu-latest + needs: + - pypi-publish + permissions: + contents: write + steps: + - name: Download dist artifacts + uses: actions/download-artifact@v4 + with: + name: python-dist + path: dist + - name: Create release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ inputs.tag }} + name: ${{ inputs.release_name || inputs.tag }} + target_commitish: ${{ github.sha }} + prerelease: ${{ inputs.prerelease }} + generate_release_notes: true + files: dist/* diff --git a/.github/workflows/python-version-tests.yml b/.github/workflows/python-version-tests.yml new file mode 100644 index 0000000..3acddc0 --- /dev/null +++ b/.github/workflows/python-version-tests.yml @@ -0,0 +1,85 @@ +name: Python Version Tests + +on: + push: + branches: ["master"] + pull_request: + branches: ["master"] + workflow_dispatch: + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] + django-version: ['3.2', '4.0', '4.1', '4.2', '5.0'] + exclude: + - python-version: '3.8' + django-version: '5.0' + - python-version: '3.9' + django-version: '5.0' + - python-version: '3.11' + django-version: '3.2' + - python-version: '3.11' + django-version: '4.0' + - python-version: '3.12' + django-version: '3.2' + - python-version: '3.12' + django-version: '4.0' + - python-version: '3.12' + django-version: '4.1' + services: + postgres: + image: postgres:12 + ports: + - 5432:5432 + options: >- + --health-cmd=pg_isready + --health-interval=10s + --health-timeout=5s + --health-retries=5 + env: + POSTGRES_DB: testdb + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + mysql: + image: mysql:8 + ports: + - 3306:3306 + options: >- + --health-cmd="mysqladmin ping" + --health-interval=10s + --health-timeout=5s + --health-retries=5 + env: + MYSQL_USER: travis + MYSQL_PASSWORD: travis + MYSQL_ALLOW_EMPTY_PASSWORD: true + MYSQL_DATABASE: test_testdb + + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + - name: Install Poetry + run: | + make poetry + - name: Install dependencies + run: | + make install-dev + - name: Pin Django version + run: | + poetry run pip install "Django==${{ matrix.django-version }}" + - name: Lint with flake8 and pylint + run: | + make lint + - name: Test with custom bootstrap runner + run: | + make test diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 0000000..43d023f --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,13 @@ +Developed and maintained by [Hearsay Social, Inc.](http://hearsaysocial.com). + +## Contributors + +- [Adam DePue](http://github.com/adepue) +- [Akshay Shah](http://github.com/akshayjshah) +- [Cordelia Notbohm](http://github.com/cnotbohm) +- [John Lynn](http://github.com/jlynn) +- [Dylan Verheul](http://github.com/dyve) +- [Grant McConnaughey](http://github.com/grantmcconnaughey) +- [Luke Burden](http://github.com/lukeburden) +- [James Addison](http://github.com/jaddison) +- [Krisztian Csizmazia](http://github.com/csizmaziakiki) diff --git a/AUTHORS.rst b/AUTHORS.rst deleted file mode 100644 index d8e22d2..0000000 --- a/AUTHORS.rst +++ /dev/null @@ -1,13 +0,0 @@ -Developed and maintained by `Hearsay Social, Inc. -`_. - -Contributors -============ -| `Adam DePue `_ -| `Akshay Shah `_ -| `John Lynn `_ -| `Dylan Verheul `_ -| `Grant McConnaughey `_ -| `Luke Burden `_ -| `James Addison `_ -| `Krisztian Csizmazia `_ \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..4f391a3 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,75 @@ +# Changelog + +## 4.2.0 +- Migrate to Poetry for building and publishing + +## 4.1.0 + +- Add support for Python 3.12 +- Add support for Django 5.0 + +## 4.0.0 + +- Add support for Python 3.8 - 3.11 +- Add support for Django 4.1 and 4.2 +- Remove support for old Django versions +- Remove support for old Python versions + +## 3.3.0 + +- Django 3.x support +- switch to BooleanField as base (Django 4.x deprecation) + +## 3.2.1 + +- Fix rST formatting in this file to pass PyPI rendering check + +## 3.2.0 (Not released) + +- Support Django 2.2 +- Support Python 3.7 +- Fix metadata to remove deprecated Django versions +- Expand travis tests for versions and database engines +- Remove obsolete pylint suppressions +- Thanks to [@shurph](https://github.com/shurph) for the above! + +## 3.1.0 + +- Fix [deprecation of context param for Field.from_db_value](https://code.djangoproject.com/ticket/28370) +- Support for Django 2.1 (Thanks [@lukeburden](https://github.com/lukeburden) +- Switch tests suite to use pytest +- Remove pylint-django plugin, no longer needed + +## 3.0.0 + +- Add support for Python 3.6 +- Add support for Django 2.0 +- Remove support for Python 3.4 +- Remove support for old Django versions +- Remove GIS + +## 2.5.0 (Not released) + +- Added official Python 3 support. +- Re-added support for Django 1.8. Now supports Django 1.8 and 1.9. + +## 2.4.0 (2016-02-11) + +- Drop support for Django 1.8 +- Add number of affected rows for delete methods (hard_delete, soft_delete, delete). Note: Django 1.9+ only. + +## 2.1.0 (2014-09-04) + +- Add support for Django 1.7. + +## 2.0.0 (2014-07-13) + +- Renamed top-level namespace to `livefield`. +- Restructured internally to match Django convention. +- Added GIS support. +- Added South support. + +## 1.0.0 (2014-02-14) + +- Initial release. +- Separated existing code from main application repository. diff --git a/CHANGELOG.rst b/CHANGELOG.rst deleted file mode 100644 index 8a6f3ae..0000000 --- a/CHANGELOG.rst +++ /dev/null @@ -1,74 +0,0 @@ -Changelog -========= - -4.1.0 --------------------- - - Add support for Python 3.12 - - Add support for Django 5.0 - -4.0.0 --------------------- - - Add support for Python 3.8 - 3.11 - - Add support for Django 4.1 and 4.2 - - Remove support for old Django versions - - Remove support for old Python versions - -3.3.0 --------------------- - - Django 3.x support - - switch to BooleanField as base (Django 4.x deprecation) - -3.2.1 --------------------- - - Fix rST formatting in this file to pass PyPI rendering check - -3.2.0 (Not released) --------------------- - - Support Django 2.2 - - Support Python 3.7 - - Fix metadata to remove deprecated Django versions - - Expand travis tests for versions and database engines - - Remove obsolete pylint suppressions - - Thanks to [@shurph](https://github.com/shurph) for the above! - -3.1.0 --------------------- - - Fix [deprecation of context param for Field.from_db_value](https://code.djangoproject.com/ticket/28370) - - Support for Django 2.1 (Thanks [@lukeburden](https://github.com/lukeburden) - - Switch tests suite to use pytest - - Remove pylint-django plugin, no longer needed - -3.0.0 --------------------- - - Add support for Python 3.6 - - Add support for Django 2.0 - - Remove support for Python 3.4 - - Remove support for old Django versions - - Remove GIS - - -2.5.0 (Not released) --------------------- - - Added official Python 3 support. - - Re-added support for Django 1.8. Now supports Django 1.8 and 1.9. - -2.4.0 (2016-02-11) --------------------- - - Drop support for Django 1.8 - - Add number of affected rows for delete methods (hard_delete, soft_delete, delete). Note: Django 1.9+ only. - -2.1.0 (2014-09-04) --------------------- - - Add support for Django 1.7. - -2.0.0 (2014-07-13) --------------------- - - Renamed top-level namespace to ``livefield``. - - Restructured internally to match Django convention. - - Added GIS support. - - Added South support. - -1.0.0 (2014-02-14) --------------------- - - Initial release. - - Separated existing code from main application repository. diff --git a/MANIFEST.in b/MANIFEST.in index 98c429d..b9c7b4a 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1 +1 @@ -include *.rst LICENSE.txt +include *.md LICENSE.txt diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..60fdd5b --- /dev/null +++ b/Makefile @@ -0,0 +1,32 @@ +REPO = $(shell git rev-parse --show-toplevel) +POETRY = poetry + +install-build: + ${POETRY} install --only=main + +install-dev: + ${POETRY} install + +poetry: + curl -sSL https://install.python-poetry.org | POETRY_VERSION=1.8.4 python3 - + poetry cache clear pypi --all + poetry config virtualenvs.in-project true + +quickstart: poetry install-dev + +quickstart-build: poetry install-build + +clean: + # Delete all .pyc and .pyo files. + find ${REPO} \( -name "*~" -o -name "*.py[co]" -o -name ".#*" -o -name "#*#" \) -exec rm -f '{}' + + rm -rf build dist src/django_livefield.egg-info django_livefield.egg-info + +lint: clean + ${POETRY} run flake8 --config=${REPO}/setup.cfg ${REPO}/src/livefield/ ${REPO}/tests/ + ${POETRY} run pylint --rcfile=${REPO}/pylint.rc ${REPO}/src/livefield/ ${REPO}/tests/ + +test: clean + ${POETRY} run python ${REPO}/tests/run_tests.py + +build: + ${POETRY} build diff --git a/README.md b/README.md new file mode 100644 index 0000000..3fd12a9 --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +# django-livefield + +## About + +A Django field that enables convenient soft-deletion. For Python 3.8+ and Django 3.2+ + +## Installation + +Simple: `pip install django-livefield`. + +## Example Usage + +```python +>>> from django.db import models +>>> from livefield import LiveField, LiveManager +>>> +>>> +>>> class Person(models.Model): +... name = models.CharField() +... live = LiveField() +... +... objects = LiveManager() +... all_objects = LiveManager(include_soft_deleted=True) +... +... class Meta: +... unique_together = ('name', 'live') +... +... def delete(self, using=None): +... self.live = False +... self.save(using=using) +... +>>> john = Person.objects.create(name='John Cleese') +>>> doppelganger = Person(name='John Cleese') +>>> doppelganger.save() # Raises an IntegrityError +>>> john.delete() +>>> doppelganger.save() # Succeeds! +``` + +## License + +MIT. See LICENSE.txt for details. + +## Contributing + +Pull requests welcome! To save everyone some hassle, please open an issue first so we can discuss your proposed change. + +In your PR, be sure to add your name to AUTHORS.md and include some tests for your spiffy new functionality. CI will green-light your build once it passes the unit tests (`make test`) and our linters (`make lint`). diff --git a/README.rst b/README.rst deleted file mode 100644 index 22de83e..0000000 --- a/README.rst +++ /dev/null @@ -1,58 +0,0 @@ -================ -django-livefield -================ - -===== -About -===== -A Django field that enables convenient soft-deletion. For Python 2.7/3.3+ and Django 1.8+ - -============ -Installation -============ -Simple: ``pip install django-livefield``. - -============= -Example Usage -============= -.. code:: python - - >>> from django.db import models - >>> from livefield import LiveField, LiveManager - >>> - >>> - >>> class Person(models.Model): - ... name = models.CharField() - ... live = LiveField() - ... - ... objects = LiveManager() - ... all_objects = LiveManager(include_soft_deleted=True) - ... - ... class Meta: - ... unique_together = ('name', 'live') - ... - ... def delete(self, using=None): - ... self.live = False - ... self.save(using=using) - ... - >>> john = Person.objects.create(name='John Cleese') - >>> doppelganger = Person(name='John Cleese') - >>> doppelganger.save() # Raises an IntegrityError - >>> john.delete() - >>> doppelganger.save() # Succeeds! - -======= -License -======= -MIT. See LICENSE.txt for details. - -============ -Contributing -============ -Pull requests welcome! To save everyone some hassle, please open an -issue first so we can discuss your proposed change. - -In your PR, be sure to add your name to AUTHORS.txt and include some -tests for your spiffy new functionality. CI will green-light your -build once it passes the unit tests (``./setup.py test``) and our -linters (``./lint.sh``). diff --git a/build.sh b/build.sh deleted file mode 100755 index f0fb26c..0000000 --- a/build.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env sh - -# Safer to update these separately. -pip install -U "setuptools" -pip install -U "wheel" -pip install -U "pip" - -./setup.py sdist -./setup.py bdist_wheel diff --git a/lint.sh b/lint.sh deleted file mode 100755 index cb06e9f..0000000 --- a/lint.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env sh - -flake8 tests src setup.py -if [ $? -ne 0 ]; then - echo "Flake8 linting failed." - exit 1 -fi - -pylint --rcfile=pylint.rc src/livefield -if [ $? -ne 0 ]; then - echo "PyLint found errors in src/." - exit 1 -fi - -pylint --rcfile=pylint.rc tests -if [ $? -ne 0 ]; then - echo "PyLint found errors in test/." - exit 1 -fi - -pylint --rcfile=pylint.rc setup.py -if [ $? -ne 0 ]; then - echo "PyLint found errors in setup.py." - exit 1 -fi diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..2fec3da --- /dev/null +++ b/poetry.lock @@ -0,0 +1,434 @@ +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. + +[[package]] +name = "asgiref" +version = "3.8.1" +description = "ASGI specs, helper code, and adapters" +optional = false +python-versions = ">=3.8" +files = [ + {file = "asgiref-3.8.1-py3-none-any.whl", hash = "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47"}, + {file = "asgiref-3.8.1.tar.gz", hash = "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4", markers = "python_version < \"3.11\""} + +[package.extras] +tests = ["mypy (>=0.800)", "pytest", "pytest-asyncio"] + +[[package]] +name = "astroid" +version = "3.2.4" +description = "An abstract syntax tree for Python with inference support." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "astroid-3.2.4-py3-none-any.whl", hash = "sha256:413658a61eeca6202a59231abb473f932038fbcbf1666587f66d482083413a25"}, + {file = "astroid-3.2.4.tar.gz", hash = "sha256:0e14202810b30da1b735827f78f5157be2bbd4a7a59b7707ca0bfc2fb4c0063a"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""} + +[[package]] +name = "backports-zoneinfo" +version = "0.2.1" +description = "Backport of the standard library zoneinfo module" +optional = false +python-versions = ">=3.6" +files = [ + {file = "backports.zoneinfo-0.2.1-cp36-cp36m-macosx_10_14_x86_64.whl", hash = "sha256:da6013fd84a690242c310d77ddb8441a559e9cb3d3d59ebac9aca1a57b2e18bc"}, + {file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:89a48c0d158a3cc3f654da4c2de1ceba85263fafb861b98b59040a5086259722"}, + {file = "backports.zoneinfo-0.2.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:1c5742112073a563c81f786e77514969acb58649bcdf6cdf0b4ed31a348d4546"}, + {file = "backports.zoneinfo-0.2.1-cp36-cp36m-win32.whl", hash = "sha256:e8236383a20872c0cdf5a62b554b27538db7fa1bbec52429d8d106effbaeca08"}, + {file = "backports.zoneinfo-0.2.1-cp36-cp36m-win_amd64.whl", hash = "sha256:8439c030a11780786a2002261569bdf362264f605dfa4d65090b64b05c9f79a7"}, + {file = "backports.zoneinfo-0.2.1-cp37-cp37m-macosx_10_14_x86_64.whl", hash = "sha256:f04e857b59d9d1ccc39ce2da1021d196e47234873820cbeaad210724b1ee28ac"}, + {file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:17746bd546106fa389c51dbea67c8b7c8f0d14b5526a579ca6ccf5ed72c526cf"}, + {file = "backports.zoneinfo-0.2.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:5c144945a7752ca544b4b78c8c41544cdfaf9786f25fe5ffb10e838e19a27570"}, + {file = "backports.zoneinfo-0.2.1-cp37-cp37m-win32.whl", hash = "sha256:e55b384612d93be96506932a786bbcde5a2db7a9e6a4bb4bffe8b733f5b9036b"}, + {file = "backports.zoneinfo-0.2.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a76b38c52400b762e48131494ba26be363491ac4f9a04c1b7e92483d169f6582"}, + {file = "backports.zoneinfo-0.2.1-cp38-cp38-macosx_10_14_x86_64.whl", hash = "sha256:8961c0f32cd0336fb8e8ead11a1f8cd99ec07145ec2931122faaac1c8f7fd987"}, + {file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e81b76cace8eda1fca50e345242ba977f9be6ae3945af8d46326d776b4cf78d1"}, + {file = "backports.zoneinfo-0.2.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7b0a64cda4145548fed9efc10322770f929b944ce5cee6c0dfe0c87bf4c0c8c9"}, + {file = "backports.zoneinfo-0.2.1-cp38-cp38-win32.whl", hash = "sha256:1b13e654a55cd45672cb54ed12148cd33628f672548f373963b0bff67b217328"}, + {file = "backports.zoneinfo-0.2.1-cp38-cp38-win_amd64.whl", hash = "sha256:4a0f800587060bf8880f954dbef70de6c11bbe59c673c3d818921f042f9954a6"}, + {file = "backports.zoneinfo-0.2.1.tar.gz", hash = "sha256:fadbfe37f74051d024037f223b8e001611eac868b5c5b06144ef4d8b799862f2"}, +] + +[package.extras] +tzdata = ["tzdata"] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "dill" +version = "0.4.0" +description = "serialize all of Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049"}, + {file = "dill-0.4.0.tar.gz", hash = "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] +profile = ["gprof2dot (>=2022.7.29)"] + +[[package]] +name = "dill" +version = "0.4.1" +description = "serialize all of Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "dill-0.4.1-py3-none-any.whl", hash = "sha256:1e1ce33e978ae97fcfcff5638477032b801c46c7c65cf717f95fbc2248f79a9d"}, + {file = "dill-0.4.1.tar.gz", hash = "sha256:423092df4182177d4d8ba8290c8a5b640c66ab35ec7da59ccfa00f6fa3eea5fa"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] +profile = ["gprof2dot (>=2022.7.29)"] + +[[package]] +name = "django" +version = "4.2.29" +description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." +optional = false +python-versions = ">=3.8" +files = [ + {file = "django-4.2.29-py3-none-any.whl", hash = "sha256:074d7c4d2808050e528388bda442bd491f06def4df4fe863f27066851bba010c"}, + {file = "django-4.2.29.tar.gz", hash = "sha256:86d91bc8086569c8d08f9c55888b583a921ac1f95ed3bdc7d5659d4709542014"}, +] + +[package.dependencies] +asgiref = ">=3.6.0,<4" +"backports.zoneinfo" = {version = "*", markers = "python_version < \"3.9\""} +sqlparse = ">=0.3.1" +tzdata = {version = "*", markers = "sys_platform == \"win32\""} + +[package.extras] +argon2 = ["argon2-cffi (>=19.1.0)"] +bcrypt = ["bcrypt"] + +[[package]] +name = "exceptiongroup" +version = "1.3.1" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, + {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, +] + +[package.dependencies] +typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "flake8" +version = "5.0.4" +description = "the modular source code checker: pep8 pyflakes and co" +optional = false +python-versions = ">=3.6.1" +files = [ + {file = "flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248"}, + {file = "flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db"}, +] + +[package.dependencies] +mccabe = ">=0.7.0,<0.8.0" +pycodestyle = ">=2.9.0,<2.10.0" +pyflakes = ">=2.5.0,<2.6.0" + +[[package]] +name = "iniconfig" +version = "2.1.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.8" +files = [ + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, +] + +[[package]] +name = "isort" +version = "5.13.2" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.13.2-py3-none-any.whl", hash = "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6"}, + {file = "isort-5.13.2.tar.gz", hash = "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109"}, +] + +[package.extras] +colors = ["colorama (>=0.4.6)"] + +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +optional = false +python-versions = ">=3.6" +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + +[[package]] +name = "packaging" +version = "26.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529"}, + {file = "packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"}, +] + +[[package]] +name = "platformdirs" +version = "4.3.6" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.8" +files = [ + {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, + {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.2)", "pytest-cov (>=5)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.11.2)"] + +[[package]] +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pycodestyle" +version = "2.9.1" +description = "Python style guide checker" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b"}, + {file = "pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785"}, +] + +[[package]] +name = "pyflakes" +version = "2.5.0" +description = "passive checker of Python programs" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2"}, + {file = "pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3"}, +] + +[[package]] +name = "pylint" +version = "3.2.7" +description = "python code static checker" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "pylint-3.2.7-py3-none-any.whl", hash = "sha256:02f4aedeac91be69fb3b4bea997ce580a4ac68ce58b89eaefeaf06749df73f4b"}, + {file = "pylint-3.2.7.tar.gz", hash = "sha256:1b7a721b575eaeaa7d39db076b6e7743c993ea44f57979127c517c6c572c803e"}, +] + +[package.dependencies] +astroid = ">=3.2.4,<=3.3.0-dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = [ + {version = ">=0.2", markers = "python_version < \"3.11\""}, + {version = ">=0.3.7", markers = "python_version >= \"3.12\""}, + {version = ">=0.3.6", markers = "python_version >= \"3.11\" and python_version < \"3.12\""}, +] +isort = ">=4.2.5,<5.13.0 || >5.13.0,<6" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2.0" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +tomlkit = ">=0.10.1" +typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] + +[[package]] +name = "pytest" +version = "8.3.5" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"}, + {file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=1.5,<2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-django" +version = "4.11.1" +description = "A Django plugin for pytest." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest_django-4.11.1-py3-none-any.whl", hash = "sha256:1b63773f648aa3d8541000c26929c1ea63934be1cfa674c76436966d73fe6a10"}, + {file = "pytest_django-4.11.1.tar.gz", hash = "sha256:a949141a1ee103cb0e7a20f1451d355f83f5e4a5d07bdd4dcfdd1fd0ff227991"}, +] + +[package.dependencies] +pytest = ">=7.0.0" + +[package.extras] +docs = ["sphinx", "sphinx_rtd_theme"] +testing = ["Django", "django-configurations (>=2.0)"] + +[[package]] +name = "sqlparse" +version = "0.5.5" +description = "A non-validating SQL parser." +optional = false +python-versions = ">=3.8" +files = [ + {file = "sqlparse-0.5.5-py3-none-any.whl", hash = "sha256:12a08b3bf3eec877c519589833aed092e2444e68240a3577e8e26148acc7b1ba"}, + {file = "sqlparse-0.5.5.tar.gz", hash = "sha256:e20d4a9b0b8585fdf63b10d30066c7c94c5d7a7ec47c889a2d83a3caa93ff28e"}, +] + +[package.extras] +dev = ["build"] +doc = ["sphinx"] + +[[package]] +name = "tomli" +version = "2.4.0" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867"}, + {file = "tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9"}, + {file = "tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95"}, + {file = "tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76"}, + {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d"}, + {file = "tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576"}, + {file = "tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a"}, + {file = "tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa"}, + {file = "tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614"}, + {file = "tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1"}, + {file = "tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8"}, + {file = "tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a"}, + {file = "tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1"}, + {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b"}, + {file = "tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51"}, + {file = "tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729"}, + {file = "tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da"}, + {file = "tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3"}, + {file = "tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0"}, + {file = "tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e"}, + {file = "tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4"}, + {file = "tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e"}, + {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c"}, + {file = "tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f"}, + {file = "tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86"}, + {file = "tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87"}, + {file = "tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132"}, + {file = "tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6"}, + {file = "tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc"}, + {file = "tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66"}, + {file = "tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d"}, + {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702"}, + {file = "tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8"}, + {file = "tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776"}, + {file = "tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475"}, + {file = "tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2"}, + {file = "tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9"}, + {file = "tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0"}, + {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df"}, + {file = "tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d"}, + {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f"}, + {file = "tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b"}, + {file = "tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087"}, + {file = "tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd"}, + {file = "tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4"}, + {file = "tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a"}, + {file = "tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c"}, +] + +[[package]] +name = "tomlkit" +version = "0.13.3" +description = "Style preserving TOML library" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tomlkit-0.13.3-py3-none-any.whl", hash = "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0"}, + {file = "tomlkit-0.13.3.tar.gz", hash = "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1"}, +] + +[[package]] +name = "typing-extensions" +version = "4.13.2" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +files = [ + {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, + {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, +] + +[[package]] +name = "tzdata" +version = "2025.3" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1"}, + {file = "tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7"}, +] + +[metadata] +lock-version = "2.0" +python-versions = ">=3.8,<4.0" +content-hash = "ea6184e707c4482a8a229cb3b59dcf3bab7a478b55e9ac303565ad4d719a0deb" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..b19c60b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,41 @@ +[tool.poetry] +name = "django-livefield" +version = "4.2.0" +description = "Convenient soft-deletion support for Django models" +authors = ["Hearsay Social "] +license = "MIT" +readme = "README.md" +keywords = ["python", "django", "soft-delete"] +packages = [ + { include = "livefield", from = "src" } +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Framework :: Django :: 3.2", + "Framework :: Django :: 4.0", + "Framework :: Django :: 4.1", + "Framework :: Django :: 4.2", + "Framework :: Django :: 5.0", + "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" +] + +[tool.poetry.urls] +"Github Repo" = "https://github.com/hearsaycorp/django-livefield" + +[tool.poetry.dependencies] +python = ">=3.8,<4.0" +Django = ">=3.2,<5.1" + +[tool.poetry.group.dev.dependencies] +flake8 = "*" +pylint = "*" +pytest = "*" +pytest-django = "*" + +[build-system] +requires = ["poetry-core>=1.1.0"] +build-backend = "poetry.core.masonry.api" diff --git a/setup.py b/setup.py deleted file mode 100755 index afa77af..0000000 --- a/setup.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python - -import multiprocessing # noqa -import os -import sys - -from setuptools import setup, find_packages -from setuptools.command.test import test as TestCommand - - -tests_require = ( - 'pytest', - 'pytest-django' -) - - -install_requires = ( - 'Django>=3.2,<5.1', -) - - -class DjangoTest(TestCommand): - DIRNAME = os.path.dirname(__file__) - APPS = ('tests',) - - def finalize_options(self): - TestCommand.finalize_options(self) - self.test_args = [] - self.test_suite = True - - def run_tests(self): - from django.conf import settings - - db_engine = os.environ.get('DJANGO_DB_ENGINE', 'sqlite') - if db_engine == 'mysql': - db_settings = { - 'ENGINE': 'django.db.backends.mysql', - 'NAME': os.environ['DJANGO_DB_NAME'], - 'USER': os.environ['DJANGO_DB_USER'], - } - elif db_engine == 'postgres': - db_settings = { - 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': os.environ['DJANGO_DB_NAME'], - 'USER': os.environ['DJANGO_DB_USER'], - } - elif db_engine == 'sqlite': - db_settings = { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(self.DIRNAME, 'database.db'), - } - else: - raise ValueError("Unknown DB engine: %s" % db_engine) - - # Common settings. - settings.configure( - DEBUG=True, - DATABASES={'default': db_settings}, - CACHES={'default': {'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}}, - INSTALLED_APPS=self.APPS) - - import django - import pytest - django.setup() - sys.exit(pytest.main(["tests/"])) - - -setup( - name='django-livefield', - version='4.1.0', - description='Convenient soft-deletion support for Django models', - long_description=( - open('README.rst').read() + '\n\n' + - open('CHANGELOG.rst').read() + '\n\n' + - open('AUTHORS.rst').read()), - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Framework :: Django :: 3.2', - 'Framework :: Django :: 4.0', - 'Framework :: Django :: 4.1', - 'Framework :: Django :: 4.2', - 'Framework :: Django :: 5.0', - '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', - ], - keywords='python django soft-delete', - url='https://github.com/hearsaycorp/django-livefield', - author='Hearsay Social', - author_email='opensource@hearsaysocial.com', - license='MIT', - package_dir={'': 'src'}, - packages=find_packages('src'), - install_requires=install_requires, - tests_require=tests_require, - cmdclass={'test': DjangoTest}, -) diff --git a/tests/run_tests.py b/tests/run_tests.py new file mode 100644 index 0000000..b9cb2b4 --- /dev/null +++ b/tests/run_tests.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +import os +import sys + + +REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +SRC_ROOT = os.path.join(REPO_ROOT, "src") +APPS = ("tests",) + + +def _db_settings(): + db_engine = os.environ.get("DJANGO_DB_ENGINE", "sqlite") + if db_engine == "mysql": + return { + "ENGINE": "django.db.backends.mysql", + "NAME": os.environ["DJANGO_DB_NAME"], + "USER": os.environ["DJANGO_DB_USER"], + } + if db_engine == "postgres": + return { + "ENGINE": "django.db.backends.postgresql", + "NAME": os.environ["DJANGO_DB_NAME"], + "USER": os.environ["DJANGO_DB_USER"], + } + if db_engine == "sqlite": + return { + "ENGINE": "django.db.backends.sqlite3", + "NAME": os.path.join(REPO_ROOT, "database.db"), + } + + raise ValueError(f"Unknown DB engine: {db_engine}") + + +def main(): + if REPO_ROOT not in sys.path: + sys.path.insert(0, REPO_ROOT) + if SRC_ROOT not in sys.path: + sys.path.insert(0, SRC_ROOT) + + from django.conf import settings + + if not settings.configured: + settings.configure( + DEBUG=True, + DATABASES={"default": _db_settings()}, + CACHES={"default": {"BACKEND": "django.core.cache.backends.dummy.DummyCache"}}, + INSTALLED_APPS=APPS, + ) + + import django + import pytest + + django.setup() + return pytest.main(["tests/"]) + + +if __name__ == "__main__": + sys.exit(main())