Compare commits

...

784 commits

Author SHA1 Message Date
dependabot[bot]
d941373d34 chore(deps-dev): bump hypothesis from 6.135.24 to 6.135.26
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.135.24 to 6.135.26.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.135.24...hypothesis-python-6.135.26)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-version: 6.135.26
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-06 20:56:28 -07:00
dependabot[bot]
8b70e6afec chore(deps-dev): bump hypothesis from 6.133.0 to 6.135.24
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.133.0 to 6.135.24.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.133.0...hypothesis-python-6.135.24)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-version: 6.135.24
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-05 12:25:44 -07:00
dependabot[bot]
5248498008 chore(deps-dev): bump ruff from 0.11.12 to 0.12.2
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.11.12 to 0.12.2.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.11.12...0.12.2)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.12.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-04 15:42:50 -07:00
dependabot[bot]
ce5f58dc50 chore(deps-dev): bump urllib3 from 2.4.0 to 2.5.0
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.4.0 to 2.5.0.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.4.0...2.5.0)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-version: 2.5.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-04 15:42:41 -07:00
dependabot[bot]
f42a53bcaf chore(deps-dev): bump pytest from 8.3.5 to 8.4.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.5 to 8.4.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.5...8.4.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-version: 8.4.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-04 15:42:34 -07:00
dependabot[bot]
32e20994f1 chore(deps-dev): bump mypy from 1.16.0 to 1.16.1
Bumps [mypy](https://github.com/python/mypy) from 1.16.0 to 1.16.1.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.16.0...v1.16.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-version: 1.16.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-04 15:37:03 -07:00
dependabot[bot]
ec9a5b413d chore(deps-dev): bump safety from 3.5.1 to 3.5.2
Bumps [safety](https://github.com/pyupio/safety) from 3.5.1 to 3.5.2.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/3.5.1...3.5.2)

---
updated-dependencies:
- dependency-name: safety
  dependency-version: 3.5.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-04 15:36:53 -07:00
dependabot[bot]
dcc643ff81 chore(deps-dev): bump pytest-cov from 5.0.0 to 6.2.1
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 5.0.0 to 6.2.1.
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v5.0.0...v6.2.1)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-version: 6.2.1
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-04 15:36:40 -07:00
dependabot[bot]
88d367f924 chore(deps): bump django from 4.2.21 to 4.2.23
Bumps [django](https://github.com/django/django) from 4.2.21 to 4.2.23.
- [Commits](https://github.com/django/django/compare/4.2.21...4.2.23)

---
updated-dependencies:
- dependency-name: django
  dependency-version: 4.2.23
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-04 15:10:34 -07:00
dependabot[bot]
f7aeed0b14 chore(deps-dev): bump requests from 2.32.3 to 2.32.4
Bumps [requests](https://github.com/psf/requests) from 2.32.3 to 2.32.4.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.32.3...v2.32.4)

---
updated-dependencies:
- dependency-name: requests
  dependency-version: 2.32.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-04 15:10:21 -07:00
dependabot[bot]
a32e94adb6 chore(deps-dev): bump tomlkit from 0.13.2 to 0.13.3
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.13.2 to 0.13.3.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/python-poetry/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.13.2...0.13.3)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-version: 0.13.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-04 15:10:11 -07:00
Mike
794c71c7a6 chore: release 1.8.1 2025-06-02 10:46:04 -07:00
pre-commit-ci[bot]
8dd92753d6 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.11 → v0.11.12](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.11...v0.11.12)
2025-06-02 10:36:16 -07:00
pre-commit-ci[bot]
539f0003a1 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.11.8 → v0.11.11](https://github.com/astral-sh/ruff-pre-commit/compare/v0.11.8...v0.11.11)
2025-06-02 09:09:58 -07:00
Mike
dc371db44f chore(deps): update downstream dependencies 2025-06-02 09:08:01 -07:00
Mike
24c1de89fa ci(workflow): update Python and Django version matrix for tests 2025-06-02 08:57:36 -07:00
Mike
3e5841af10 chore(deps): update python and django version requirements 2025-06-02 08:57:18 -07:00
dependabot[bot]
dc49b53c82 chore(deps-dev): bump m2r2 from 0.3.3.post2 to 0.3.4
Bumps [m2r2](https://github.com/crossnox/m2r2) from 0.3.3.post2 to 0.3.4.
- [Changelog](https://github.com/CrossNox/m2r2/blob/development/CHANGES.md)
- [Commits](https://github.com/crossnox/m2r2/compare/v0.3.3.post2...v0.3.4)

---
updated-dependencies:
- dependency-name: m2r2
  dependency-version: 0.3.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-05 14:45:08 -07:00
dependabot[bot]
f193bd41cd chore(deps-dev): bump ruff from 0.9.7 to 0.11.8
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.9.7 to 0.11.8.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.9.7...0.11.8)

---
updated-dependencies:
- dependency-name: ruff
  dependency-version: 0.11.8
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-05 14:26:54 -07:00
dependabot[bot]
f7f3d59b30 chore(deps-dev): bump jinja2 from 3.1.5 to 3.1.6
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.5 to 3.1.6.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.5...3.1.6)

---
updated-dependencies:
- dependency-name: jinja2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-05 14:18:04 -07:00
pre-commit-ci[bot]
439fa5046f [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.9.7 → v0.11.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.7...v0.11.8)
2025-05-05 14:17:56 -07:00
dependabot[bot]
fe6db896bd chore(deps-dev): bump pytest from 8.3.4 to 8.3.5
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.4 to 8.3.5.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.4...8.3.5)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-05 14:17:44 -07:00
Mike
682cf61840 ci: improve test workflow configuration
- Prevent test workflow from running on tag pushes to avoid
  duplicate runs during releases
- Rename job from "build" to "test-matrix" for clarity
2025-02-24 19:22:03 -08:00
Mike
7e572801b0 ci: update PyPI publish action to use recommended tag 2025-02-24 19:15:02 -08:00
Mike
a38a6b9f5c chore: release 1.8.0 2025-02-24 19:01:08 -08:00
wolfmetr
2b9b9d7aa7 Fix for issue #648: Ensure choices are valid (value, label) tuples to avoid 'not enough values to unpack' error
(cherry picked from commit 30e8873b10db560b845f23697e00d20c42d7a989)
2025-02-24 18:53:50 -08:00
pre-commit-ci[bot]
f6b3cf0865 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.9.6 → v0.9.7](https://github.com/astral-sh/ruff-pre-commit/compare/v0.9.6...v0.9.7)
2025-02-24 18:27:00 -08:00
dependabot[bot]
041b19a1d2 chore(deps-dev): bump ruff from 0.9.6 to 0.9.7
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.9.6 to 0.9.7.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.9.6...0.9.7)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 18:26:49 -08:00
dependabot[bot]
e789a0dcd3 chore(deps-dev): bump safety from 3.2.14 to 3.3.0
Bumps [safety](https://github.com/pyupio/safety) from 3.2.14 to 3.3.0.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/3.2.14...3.3.0)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 18:26:40 -08:00
Mike
fafe528ea5 feat(models): add database constraints to Value model 2025-02-24 18:26:28 -08:00
Mike
4deda2abc5 refactor: move Sequence import to type-checking block
- Fix Ruff TC003 linting error
2025-02-13 09:09:40 -08:00
pre-commit-ci[bot]
28c67b3d04 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2025-02-13 09:09:40 -08:00
pre-commit-ci[bot]
449ddc9248 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.7.3 → v0.9.6](https://github.com/astral-sh/ruff-pre-commit/compare/v0.7.3...v0.9.6)
2025-02-13 09:09:40 -08:00
Mike
a95f2a1c33 style(lint): apply ruff formatting rules with defined target-version 2025-02-13 07:40:43 -08:00
Mike
996512b04c chore(ruff): set python target version to 3.8 2025-02-13 07:39:22 -08:00
dependabot[bot]
73755c4fdf chore(deps-dev): bump ruff from 0.9.5 to 0.9.6
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.9.5 to 0.9.6.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.9.5...0.9.6)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-13 07:27:44 -08:00
dependabot[bot]
579a1e0fc7 chore(deps-dev): bump pytest-django from 4.9.0 to 4.10.0
Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.9.0 to 4.10.0.
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/main/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.9.0...v4.10.0)

---
updated-dependencies:
- dependency-name: pytest-django
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-13 07:27:31 -08:00
dependabot[bot]
b160b38309 chore(deps-dev): bump ruff from 0.8.0 to 0.9.5
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.8.0 to 0.9.5.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.8.0...0.9.5)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-09 13:25:33 -08:00
dependabot[bot]
436edd5492 chore(deps): bump django from 4.2.16 to 4.2.19
Bumps [django](https://github.com/django/django) from 4.2.16 to 4.2.19.
- [Commits](https://github.com/django/django/compare/4.2.16...4.2.19)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-08 08:46:37 -08:00
dependabot[bot]
9261d518da chore(deps-dev): bump jinja2 from 3.1.4 to 3.1.5
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.4 to 3.1.5.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.4...3.1.5)

---
updated-dependencies:
- dependency-name: jinja2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-08 08:30:09 -08:00
Mike
18148c2b97 pin Poetry to 1.8.4 2025-02-08 08:25:33 -08:00
dependabot[bot]
eca5995616 chore(deps-dev): bump mypy from 1.13.0 to 1.14.1
Bumps [mypy](https://github.com/python/mypy) from 1.13.0 to 1.14.1.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.13.0...v1.14.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-08 08:17:47 -08:00
dependabot[bot]
1125887ba9 chore(deps-dev): bump safety from 3.2.11 to 3.2.14
Bumps [safety](https://github.com/pyupio/safety) from 3.2.11 to 3.2.14.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/3.2.11...3.2.14)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-08 08:17:41 -08:00
dependabot[bot]
9c68743af8 chore(deps-dev): bump pytest from 8.3.3 to 8.3.4
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.3 to 8.3.4.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.3...8.3.4)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-08 08:17:34 -08:00
dependabot[bot]
6c44ba988a chore(deps-dev): bump ruff from 0.7.3 to 0.8.0
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.7.3 to 0.8.0.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.7.3...0.8.0)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-27 11:24:33 -08:00
dependabot[bot]
75708e3fbb chore(deps): bump codecov/codecov-action from 3 to 5
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 5.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v3...v5)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-27 11:24:25 -08:00
dependabot[bot]
34862ed30a chore(deps-dev): bump sphinx-rtd-theme from 3.0.1 to 3.0.2
Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 3.0.1 to 3.0.2.
- [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst)
- [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/3.0.1...3.0.2)

---
updated-dependencies:
- dependency-name: sphinx-rtd-theme
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-27 11:24:16 -08:00
dependabot[bot]
abd93a44a1 chore(deps-dev): bump safety from 3.2.10 to 3.2.11
Bumps [safety](https://github.com/pyupio/safety) from 3.2.10 to 3.2.11.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/3.2.10...3.2.11)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-27 11:24:09 -08:00
dependabot[bot]
835717bd27 chore(deps-dev): bump ruff from 0.6.8 to 0.7.3
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.6.8 to 0.7.3.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.6.8...0.7.3)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 15:39:32 -08:00
dependabot[bot]
3a7d8eec63 chore(deps-dev): bump safety from 3.2.8 to 3.2.10
Bumps [safety](https://github.com/pyupio/safety) from 3.2.8 to 3.2.10.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/3.2.8...3.2.10)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 14:09:02 -08:00
dependabot[bot]
fef15f0ba6 chore(deps-dev): bump mypy from 1.11.2 to 1.13.0
Bumps [mypy](https://github.com/python/mypy) from 1.11.2 to 1.13.0.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.11.2...v1.13.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 14:08:55 -08:00
dependabot[bot]
ae73962bb2 chore(deps-dev): bump sphinx-rtd-theme from 2.0.0 to 3.0.1
Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 2.0.0 to 3.0.1.
- [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst)
- [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/2.0.0...3.0.1)

---
updated-dependencies:
- dependency-name: sphinx-rtd-theme
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 14:08:48 -08:00
dependabot[bot]
70fceedda0 chore(deps-dev): bump hypothesis from 6.112.2 to 6.113.0
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.112.2 to 6.113.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.112.2...hypothesis-python-6.113.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-11 14:08:39 -08:00
pre-commit-ci[bot]
39c3540592 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/pre-commit/pre-commit-hooks: v4.6.0 → v5.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.6.0...v5.0.0)
- [github.com/astral-sh/ruff-pre-commit: v0.6.8 → v0.7.3](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.8...v0.7.3)
2024-11-11 14:08:26 -08:00
dependabot[bot]
6c3c7f39e8 chore(deps-dev): bump hypothesis from 6.112.1 to 6.112.2
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.112.1 to 6.112.2.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.112.1...hypothesis-python-6.112.2)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-03 17:24:32 -07:00
dependabot[bot]
a47b1b05e0 chore(deps-dev): bump safety from 3.2.7 to 3.2.8
Bumps [safety](https://github.com/pyupio/safety) from 3.2.7 to 3.2.8.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/3.2.7...3.2.8)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-03 17:24:26 -07:00
dependabot[bot]
b276cb3e35 chore(deps-dev): bump ruff from 0.6.5 to 0.6.8
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.6.5 to 0.6.8.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.6.5...0.6.8)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-03 17:24:18 -07:00
pre-commit-ci[bot]
5a1d7546f4 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.6.5 → v0.6.8](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.5...v0.6.8)
2024-10-03 17:24:10 -07:00
dependabot[bot]
dc2cd2dff5 chore(deps-dev): bump ruff from 0.6.3 to 0.6.5
Bumps [ruff](https://github.com/astral-sh/ruff) from 0.6.3 to 0.6.5.
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.6.3...0.6.5)

---
updated-dependencies:
- dependency-name: ruff
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-19 08:56:06 -07:00
dependabot[bot]
0e27224106 chore(deps-dev): bump hypothesis from 6.111.2 to 6.112.1
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.111.2 to 6.112.1.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.111.2...hypothesis-python-6.112.1)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-19 08:56:00 -07:00
dependabot[bot]
305740e2e6 chore(deps-dev): bump pytest from 8.3.2 to 8.3.3
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.2 to 8.3.3.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.2...8.3.3)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-19 08:55:53 -07:00
pre-commit-ci[bot]
d281ff97c2 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/astral-sh/ruff-pre-commit: v0.6.3 → v0.6.5](https://github.com/astral-sh/ruff-pre-commit/compare/v0.6.3...v0.6.5)
2024-09-19 08:55:44 -07:00
dependabot[bot]
e17778b522 chore(deps): bump django from 4.2.15 to 4.2.16
Bumps [django](https://github.com/django/django) from 4.2.15 to 4.2.16.
- [Commits](https://github.com/django/django/compare/4.2.15...4.2.16)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-19 08:55:36 -07:00
dependabot[bot]
0f218add0b chore(deps-dev): bump cryptography from 42.0.8 to 43.0.1
Bumps [cryptography](https://github.com/pyca/cryptography) from 42.0.8 to 43.0.1.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/42.0.8...43.0.1)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-03 18:18:12 -07:00
dependabot[bot]
f07e2d0506 chore(deps-dev): bump pytest-django from 4.8.0 to 4.9.0
Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.8.0 to 4.9.0.
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/main/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.8.0...v4.9.0)

---
updated-dependencies:
- dependency-name: pytest-django
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-03 17:29:39 -07:00
dependabot[bot]
0d82d5ab5a chore(deps-dev): bump doc8 from 1.1.1 to 1.1.2
Bumps [doc8](https://github.com/pycqa/doc8) from 1.1.1 to 1.1.2.
- [Release notes](https://github.com/pycqa/doc8/releases)
- [Commits](https://github.com/pycqa/doc8/compare/v1.1.1...v1.1.2)

---
updated-dependencies:
- dependency-name: doc8
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-03 17:29:31 -07:00
Mike
d0b531f7be chore: release 1.7.1 2024-09-01 21:30:59 -07:00
Mike
8f18d5e7e2 fix(attribute): restore backward compatibility for invalid slugs
Replace ValidationError with a warning when creating Attributes with invalid slugs. This change allows existing code to continue functioning while alerting users to potential issues.
2024-09-01 21:26:45 -07:00
Mike
3e7563338f chore: release 1.7.0 2024-09-01 15:39:31 -07:00
dependabot[bot]
1c4355e948 chore(deps-dev): bump mypy from 1.11.1 to 1.11.2
Bumps [mypy](https://github.com/python/mypy) from 1.11.1 to 1.11.2.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.11.1...v1.11.2)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-01 15:12:46 -07:00
dependabot[bot]
353bc5f094 chore(deps-dev): bump hypothesis from 6.111.0 to 6.111.2
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.111.0 to 6.111.2.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.111.0...hypothesis-python-6.111.2)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-01 15:09:23 -07:00
dependabot[bot]
17c94198d0 chore(deps-dev): bump safety from 3.2.5 to 3.2.7
Bumps [safety](https://github.com/pyupio/safety) from 3.2.5 to 3.2.7.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/3.2.5...3.2.7)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-01 15:03:29 -07:00
Mike
625b8a5315 chore(migrations): update defaults and meta options for Attribute and Value models 2024-09-01 14:57:47 -07:00
pre-commit-ci[bot]
6b7a04f8a7 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2024-09-01 14:57:47 -07:00
Mike
9f4bddb94d fix(eav): update ClassVar type hint for Python 3.8 compatibility 2024-09-01 14:57:47 -07:00
Mike
393e3e352a chore: update lockfile 2024-09-01 14:57:47 -07:00
Mike
56939d9c5e chore: remove nitpick and black configuration from pyproject.toml 2024-09-01 14:57:47 -07:00
Mike
3ccf3146eb ci(pre-commit): replace black with ruff for linting and formatting 2024-09-01 14:57:47 -07:00
Mike
50db5bead4 chore: add .git-blame-ignore-revs file 2024-09-01 14:57:47 -07:00
Mike
b5b576aca5 refactor: apply ruff linter rules and standardize code style
Replace flake8 with ruff and apply consistent linting rules across the entire codebase. Update type annotations, quotation marks, and other style-related changes to comply with the new standards.
2024-09-01 14:57:47 -07:00
Mike
5e1a7d2803 chore(linting): replace wemake-python-styleguide with ruff 2024-09-01 14:57:47 -07:00
Mike
b8bcc383a4 ci(test): update Django versions and Python compatibility
Update test matrix to use Django 4.2, 5.0, and 5.1, removing support for Django 3.2.
2024-08-31 21:37:28 -07:00
pre-commit-ci[bot]
41fa7ddc5c [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2024-08-31 21:20:36 -07:00
Mike
1262a52282 test(attributes): add slug parameter to attribute model test 2024-08-31 21:20:36 -07:00
Mike
27d3887604 feat(attribute): add slug validation for Python identifier compliance
Implement custom validation for Attribute model's slug field to ensure it's a valid Python identifier. Add corresponding test case.
2024-08-31 21:20:36 -07:00
Mike
3990d7d6cb test: remove special chars in attribute name test data 2024-08-31 21:20:36 -07:00
Mike
6f141ff4f2 refactor(slug): ensure generated slugs are valid Python identifiers 2024-08-31 21:20:36 -07:00
dependabot[bot]
ab23ba118d chore(deps-dev): bump tomlkit from 0.13.0 to 0.13.2
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.13.0 to 0.13.2.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/python-poetry/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.13.0...0.13.2)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-15 07:34:48 -07:00
dependabot[bot]
03cb115531 chore(deps-dev): bump safety from 3.2.4 to 3.2.5
Bumps [safety](https://github.com/pyupio/safety) from 3.2.4 to 3.2.5.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/3.2.4...3.2.5)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-15 07:34:40 -07:00
dependabot[bot]
a56559ebb7 chore(deps-dev): bump hypothesis from 6.108.10 to 6.111.0
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.108.10 to 6.111.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.108.10...hypothesis-python-6.111.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-15 07:34:31 -07:00
dependabot[bot]
3884d2c2aa chore(deps): bump django from 4.2.14 to 4.2.15
Bumps [django](https://github.com/django/django) from 4.2.14 to 4.2.15.
- [Commits](https://github.com/django/django/compare/4.2.14...4.2.15)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-07 07:49:09 -07:00
dependabot[bot]
b0a73e2b9c chore(deps): bump pyyaml from 6.0.1 to 6.0.2
Bumps [pyyaml](https://github.com/yaml/pyyaml) from 6.0.1 to 6.0.2.
- [Release notes](https://github.com/yaml/pyyaml/releases)
- [Changelog](https://github.com/yaml/pyyaml/blob/main/CHANGES)
- [Commits](https://github.com/yaml/pyyaml/compare/6.0.1...6.0.2)

---
updated-dependencies:
- dependency-name: pyyaml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-07 07:49:01 -07:00
dependabot[bot]
cad0846d2c chore(deps-dev): bump hypothesis from 6.108.5 to 6.108.10
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.108.5 to 6.108.10.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.108.5...hypothesis-python-6.108.10)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-07 07:48:43 -07:00
pre-commit-ci[bot]
c86b909970 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 24.4.2 → 24.8.0](https://github.com/psf/black/compare/24.4.2...24.8.0)
2024-08-07 07:48:35 -07:00
dependabot[bot]
6e63441ca0 chore(deps-dev): bump black from 24.4.2 to 24.8.0
Bumps [black](https://github.com/psf/black) from 24.4.2 to 24.8.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.4.2...24.8.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-07 07:48:23 -07:00
dependabot[bot]
d2c34da383 chore(deps-dev): bump mypy from 1.11.0 to 1.11.1
Bumps [mypy](https://github.com/python/mypy) from 1.11.0 to 1.11.1.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.11...v1.11.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-07 07:48:11 -07:00
dependabot[bot]
c8bc9310d9 chore(deps-dev): bump hypothesis from 6.104.2 to 6.108.5
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.104.2 to 6.108.5.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.104.2...hypothesis-python-6.108.5)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-29 07:58:37 -07:00
dependabot[bot]
4940d7fa0b chore(deps-dev): bump pytest from 8.2.2 to 8.3.2
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.2.2 to 8.3.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.2.2...8.3.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-29 07:58:28 -07:00
dependabot[bot]
8ab1d09627 chore(deps-dev): bump mypy from 1.10.1 to 1.11.0
Bumps [mypy](https://github.com/python/mypy) from 1.10.1 to 1.11.0.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.10.1...v1.11)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-29 07:58:21 -07:00
dependabot[bot]
3ea0257a21 chore(deps-dev): bump tomlkit from 0.12.5 to 0.13.0
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.12.5 to 0.13.0.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/python-poetry/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.12.5...0.13.0)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-29 07:58:12 -07:00
dependabot[bot]
5dba618e63 chore(deps): bump django from 4.2.13 to 4.2.14
Bumps [django](https://github.com/django/django) from 4.2.13 to 4.2.14.
- [Commits](https://github.com/django/django/compare/4.2.13...4.2.14)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-29 07:58:04 -07:00
dependabot[bot]
17e018a0a0 chore(deps-dev): bump certifi from 2024.6.2 to 2024.7.4
Bumps [certifi](https://github.com/certifi/python-certifi) from 2024.6.2 to 2024.7.4.
- [Commits](https://github.com/certifi/python-certifi/compare/2024.06.02...2024.07.04)

---
updated-dependencies:
- dependency-name: certifi
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-29 07:57:55 -07:00
dependabot[bot]
c82273e62e chore(deps-dev): bump safety from 3.2.3 to 3.2.4
Bumps [safety](https://github.com/pyupio/safety) from 3.2.3 to 3.2.4.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/3.2.3...3.2.4)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-29 07:57:45 -07:00
dependabot[bot]
ceaf3abf40 chore(deps-dev): bump hypothesis from 6.103.2 to 6.104.2
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.103.2 to 6.104.2.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.103.2...hypothesis-python-6.104.2)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-03 14:01:58 -07:00
dependabot[bot]
38ddd519cf chore(deps-dev): bump mypy from 1.10.0 to 1.10.1
Bumps [mypy](https://github.com/python/mypy) from 1.10.0 to 1.10.1.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.10.0...v1.10.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-03 14:01:48 -07:00
Mike
c35d1355b0 chore: prepare release v1.6.1 2024-06-23 14:06:01 -07:00
Mike
97eb3f7fc2 chore: update downstream dependencies 2024-06-23 09:37:32 -07:00
dependabot[bot]
a4f5a8ae3d chore(deps-dev): bump urllib3 from 1.26.18 to 1.26.19
Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.18 to 1.26.19.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/1.26.19/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/1.26.18...1.26.19)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-23 09:00:22 -07:00
dependabot[bot]
322753b821 chore(deps-dev): bump hypothesis from 6.102.6 to 6.103.2
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.102.6 to 6.103.2.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.102.6...hypothesis-python-6.103.2)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-23 09:00:15 -07:00
dependabot[bot]
c62c927548 chore(deps-dev): bump safety from 3.2.0 to 3.2.3
Bumps [safety](https://github.com/pyupio/safety) from 3.2.0 to 3.2.3.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/3.2.0...3.2.3)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-23 09:00:08 -07:00
dependabot[bot]
c0f485e766 chore(deps-dev): bump authlib from 1.3.0 to 1.3.1
Bumps [authlib](https://github.com/lepture/authlib) from 1.3.0 to 1.3.1.
- [Release notes](https://github.com/lepture/authlib/releases)
- [Changelog](https://github.com/lepture/authlib/blob/master/docs/changelog.rst)
- [Commits](https://github.com/lepture/authlib/compare/v1.3.0...v1.3.1)

---
updated-dependencies:
- dependency-name: authlib
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-23 09:00:01 -07:00
dependabot[bot]
462e949a08 chore(deps-dev): bump pytest from 8.2.1 to 8.2.2
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.2.1 to 8.2.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.2.1...8.2.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-23 08:59:48 -07:00
pre-commit-ci[bot]
6585010038 [pre-commit.ci] auto fixes from pre-commit.com hooks
for more information, see https://pre-commit.ci
2024-06-23 08:59:33 -07:00
Mike
8c87f2f53b fix: ensure default manager is correctly replaced and ordered 2024-06-23 08:59:33 -07:00
dependabot[bot]
1b0ea0b9c4
Merge pull request #572 from jazzband/dependabot/pip/jinja2-3.1.4 2024-05-26 15:58:04 +00:00
dependabot[bot]
1b73435ff3
chore(deps-dev): bump jinja2 from 3.1.3 to 3.1.4
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.3 to 3.1.4.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.3...3.1.4)

---
updated-dependencies:
- dependency-name: jinja2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-26 15:54:39 +00:00
dependabot[bot]
3c74c2c008 chore(deps-dev): bump hypothesis from 6.102.1 to 6.102.6
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.102.1 to 6.102.6.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.102.1...hypothesis-python-6.102.6)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-26 08:53:16 -07:00
dependabot[bot]
04b1926d3a ---
updated-dependencies:
- dependency-name: requests
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-26 08:53:09 -07:00
dependabot[bot]
6d3892459f chore(deps-dev): bump pytest from 8.2.0 to 8.2.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.2.0 to 8.2.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.2.0...8.2.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-26 08:53:01 -07:00
dependabot[bot]
671fd814b6 chore(deps-dev): bump black from 24.4.0 to 24.4.2
Bumps [black](https://github.com/psf/black) from 24.4.0 to 24.4.2.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.4.0...24.4.2)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-26 08:52:52 -07:00
pre-commit-ci[bot]
27dfd357de [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 24.3.0 → 24.4.2](https://github.com/psf/black/compare/24.3.0...24.4.2)
2024-05-14 12:52:08 -07:00
dependabot[bot]
9746ef8218 chore(deps-dev): bump hypothesis from 6.99.5 to 6.102.1
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.99.5 to 6.102.1.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.99.5...hypothesis-python-6.102.1)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-14 12:48:17 -07:00
dependabot[bot]
5c804658b9 chore(deps-dev): bump tomlkit from 0.12.4 to 0.12.5
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.12.4 to 0.12.5.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/python-poetry/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.12.4...0.12.5)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-14 12:47:57 -07:00
dependabot[bot]
18b821e4a5 chore(deps): bump django from 4.2.11 to 4.2.13
Bumps [django](https://github.com/django/django) from 4.2.11 to 4.2.13.
- [Commits](https://github.com/django/django/compare/4.2.11...4.2.13)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-14 12:47:40 -07:00
dependabot[bot]
8529a40d9d chore(deps-dev): bump safety from 3.1.0 to 3.2.0
Bumps [safety](https://github.com/pyupio/safety) from 3.1.0 to 3.2.0.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/3.1.0...3.2.0)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-14 12:47:33 -07:00
dependabot[bot]
827c54895f chore(deps-dev): bump pytest from 8.1.1 to 8.2.0
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.1.1 to 8.2.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.1.1...8.2.0)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-14 12:47:25 -07:00
dependabot[bot]
26dfc17c1b chore(deps-dev): bump mypy from 1.9.0 to 1.10.0
Bumps [mypy](https://github.com/python/mypy) from 1.9.0 to 1.10.0.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/1.9.0...v1.10.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-14 12:47:15 -07:00
dependabot[bot]
b48882ee9d chore(deps): bump sqlparse from 0.4.4 to 0.5.0
Bumps [sqlparse](https://github.com/andialbrecht/sqlparse) from 0.4.4 to 0.5.0.
- [Changelog](https://github.com/andialbrecht/sqlparse/blob/master/CHANGELOG)
- [Commits](https://github.com/andialbrecht/sqlparse/compare/0.4.4...0.5.0)

---
updated-dependencies:
- dependency-name: sqlparse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-14 12:46:49 -07:00
dependabot[bot]
b94cc44db5 chore(deps-dev): bump black from 24.3.0 to 24.4.0
Bumps [black](https://github.com/psf/black) from 24.3.0 to 24.4.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.3.0...24.4.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-15 09:56:24 -07:00
dependabot[bot]
4a01f13109 chore(deps-dev): bump idna from 3.4 to 3.7
Bumps [idna](https://github.com/kjd/idna) from 3.4 to 3.7.
- [Release notes](https://github.com/kjd/idna/releases)
- [Changelog](https://github.com/kjd/idna/blob/master/HISTORY.rst)
- [Commits](https://github.com/kjd/idna/compare/v3.4...v3.7)

---
updated-dependencies:
- dependency-name: idna
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-15 09:56:16 -07:00
dependabot[bot]
20c9194372 chore(deps-dev): bump sphinx-autodoc-typehints from 2.0.0 to 2.0.1
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/2.0.0...2.0.1)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-15 09:56:07 -07:00
pre-commit-ci[bot]
e6cc7bc64e [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/pre-commit/pre-commit-hooks: v4.5.0 → v4.6.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.5.0...v4.6.0)
2024-04-15 09:55:56 -07:00
dependabot[bot]
6cc8e1206c chore(deps-dev): bump safety from 3.0.1 to 3.1.0
Bumps [safety](https://github.com/pyupio/safety) from 3.0.1 to 3.1.0.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/3.0.1...3.1.0)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-01 09:02:13 -07:00
dependabot[bot]
9ee8af9a8a chore(deps-dev): bump pytest-cov from 4.1.0 to 5.0.0
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 4.1.0 to 5.0.0.
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v4.1.0...v5.0.0)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-01 09:01:59 -07:00
pre-commit-ci[bot]
19fb9f2017 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 24.2.0 → 24.3.0](https://github.com/psf/black/compare/24.2.0...24.3.0)
2024-04-01 09:01:49 -07:00
dependabot[bot]
bc64acf39c chore(deps-dev): bump black from 24.2.0 to 24.3.0
Bumps [black](https://github.com/psf/black) from 24.2.0 to 24.3.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.2.0...24.3.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-01 09:01:37 -07:00
Mike
83e598a14d chore: release v1.6.0 2024-03-14 07:26:57 -07:00
dependabot[bot]
8318cfd8cc chore(deps-dev): bump hypothesis from 6.98.17 to 6.99.5
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.98.17 to 6.99.5.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.98.17...hypothesis-python-6.99.5)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-14 07:10:26 -07:00
dependabot[bot]
aea2f96874 chore(deps-dev): bump mypy from 1.8.0 to 1.9.0
Bumps [mypy](https://github.com/python/mypy) from 1.8.0 to 1.9.0.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.8.0...1.9.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-14 07:10:17 -07:00
dependabot[bot]
49587d0800 chore(deps-dev): bump pytest from 8.0.0 to 8.1.1
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.0.0 to 8.1.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.0.0...8.1.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-14 07:10:05 -07:00
Mike
792fc65003 chore: remove support for Django < 3.2 and Python < 3.8 2024-03-06 10:05:42 -08:00
Mike
d6af6a004a refactor(admin): optimize EAV field handling in admin forms 2024-03-06 09:34:45 -08:00
Mike
4d2c080857 test(forms): add test case for BaseEntityAdmin with no attributes 2024-03-06 09:34:45 -08:00
Mike
2d7b06c956 docs(eav): update documentation for Django EAV 2 admin integration and settings 2024-03-06 09:34:45 -08:00
Mike
93c434bf72 feat(admin): enhance admin integration for dynamic EAV fieldsets
- Implement dynamic EAV fieldset rendering in admin forms, supporting the inclusion of EAV attributes alongside standard model fields.
- Introduce `eav_fieldset_title` and `eav_fieldset_description` to customize the display of EAV fields in the admin.
- Refactor `render_change_form` to dynamically assemble fieldsets, including a dedicated section for EAV attributes.
2024-03-06 09:34:45 -08:00
Mike
5bc35da842 refactor(tests): expand EntityAdmin form tests and move to base function 2024-03-06 09:34:45 -08:00
Mike
84bfbf9063
Merge pull request #539 from jazzband/dependabot/pip/django-4.2.11
chore(deps): bump django from 4.2.10 to 4.2.11
2024-03-05 13:24:24 -08:00
Mike
c97fdd2b2b
Merge pull request #538 from jazzband/dependabot/pip/hypothesis-6.98.17
chore(deps-dev): bump hypothesis from 6.98.3 to 6.98.17
2024-03-05 13:24:17 -08:00
Mike
e0e5602cbd
Merge pull request #535 from jazzband/dependabot/pip/tomlkit-0.12.4
chore(deps-dev): bump tomlkit from 0.12.3 to 0.12.4
2024-03-05 13:24:03 -08:00
Mike
90cd78d8f7
Merge pull request #530 from jazzband/dependabot/pip/cryptography-42.0.4
chore(deps-dev): bump cryptography from 42.0.0 to 42.0.4
2024-03-05 13:23:55 -08:00
Mike
9712b9152c
Merge pull request #528 from jazzband/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2024-03-05 13:22:03 -08:00
Mike
fecebffd1b
Merge pull request #522 from jazzband/dependabot/pip/black-24.2.0
chore(deps-dev): bump black from 24.1.1 to 24.2.0
2024-03-05 13:21:55 -08:00
dependabot[bot]
64555d861b
chore(deps): bump django from 4.2.10 to 4.2.11
Bumps [django](https://github.com/django/django) from 4.2.10 to 4.2.11.
- [Commits](https://github.com/django/django/compare/4.2.10...4.2.11)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-05 02:44:01 +00:00
dependabot[bot]
75473be13e
chore(deps-dev): bump hypothesis from 6.98.3 to 6.98.17
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.98.3 to 6.98.17.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.98.3...hypothesis-python-6.98.17)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-05 02:43:03 +00:00
dependabot[bot]
0d9b2b4b48
chore(deps-dev): bump tomlkit from 0.12.3 to 0.12.4
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.12.3 to 0.12.4.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.12.3...0.12.4)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-28 02:16:41 +00:00
dependabot[bot]
af46fec191
chore(deps-dev): bump cryptography from 42.0.0 to 42.0.4
Bumps [cryptography](https://github.com/pyca/cryptography) from 42.0.0 to 42.0.4.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/42.0.0...42.0.4)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-21 20:35:16 +00:00
pre-commit-ci[bot]
176d74e0bc
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 24.1.1 → 24.2.0](https://github.com/psf/black/compare/24.1.1...24.2.0)
2024-02-19 17:41:26 +00:00
dependabot[bot]
76c92da8fe
chore(deps-dev): bump black from 24.1.1 to 24.2.0
Bumps [black](https://github.com/psf/black) from 24.1.1 to 24.2.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.1.1...24.2.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-13 02:26:49 +00:00
Mike
bdde209f30
Merge pull request #520 from jazzband/dependabot/pip/cryptography-42.0.0
chore(deps-dev): bump cryptography from 41.0.7 to 42.0.0
2024-02-12 12:13:58 -08:00
Mike
27e8aee9b8
Merge pull request #519 from jazzband/dependabot/pip/hypothesis-6.98.3
chore(deps-dev): bump hypothesis from 6.93.0 to 6.98.3
2024-02-12 12:13:51 -08:00
Mike
159d16671f
Merge pull request #518 from jazzband/dependabot/pip/sphinx-autodoc-typehints-2.0.0
chore(deps-dev): bump sphinx-autodoc-typehints from 1.25.2 to 2.0.0
2024-02-12 12:13:43 -08:00
dependabot[bot]
5e97e2ab9a
chore(deps-dev): bump sphinx-autodoc-typehints from 1.25.2 to 2.0.0
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.25.2 to 2.0.0.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.25.2...2.0.0)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 20:10:53 +00:00
Mike
aad9a79396
Merge pull request #510 from jazzband/dependabot/pip/pytest-8.0.0
chore(deps-dev): bump pytest from 7.4.4 to 8.0.0
2024-02-12 12:09:32 -08:00
dependabot[bot]
e30fdf7a8c
chore(deps-dev): bump pytest from 7.4.4 to 8.0.0
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.4 to 8.0.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.4.4...8.0.0)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 19:57:59 +00:00
Mike
23f10d2955
Merge pull request #517 from jazzband/dependabot/pip/django-4.2.10
chore(deps): bump django from 4.2.9 to 4.2.10
2024-02-12 11:57:01 -08:00
Mike
8a067fe88b
Merge pull request #513 from jazzband/dependabot/pip/pytest-django-4.8.0
chore(deps-dev): bump pytest-django from 4.7.0 to 4.8.0
2024-02-12 11:56:51 -08:00
Mike
8be3cedf04
Merge pull request #508 from jazzband/dependabot/pip/black-24.1.1
chore(deps-dev): bump black from 22.12.0 to 24.1.1
2024-02-12 11:56:37 -08:00
dependabot[bot]
aba1ca4b2e
chore(deps-dev): bump cryptography from 41.0.7 to 42.0.0
Bumps [cryptography](https://github.com/pyca/cryptography) from 41.0.7 to 42.0.0.
- [Changelog](https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pyca/cryptography/compare/41.0.7...42.0.0)

---
updated-dependencies:
- dependency-name: cryptography
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 19:26:35 +00:00
dependabot[bot]
c2776cca52
chore(deps-dev): bump black from 22.12.0 to 24.1.1
Bumps [black](https://github.com/psf/black) from 22.12.0 to 24.1.1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.12.0...24.1.1)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-12 19:26:24 +00:00
Mike
d592c61e78
Merge pull request #511 from jazzband/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2024-02-12 11:24:18 -08:00
Mike
9713c0d1c9
Merge pull request #503 from jazzband/dependabot/pip/safety-3.0.1
chore(deps-dev): bump safety from 2.3.5 to 3.0.1
2024-02-12 11:23:52 -08:00
Mike
eb31634b9e
Merge pull request #498 from jazzband/dependabot/github_actions/actions/cache-4
chore(deps): bump actions/cache from 3 to 4
2024-02-12 11:23:44 -08:00
dependabot[bot]
91c1b1452d
chore(deps-dev): bump hypothesis from 6.93.0 to 6.98.3
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.93.0 to 6.98.3.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.93.0...hypothesis-python-6.98.3)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-09 02:52:28 +00:00
dependabot[bot]
24a35e77dc
chore(deps): bump django from 4.2.9 to 4.2.10
Bumps [django](https://github.com/django/django) from 4.2.9 to 4.2.10.
- [Commits](https://github.com/django/django/compare/4.2.9...4.2.10)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-07 02:37:17 +00:00
dependabot[bot]
1a46ddc9a7
chore(deps-dev): bump pytest-django from 4.7.0 to 4.8.0
Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.7.0 to 4.8.0.
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/master/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.7.0...v4.8.0)

---
updated-dependencies:
- dependency-name: pytest-django
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-31 02:39:39 +00:00
pre-commit-ci[bot]
fa56adc94a
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 23.12.1 → 24.1.1](https://github.com/psf/black/compare/23.12.1...24.1.1)
2024-01-29 17:33:39 +00:00
dependabot[bot]
6d97fce0b0
chore(deps-dev): bump safety from 2.3.5 to 3.0.1
Bumps [safety](https://github.com/pyupio/safety) from 2.3.5 to 3.0.1.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/2.3.5...3.0.1)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-22 02:08:38 +00:00
dependabot[bot]
932bcd2b02
chore(deps): bump actions/cache from 3 to 4
Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-18 02:10:14 +00:00
Mike
188f21a120
Merge pull request #494 from jazzband/dependabot/pip/hypothesis-6.93.0
chore(deps-dev): bump hypothesis from 6.92.6 to 6.93.0
2024-01-15 09:58:21 -08:00
Mike
ec1d9737ab
Merge pull request #492 from jazzband/dependabot/pip/jinja2-3.1.3
chore(deps-dev): bump jinja2 from 3.1.2 to 3.1.3
2024-01-15 09:58:15 -08:00
Mike
3b8ce78010
Merge pull request #491 from jazzband/dependabot/pip/safety-2.3.5
chore(deps-dev): bump safety from 2.3.4 to 2.3.5
2024-01-15 09:58:08 -08:00
dependabot[bot]
6c4c418b7c
chore(deps-dev): bump hypothesis from 6.92.6 to 6.93.0
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.92.6 to 6.93.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.92.6...hypothesis-python-6.93.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-15 02:33:57 +00:00
dependabot[bot]
6ec6e008dc
chore(deps-dev): bump jinja2 from 3.1.2 to 3.1.3
Bumps [jinja2](https://github.com/pallets/jinja) from 3.1.2 to 3.1.3.
- [Release notes](https://github.com/pallets/jinja/releases)
- [Changelog](https://github.com/pallets/jinja/blob/main/CHANGES.rst)
- [Commits](https://github.com/pallets/jinja/compare/3.1.2...3.1.3)

---
updated-dependencies:
- dependency-name: jinja2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-11 20:31:14 +00:00
dependabot[bot]
b51be65f44
chore(deps-dev): bump safety from 2.3.4 to 2.3.5
Bumps [safety](https://github.com/pyupio/safety) from 2.3.4 to 2.3.5.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/2.3.4...2.3.5)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-11 02:50:37 +00:00
Mike
0e899c4c21
Merge pull request #489 from cclauss/codespell
Fix typos with codespell
2024-01-10 12:29:26 -08:00
Christian Clauss
0b683ef3d5 Fix typos with codespell --ignore-words-list=unkown --skip="*.po" -w 2024-01-10 21:06:29 +01:00
Mike
560fa4aea5
Merge pull request #488 from jazzband/dependabot/pip/gitpython-3.1.41
chore(deps-dev): bump gitpython from 3.1.37 to 3.1.41
2024-01-10 10:41:05 -08:00
dependabot[bot]
f7ef931b3e
chore(deps-dev): bump gitpython from 3.1.37 to 3.1.41
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.37 to 3.1.41.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.37...3.1.41)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-10 18:34:14 +00:00
Mike
43dfefaaeb
Merge pull request #486 from jazzband/dependabot/pip/hypothesis-6.92.6
chore(deps-dev): bump hypothesis from 6.92.1 to 6.92.6
2024-01-10 10:32:27 -08:00
Mike
cd9f32bb21
Merge pull request #485 from jazzband/dependabot/pip/django-4.2.9
chore(deps): bump django from 4.2.8 to 4.2.9
2024-01-10 10:32:20 -08:00
Mike
91565d476e
Merge pull request #484 from jazzband/dependabot/pip/nitpick-0.35.0
chore(deps-dev): bump nitpick from 0.34.0 to 0.35.0
2024-01-10 10:32:08 -08:00
Mike
45c15759ba
Merge pull request #483 from jazzband/dependabot/pip/pytest-7.4.4
chore(deps-dev): bump pytest from 7.4.3 to 7.4.4
2024-01-10 10:31:55 -08:00
Mike
f0a8e0636b
Merge pull request #480 from jazzband/dependabot/pip/black-23.12.1
chore(deps-dev): bump black from 22.12.0 to 23.12.1
2024-01-10 10:31:47 -08:00
Mike
a9c7c7a85e
Merge pull request #481 from jazzband/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2024-01-10 10:30:54 -08:00
Mike
7aa9b62d6d
Merge pull request #479 from jazzband/dependabot/pip/mypy-1.8.0
chore(deps-dev): bump mypy from 1.7.1 to 1.8.0
2024-01-10 10:30:09 -08:00
dependabot[bot]
5ed4f1c1e2
chore(deps-dev): bump nitpick from 0.34.0 to 0.35.0
Bumps [nitpick](https://github.com/andreoliwa/nitpick) from 0.34.0 to 0.35.0.
- [Release notes](https://github.com/andreoliwa/nitpick/releases)
- [Changelog](https://github.com/andreoliwa/nitpick/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/andreoliwa/nitpick/compare/v0.34.0...v0.35.0)

---
updated-dependencies:
- dependency-name: nitpick
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-10 18:25:53 +00:00
dependabot[bot]
549e5c9efb
chore(deps): bump django from 4.2.8 to 4.2.9
Bumps [django](https://github.com/django/django) from 4.2.8 to 4.2.9.
- [Commits](https://github.com/django/django/compare/4.2.8...4.2.9)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-10 18:25:47 +00:00
dependabot[bot]
a8e7fb0b18
chore(deps-dev): bump mypy from 1.7.1 to 1.8.0
Bumps [mypy](https://github.com/python/mypy) from 1.7.1 to 1.8.0.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.7.1...v1.8.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-10 18:25:23 +00:00
Christian Clauss
3ca27bb65e
chore: Add Django 5.0 and Python 3.12 to the testing (#487)
* chore: Add Django 5.0 and Python 3.12 to the testing

* what-python-version-can-i-use-with-django

* Do not test Django 4.1 on Python 3.12

* Upgrade setuptools on Python 3.12

* pyyaml = { version = "^6.0.1", python = "^3.12" }

* pyyaml = { version = "^6.0.1", python = "^3.12" }

* poetry lock --no-update
2024-01-10 10:24:14 -08:00
dependabot[bot]
76f52835e9
chore(deps-dev): bump hypothesis from 6.92.1 to 6.92.6
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.92.1 to 6.92.6.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.92.1...hypothesis-python-6.92.6)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-09 02:04:07 +00:00
dependabot[bot]
5019052792
chore(deps-dev): bump pytest from 7.4.3 to 7.4.4
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.3 to 7.4.4.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.4.3...7.4.4)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-01 02:19:06 +00:00
pre-commit-ci[bot]
9c1b5971c0
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 23.12.0 → 23.12.1](https://github.com/psf/black/compare/23.12.0...23.12.1)
2023-12-25 17:36:05 +00:00
dependabot[bot]
fb1d3f8423
chore(deps-dev): bump black from 22.12.0 to 23.12.1
Bumps [black](https://github.com/psf/black) from 22.12.0 to 23.12.1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.12.0...23.12.1)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-25 02:09:12 +00:00
Mike
141a274d74
Merge pull request #477 from jazzband/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2023-12-19 15:24:26 -08:00
Mike
163d973455
Merge pull request #476 from jazzband/dependabot/pip/hypothesis-6.92.1
chore(deps-dev): bump hypothesis from 6.92.0 to 6.92.1
2023-12-19 15:24:08 -08:00
Mike
ba8e737810
Merge pull request #475 from jazzband/dependabot/pip/m2r2-0.3.3.post2
chore(deps-dev): bump m2r2 from 0.3.2 to 0.3.3.post2
2023-12-19 15:24:02 -08:00
Mike
330607d403
Merge pull request #474 from jazzband/dependabot/pip/doc8-1.1.1
chore(deps-dev): bump doc8 from 0.11.2 to 1.1.1
2023-12-19 15:23:53 -08:00
pre-commit-ci[bot]
f7b806afed
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 23.11.0 → 23.12.0](https://github.com/psf/black/compare/23.11.0...23.12.0)
2023-12-18 17:38:26 +00:00
dependabot[bot]
b3d2e7ee21
chore(deps-dev): bump hypothesis from 6.92.0 to 6.92.1
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.92.0 to 6.92.1.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.92.0...hypothesis-python-6.92.1)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-18 02:45:23 +00:00
dependabot[bot]
c7948e1fdf
chore(deps-dev): bump m2r2 from 0.3.2 to 0.3.3.post2
Bumps [m2r2](https://github.com/crossnox/m2r2) from 0.3.2 to 0.3.3.post2.
- [Changelog](https://github.com/CrossNox/m2r2/blob/development/CHANGES.md)
- [Commits](https://github.com/crossnox/m2r2/compare/v0.3.2...v0.3.3.post2)

---
updated-dependencies:
- dependency-name: m2r2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-14 02:23:05 +00:00
dependabot[bot]
c5185f2afc
chore(deps-dev): bump doc8 from 0.11.2 to 1.1.1
Bumps [doc8](https://github.com/pycqa/doc8) from 0.11.2 to 1.1.1.
- [Release notes](https://github.com/pycqa/doc8/releases)
- [Commits](https://github.com/pycqa/doc8/compare/0.11.2...v1.1.1)

---
updated-dependencies:
- dependency-name: doc8
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-14 02:22:19 +00:00
Mike
f8990447b7
Merge pull request #472 from jazzband/dependabot/pip/hypothesis-6.92.0
chore(deps-dev): bump hypothesis from 6.88.3 to 6.92.0
2023-12-12 18:43:21 -08:00
Mike
2aba31144b
Merge pull request #471 from jazzband/dependabot/github_actions/actions/setup-python-5
chore(deps): bump actions/setup-python from 4 to 5
2023-12-12 18:43:09 -08:00
Mike
9bfd7f994c
Merge pull request #470 from jazzband/dependabot/pip/django-4.2.8
chore(deps): bump django from 4.2.7 to 4.2.8
2023-12-12 18:42:45 -08:00
Mike
8168d4d74b
Merge pull request #466 from jazzband/dependabot/pip/sphinx-rtd-theme-2.0.0
chore(deps-dev): bump sphinx-rtd-theme from 1.3.0 to 2.0.0
2023-12-12 18:42:38 -08:00
Mike
6e512833fe
Merge pull request #464 from jazzband/dependabot/pip/mypy-1.7.1
chore(deps-dev): bump mypy from 1.6.1 to 1.7.1
2023-12-12 18:42:17 -08:00
Mike
561a9054c7
Merge pull request #460 from jazzband/dependabot/pip/tomlkit-0.12.3
chore(deps-dev): bump tomlkit from 0.12.2 to 0.12.3
2023-12-12 18:42:07 -08:00
Mike
35a681c597
Merge pull request #458 from jazzband/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2023-12-12 18:41:59 -08:00
Mike
ae6d311460
Merge pull request #457 from jazzband/dependabot/pip/sphinx-autodoc-typehints-1.25.2
chore(deps-dev): bump sphinx-autodoc-typehints from 1.24.1 to 1.25.2
2023-12-12 18:41:50 -08:00
Mike
190621966b
Merge pull request #452 from jazzband/dependabot/pip/pytest-django-4.7.0
chore(deps-dev): bump pytest-django from 4.6.0 to 4.7.0
2023-12-12 18:41:41 -08:00
dependabot[bot]
4151cfc167
chore(deps-dev): bump hypothesis from 6.88.3 to 6.92.0
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.88.3 to 6.92.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.88.3...hypothesis-python-6.92.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-11 02:29:10 +00:00
Mike
e1bc6673b0
Merge pull request #467 from iacobfred/master
refactor: split model modules
2023-12-07 09:01:13 -08:00
dependabot[bot]
ac90a17bd9
chore(deps): bump actions/setup-python from 4 to 5
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-07 02:35:21 +00:00
Jacob Fredericksen
ee3f5662de fix: use typing.Tuple for annotations 2023-12-06 17:53:36 -05:00
Jacob Fredericksen
289e86e03f fix: use typing.Tuple for annotations 2023-12-06 13:43:02 -05:00
Jacob Fredericksen
08086b00c6 fix: use typing.Tuple for annotations 2023-12-05 11:47:28 -05:00
dependabot[bot]
6382edcfba
chore(deps): bump django from 4.2.7 to 4.2.8
Bumps [django](https://github.com/django/django) from 4.2.7 to 4.2.8.
- [Commits](https://github.com/django/django/compare/4.2.7...4.2.8)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-05 02:28:31 +00:00
Jacob Fredericksen
1cdc2c4a41 refactor: cleanup 2023-11-30 13:11:59 -05:00
Jacob Fredericksen
7153bedce0 refactor: split model modules 2023-11-30 13:05:20 -05:00
dependabot[bot]
ef0647cfb3
chore(deps-dev): bump sphinx-rtd-theme from 1.3.0 to 2.0.0
Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 1.3.0 to 2.0.0.
- [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst)
- [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/1.3.0...2.0.0)

---
updated-dependencies:
- dependency-name: sphinx-rtd-theme
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-29 02:36:48 +00:00
dependabot[bot]
87c73c9b0b
chore(deps-dev): bump mypy from 1.6.1 to 1.7.1
Bumps [mypy](https://github.com/python/mypy) from 1.6.1 to 1.7.1.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.6.1...v1.7.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-24 02:33:02 +00:00
dependabot[bot]
bb80c75647
chore(deps-dev): bump tomlkit from 0.12.2 to 0.12.3
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.12.2 to 0.12.3.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.12.2...0.12.3)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-15 02:54:55 +00:00
pre-commit-ci[bot]
ef88025b92
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 23.10.1 → 23.11.0](https://github.com/psf/black/compare/23.10.1...23.11.0)
2023-11-13 17:38:54 +00:00
dependabot[bot]
6c66ebc3d0
chore(deps-dev): bump sphinx-autodoc-typehints from 1.24.1 to 1.25.2
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.24.1 to 1.25.2.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.24.1...1.25.2)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-13 02:13:49 +00:00
dependabot[bot]
b53474661a
chore(deps-dev): bump pytest-django from 4.6.0 to 4.7.0
Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.6.0 to 4.7.0.
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/master/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.6.0...v4.7.0)

---
updated-dependencies:
- dependency-name: pytest-django
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-09 02:12:58 +00:00
Mike
3858d9f1d2 chore: release v1.5.0 2023-11-08 09:28:17 -07:00
Mike
40a50cd8a3
Merge pull request #450 from jazzband/dependabot/pip/hypothesis-6.88.3
chore(deps-dev): bump hypothesis from 6.88.1 to 6.88.3
2023-11-08 09:20:03 -07:00
dependabot[bot]
25c7f9cf14
chore(deps-dev): bump hypothesis from 6.88.1 to 6.88.3
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.88.1 to 6.88.3.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.88.1...hypothesis-python-6.88.3)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-08 16:08:56 +00:00
Mike
8b179c0029
Merge pull request #449 from jazzband/dependabot/pip/tomlkit-0.12.2
chore(deps-dev): bump tomlkit from 0.12.1 to 0.12.2
2023-11-08 09:07:33 -07:00
Mike
4680b45026
Merge pull request #448 from jazzband/dependabot/pip/django-4.2.7
chore(deps): bump django from 4.2.6 to 4.2.7
2023-11-08 09:07:25 -07:00
Mike
ab9f33c772
Merge pull request #447 from jazzband/dependabot/pip/sphinx-autodoc-typehints-1.24.1
chore(deps-dev): bump sphinx-autodoc-typehints from 1.24.0 to 1.24.1
2023-11-08 09:07:16 -07:00
Mike
bb3d0c333b
Merge pull request #446 from jazzband/dependabot/pip/pytest-django-4.6.0
chore(deps-dev): bump pytest-django from 4.5.2 to 4.6.0
2023-11-08 09:07:08 -07:00
Mike
0e70322562
Merge pull request #445 from jazzband/dependabot/pip/safety-2.3.5
chore(deps-dev): bump safety from 2.3.4 to 2.3.5
2023-11-08 09:06:58 -07:00
dependabot[bot]
35869a56f0
chore(deps-dev): bump tomlkit from 0.12.1 to 0.12.2
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.12.1 to 0.12.2.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.12.1...0.12.2)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-03 02:07:02 +00:00
dependabot[bot]
568e704d26
chore(deps): bump django from 4.2.6 to 4.2.7
Bumps [django](https://github.com/django/django) from 4.2.6 to 4.2.7.
- [Commits](https://github.com/django/django/compare/4.2.6...4.2.7)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-02 02:10:27 +00:00
dependabot[bot]
48190e0426
chore(deps-dev): bump sphinx-autodoc-typehints from 1.24.0 to 1.24.1
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.24.0 to 1.24.1.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.24.0...1.24.1)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-01 02:51:21 +00:00
dependabot[bot]
010e629f2a
chore(deps-dev): bump pytest-django from 4.5.2 to 4.6.0
Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.5.2 to 4.6.0.
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/master/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.5.2...v4.6.0)

---
updated-dependencies:
- dependency-name: pytest-django
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-31 02:12:57 +00:00
dependabot[bot]
000c7605d4
chore(deps-dev): bump safety from 2.3.4 to 2.3.5
Bumps [safety](https://github.com/pyupio/safety) from 2.3.4 to 2.3.5.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/2.3.4...2.3.5)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-31 02:12:32 +00:00
Mike
6296f1abca
Merge pull request #444 from jazzband/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2023-10-30 12:34:18 -07:00
pre-commit-ci[bot]
ab5a2af67a [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 23.10.0 → 23.10.1](https://github.com/psf/black/compare/23.10.0...23.10.1)
2023-10-30 12:12:42 -07:00
Mike
9ce261428c
Merge pull request #443 from Dresdn/issue-442
Add Python 3.11 and Django 4.2 to support matrix
2023-10-30 12:08:56 -07:00
Mike
debc0d099e docs: Add test matrix updates to Changelog 2023-10-30 10:34:21 -07:00
Mike
d32f0d0e74 chore(test): Migrate pythonpath to pytest v7 setting 2023-10-30 10:31:29 -07:00
Mike
36221042b7 chore(deps-dev): Update pytest to v7 2023-10-30 10:30:46 -07:00
Mike
e1dba28fff chore(pyproject.toml): update Django classifiers
- Removed the classifier for Django 4.0.
- Added the classifier for Django 4.2.
2023-10-30 09:15:49 -07:00
Mike
205e16d25d ci(test): update Django versions in testing matrix
- Removed Django 4.0 from the testing matrix.
- Added Django 4.2 to the testing matrix.
2023-10-30 09:15:41 -07:00
Mike
62d5bcc0a2 chore(pyproject.toml): add classifiers for Python versions 2023-10-30 09:14:20 -07:00
Mike
1e4d5742ad ci(test): update testing matrix to include Python 3.11 2023-10-30 09:14:09 -07:00
Mike
100a72df96
Merge pull request #441 from jazzband/dependabot/pip/black-23.10.1
chore(deps-dev): bump black from 22.12.0 to 23.10.1
2023-10-30 08:59:04 -07:00
Mike
6ddd6e01e8
Merge pull request #440 from jazzband/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2023-10-30 08:58:56 -07:00
Mike
0a23169da1
Merge pull request #439 from jazzband/dependabot/pip/mypy-1.6.1
chore(deps-dev): bump mypy from 1.6.0 to 1.6.1
2023-10-30 08:58:36 -07:00
Mike
6d43889223
Merge pull request #437 from jazzband/dependabot/pip/urllib3-1.26.18
chore(deps-dev): bump urllib3 from 1.26.17 to 1.26.18
2023-10-30 08:58:29 -07:00
Mike
a90533fcf9
Merge pull request #436 from jazzband/dependabot/pip/hypothesis-6.88.1
chore(deps-dev): bump hypothesis from 6.87.1 to 6.88.1
2023-10-30 08:58:19 -07:00
mathiasag7
3b1be10e9b
feat: Provide UUIDField option for pk field and a natural key feature for serialization (#428) 2023-10-30 08:57:29 -07:00
dependabot[bot]
0b1e01dde9
chore(deps-dev): bump black from 22.12.0 to 23.10.1
Bumps [black](https://github.com/psf/black) from 22.12.0 to 23.10.1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.12.0...23.10.1)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-24 02:12:43 +00:00
pre-commit-ci[bot]
48c48532e4
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 23.9.1 → 23.10.0](https://github.com/psf/black/compare/23.9.1...23.10.0)
2023-10-23 17:37:22 +00:00
dependabot[bot]
8109402ce2
chore(deps-dev): bump mypy from 1.6.0 to 1.6.1
Bumps [mypy](https://github.com/python/mypy) from 1.6.0 to 1.6.1.
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.6.0...v1.6.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-19 02:55:39 +00:00
dependabot[bot]
d3da79bc90
chore(deps-dev): bump urllib3 from 1.26.17 to 1.26.18
Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.17 to 1.26.18.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/1.26.17...1.26.18)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-18 01:22:48 +00:00
dependabot[bot]
85e770ece3
chore(deps-dev): bump hypothesis from 6.87.1 to 6.88.1
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.87.1 to 6.88.1.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.87.1...hypothesis-python-6.88.1)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-17 02:33:38 +00:00
Mike
964f77dc54 refactor(docs): Update intersphinx mapping in Sphinx configuration 2023-10-15 16:24:12 -07:00
Mike
6791df9ba0 refactor(build): Refactor pyproject.toml configuration for latest Poetry version compatibility 2023-10-15 16:17:51 -07:00
Mike
537ef3792a docs(config): Update Read the Docs build configuration 2023-10-15 16:01:39 -07:00
Mike
691e5a8a52
Merge pull request #432 from jazzband/dependabot/pip/mypy-1.6.0
chore(deps-dev): bump mypy from 1.5.1 to 1.6.0
2023-10-12 21:32:24 -07:00
Mike
f1192bc2b2
Merge pull request #431 from jazzband/dependabot/pip/gitpython-3.1.37
chore(deps-dev): bump gitpython from 3.1.35 to 3.1.37
2023-10-12 21:32:11 -07:00
Mike
714f26be9e
Merge pull request #430 from jazzband/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2023-10-12 21:30:11 -07:00
dependabot[bot]
829becd370
chore(deps-dev): bump mypy from 1.5.1 to 1.6.0
Bumps [mypy](https://github.com/python/mypy) from 1.5.1 to 1.6.0.
- [Commits](https://github.com/python/mypy/compare/v1.5.1...v1.6.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-11 02:14:20 +00:00
dependabot[bot]
79ab62a74d
chore(deps-dev): bump gitpython from 3.1.35 to 3.1.37
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.35 to 3.1.37.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.35...3.1.37)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-10 21:00:33 +00:00
pre-commit-ci[bot]
9053dd6306
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/pre-commit/pre-commit-hooks: v4.4.0 → v4.5.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.4.0...v4.5.0)
2023-10-09 17:39:37 +00:00
Mike
71dd789c3e
Merge pull request #426 from jazzband/dependabot/pip/django-4.2.6
chore(deps): bump django from 4.2.5 to 4.2.6
2023-10-05 10:58:21 -07:00
dependabot[bot]
e2d9d56a9a
chore(deps): bump django from 4.2.5 to 4.2.6
Bumps [django](https://github.com/django/django) from 4.2.5 to 4.2.6.
- [Commits](https://github.com/django/django/compare/4.2.5...4.2.6)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-05 03:02:42 +00:00
dependabot[bot]
98e3b2948b chore(deps): bump urllib3 from 1.26.14 to 1.26.17
Bumps [urllib3](https://github.com/urllib3/urllib3) from 1.26.14 to 1.26.17.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/1.26.14...1.26.17)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-03 09:25:21 -07:00
dependabot[bot]
efd9416819 chore(deps-dev): bump hypothesis from 6.87.0 to 6.87.1
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.87.0 to 6.87.1.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.87.0...hypothesis-python-6.87.1)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-03 09:25:07 -07:00
dependabot[bot]
c8697c7f29 chore(deps-dev): bump hypothesis from 6.84.2 to 6.87.0
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.84.2 to 6.87.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.84.2...hypothesis-python-6.87.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-28 07:09:57 -07:00
pre-commit-ci[bot]
e76bb17958 [pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 23.7.0 → 23.9.1](https://github.com/psf/black/compare/23.7.0...23.9.1)
2023-09-28 07:09:35 -07:00
dependabot[bot]
a823d8849c chore(deps-dev): bump gitpython from 3.1.34 to 3.1.35
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.34 to 3.1.35.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.34...3.1.35)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-28 07:09:25 -07:00
dependabot[bot]
8cad58b22e chore(deps): bump sphinx-autodoc-typehints from 1.23.0 to 1.24.0
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.23.0 to 1.24.0.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.23.0...1.24.0)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-08 14:07:30 -07:00
Mike
d2ceab3af4 docs(changelog): document bug fix for querying with multiple EAV kwargs 2023-09-08 14:06:52 -07:00
Mike
d45e31520e fix(queryset): apply filter to combine multiple eav filter kwargs 2023-09-08 14:06:52 -07:00
Mike
dd5f375640 test(queryset): add filter test for multiple EAV attributes 2023-09-08 14:06:52 -07:00
Mike
b31f5c2d37
Merge pull request #405 from jazzband/dependabot/pip/sphinx-7.1.2
chore(deps): bump sphinx from 6.2.1 to 7.1.2
2023-09-06 22:45:45 -07:00
dependabot[bot]
a50f8ccfb5
chore(deps): bump sphinx from 6.2.1 to 7.1.2
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 6.2.1 to 7.1.2.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v6.2.1...v7.1.2)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-07 05:41:29 +00:00
Mike
e015a987ab
Merge pull request #412 from jazzband/dependabot/pip/gitpython-3.1.34
chore(deps-dev): bump gitpython from 3.1.32 to 3.1.34
2023-09-06 22:40:20 -07:00
Mike
f3b04472c9
Merge pull request #413 from jazzband/dependabot/pip/hypothesis-6.84.2
chore(deps-dev): bump hypothesis from 6.82.6 to 6.84.2
2023-09-06 22:40:12 -07:00
Mike
4b9f10b4a5
Merge pull request #410 from jazzband/dependabot/pip/django-4.2.5
chore(deps): bump django from 4.2.4 to 4.2.5
2023-09-06 22:40:02 -07:00
Mike
7fec64d6c1
Merge pull request #408 from jazzband/dependabot/github_actions/actions/checkout-4
chore(deps): bump actions/checkout from 3 to 4
2023-09-06 22:39:50 -07:00
dependabot[bot]
6a78b02f5a
chore(deps-dev): bump hypothesis from 6.82.6 to 6.84.2
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.82.6 to 6.84.2.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.82.6...hypothesis-python-6.84.2)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-07 02:25:16 +00:00
dependabot[bot]
c7cef5350a
chore(deps-dev): bump gitpython from 3.1.32 to 3.1.34
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.32 to 3.1.34.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.32...3.1.34)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-06 18:47:34 +00:00
dependabot[bot]
5d50478fe3
chore(deps): bump django from 4.2.4 to 4.2.5
Bumps [django](https://github.com/django/django) from 4.2.4 to 4.2.5.
- [Commits](https://github.com/django/django/compare/4.2.4...4.2.5)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-05 02:41:35 +00:00
dependabot[bot]
921576042c
chore(deps): bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-05 02:16:25 +00:00
Mike
ec957dc01e
Merge pull request #401 from jazzband/dependabot/pip/sphinx-rtd-theme-1.3.0
chore(deps): bump sphinx-rtd-theme from 1.2.2 to 1.3.0
2023-08-24 21:40:51 -07:00
dependabot[bot]
4f95e6cda7
chore(deps): bump sphinx-rtd-theme from 1.2.2 to 1.3.0
Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 1.2.2 to 1.3.0.
- [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst)
- [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/1.2.2...1.3.0)

---
updated-dependencies:
- dependency-name: sphinx-rtd-theme
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-25 04:38:23 +00:00
Mike
860bc7bcf1
Merge pull request #400 from jazzband/dependabot/pip/hypothesis-6.82.6
chore(deps-dev): bump hypothesis from 6.82.0 to 6.82.6
2023-08-24 21:35:57 -07:00
dependabot[bot]
170c95a94c
chore(deps-dev): bump hypothesis from 6.82.0 to 6.82.6
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.82.0 to 6.82.6.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.82.0...hypothesis-python-6.82.6)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-25 04:33:09 +00:00
Mike
f84542b115
Merge pull request #398 from jazzband/dependabot/pip/mypy-1.5.1
chore(deps-dev): bump mypy from 1.4.1 to 1.5.1
2023-08-24 21:31:37 -07:00
dependabot[bot]
5be3e8006a
chore(deps-dev): bump mypy from 1.4.1 to 1.5.1
Bumps [mypy](https://github.com/python/mypy) from 1.4.1 to 1.5.1.
- [Commits](https://github.com/python/mypy/compare/v1.4.1...v1.5.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-25 04:08:33 +00:00
Mike
bb381255bc
Merge pull request #399 from jazzband/dependabot/pip/nitpick-0.34.0
chore(deps-dev): bump nitpick from 0.33.2 to 0.34.0
2023-08-24 21:07:17 -07:00
dependabot[bot]
70354a96e5
chore(deps-dev): bump nitpick from 0.33.2 to 0.34.0
Bumps [nitpick](https://github.com/andreoliwa/nitpick) from 0.33.2 to 0.34.0.
- [Release notes](https://github.com/andreoliwa/nitpick/releases)
- [Changelog](https://github.com/andreoliwa/nitpick/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/andreoliwa/nitpick/compare/v0.33.2...v0.34.0)

---
updated-dependencies:
- dependency-name: nitpick
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-25 03:53:06 +00:00
Mike
6df9405a98
Merge pull request #404 from jazzband/dependabot/pip/gitpython-3.1.32
chore(deps-dev): bump gitpython from 3.1.30 to 3.1.32
2023-08-24 20:52:47 -07:00
Mike
83e2e3e47e
Merge pull request #402 from jazzband/dependabot/pip/certifi-2023.7.22
chore(deps): bump certifi from 2022.12.7 to 2023.7.22
2023-08-24 20:51:36 -07:00
Mike
137c77e4e0
Merge pull request #403 from jazzband/dependabot/pip/pygments-2.15.0
chore(deps): bump pygments from 2.14.0 to 2.15.0
2023-08-24 20:51:26 -07:00
Mike
31a354216f
Merge pull request #397 from jazzband/dependabot/pip/pytest-randomly-3.15.0
chore(deps-dev): bump pytest-randomly from 3.13.0 to 3.15.0
2023-08-24 20:50:52 -07:00
dependabot[bot]
78469530f9
chore(deps-dev): bump gitpython from 3.1.30 to 3.1.32
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.30 to 3.1.32.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.30...3.1.32)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-25 03:44:15 +00:00
dependabot[bot]
eeb66ca73f
chore(deps-dev): bump pytest-randomly from 3.13.0 to 3.15.0
Bumps [pytest-randomly](https://github.com/pytest-dev/pytest-randomly) from 3.13.0 to 3.15.0.
- [Changelog](https://github.com/pytest-dev/pytest-randomly/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-randomly/compare/3.13.0...3.15.0)

---
updated-dependencies:
- dependency-name: pytest-randomly
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-25 03:44:06 +00:00
dependabot[bot]
c9b3068adf
chore(deps): bump certifi from 2022.12.7 to 2023.7.22
Bumps [certifi](https://github.com/certifi/python-certifi) from 2022.12.7 to 2023.7.22.
- [Commits](https://github.com/certifi/python-certifi/compare/2022.12.07...2023.07.22)

---
updated-dependencies:
- dependency-name: certifi
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-25 03:43:05 +00:00
dependabot[bot]
a6fc17ee2f
chore(deps): bump pygments from 2.14.0 to 2.15.0
Bumps [pygments](https://github.com/pygments/pygments) from 2.14.0 to 2.15.0.
- [Release notes](https://github.com/pygments/pygments/releases)
- [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES)
- [Commits](https://github.com/pygments/pygments/compare/2.14.0...2.15.0)

---
updated-dependencies:
- dependency-name: pygments
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-25 03:43:05 +00:00
Mike
245424d215
Merge pull request #391 from jazzband/dependabot/pip/django-4.2.4
chore(deps): bump django from 4.2.3 to 4.2.4
2023-08-24 20:42:14 -07:00
Mike
50ce01bfad
Merge pull request #390 from jazzband/dependabot/pip/tomlkit-0.12.1
chore(deps): bump tomlkit from 0.11.8 to 0.12.1
2023-08-24 20:42:05 -07:00
dependabot[bot]
9f30879186
chore(deps): bump django from 4.2.3 to 4.2.4
Bumps [django](https://github.com/django/django) from 4.2.3 to 4.2.4.
- [Commits](https://github.com/django/django/compare/4.2.3...4.2.4)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-02 02:41:08 +00:00
dependabot[bot]
d897e82f62
chore(deps): bump tomlkit from 0.11.8 to 0.12.1
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.11.8 to 0.12.1.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.11.8...0.12.1)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-28 02:38:45 +00:00
Mike
643a959342
Merge pull request #389 from jazzband/dependabot/pip/hypothesis-6.82.0
chore(deps-dev): bump hypothesis from 6.81.1 to 6.82.0
2023-07-25 14:02:17 -07:00
Mike
ba45668048
Merge pull request #388 from jazzband/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2023-07-25 14:02:10 -07:00
dependabot[bot]
918a3b02f8
chore(deps-dev): bump hypothesis from 6.81.1 to 6.82.0
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.81.1 to 6.82.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.81.1...hypothesis-python-6.82.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-21 02:56:23 +00:00
pre-commit-ci[bot]
2b47d463e4
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 23.3.0 → 23.7.0](https://github.com/psf/black/compare/23.3.0...23.7.0)
2023-07-17 20:26:41 +00:00
Mike
26d8984fe4
Merge pull request #386 from jazzband/dependabot/pip/pytest-randomly-3.13.0
chore(deps-dev): bump pytest-randomly from 3.12.0 to 3.13.0
2023-07-13 19:52:44 -07:00
dependabot[bot]
d5e6998b07
chore(deps-dev): bump pytest-randomly from 3.12.0 to 3.13.0
Bumps [pytest-randomly](https://github.com/pytest-dev/pytest-randomly) from 3.12.0 to 3.13.0.
- [Changelog](https://github.com/pytest-dev/pytest-randomly/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-randomly/compare/3.12.0...3.13.0)

---
updated-dependencies:
- dependency-name: pytest-randomly
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-14 02:44:54 +00:00
Mike
f18e2d5c99
Merge pull request #385 from jazzband/dependabot/pip/hypothesis-6.81.1
chore(deps-dev): bump hypothesis from 6.80.1 to 6.81.1
2023-07-13 19:42:44 -07:00
dependabot[bot]
ea129e7df1
chore(deps-dev): bump hypothesis from 6.80.1 to 6.81.1
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.80.1 to 6.81.1.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.80.1...hypothesis-python-6.81.1)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-11 02:50:35 +00:00
Mike
dcfc74e8ae 1.4.0 2023-07-07 13:11:50 -07:00
Mike
ed7af1bf11
Merge pull request #384 from jazzband/dependabot/pip/hypothesis-6.80.1
chore(deps-dev): bump hypothesis from 6.80.0 to 6.80.1
2023-07-07 12:49:00 -07:00
Mike
7732ca60f4
Merge pull request #382 from jazzband/dependabot/pip/django-4.2.3
chore(deps): bump django from 4.2.2 to 4.2.3
2023-07-07 12:48:34 -07:00
dependabot[bot]
0acc6fc926
chore(deps-dev): bump hypothesis from 6.80.0 to 6.80.1
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.80.0 to 6.80.1.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.80.0...hypothesis-python-6.80.1)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-07 02:52:08 +00:00
dependabot[bot]
a5a0e132ee
chore(deps): bump django from 4.2.2 to 4.2.3
Bumps [django](https://github.com/django/django) from 4.2.2 to 4.2.3.
- [Commits](https://github.com/django/django/compare/4.2.2...4.2.3)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-04 02:37:40 +00:00
Mike
a576fc8b68
Merge pull request #380 from jazzband/dependabot/pip/hypothesis-6.80.0
chore(deps-dev): bump hypothesis from 6.79.3 to 6.80.0
2023-07-02 17:03:22 -07:00
Mike
9c0aeb6f90
Merge pull request #381 from kiraware/add-id-translations
add id translations
2023-07-02 17:02:39 -07:00
Kira
208317322c update CHANGELOG 2023-06-29 17:25:55 +08:00
Kira
d1e13cab4a add id translations 2023-06-29 17:14:00 +08:00
dependabot[bot]
ac90f43db0
chore(deps-dev): bump hypothesis from 6.79.3 to 6.80.0
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.79.3 to 6.80.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.79.3...hypothesis-python-6.80.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-28 03:00:01 +00:00
Mike
fbe4b86cb0
Merge pull request #379 from jazzband/dependabot/pip/hypothesis-6.79.3
chore(deps-dev): bump hypothesis from 6.79.2 to 6.79.3
2023-06-26 20:03:43 -07:00
dependabot[bot]
d05bde1ef2
chore(deps-dev): bump hypothesis from 6.79.2 to 6.79.3
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.79.2 to 6.79.3.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.79.2...hypothesis-python-6.79.3)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-27 02:59:11 +00:00
Mike
8ebf8327e2
Merge pull request #378 from jazzband/dependabot/pip/mypy-1.4.1
chore(deps-dev): bump mypy from 1.4.0 to 1.4.1
2023-06-26 07:30:35 -07:00
dependabot[bot]
bb39b757ec
chore(deps-dev): bump mypy from 1.4.0 to 1.4.1
Bumps [mypy](https://github.com/python/mypy) from 1.4.0 to 1.4.1.
- [Commits](https://github.com/python/mypy/compare/v1.4.0...v1.4.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-26 02:59:11 +00:00
dependabot[bot]
6b512cfa1a
Merge pull request #377 from jazzband/dependabot/pip/hypothesis-6.79.2 2023-06-26 00:16:39 +00:00
dependabot[bot]
d982bdf1bd
chore(deps-dev): bump hypothesis from 6.78.3 to 6.79.2
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.78.3 to 6.79.2.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.78.3...hypothesis-python-6.79.2)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-26 00:14:28 +00:00
Mike
7b3f9ffde0
Merge pull request #376 from jazzband/dependabot/pip/mypy-1.4.0
chore(deps-dev): bump mypy from 1.3.0 to 1.4.0
2023-06-25 17:01:08 -07:00
dependabot[bot]
07b2f6c95a
chore(deps-dev): bump mypy from 1.3.0 to 1.4.0
Bumps [mypy](https://github.com/python/mypy) from 1.3.0 to 1.4.0.
- [Commits](https://github.com/python/mypy/compare/v1.3.0...v1.4.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-21 02:59:24 +00:00
Mike
bae84976d6
Merge pull request #374 from jazzband/dependabot/pip/hypothesis-6.78.3
chore(deps-dev): bump hypothesis from 6.76.0 to 6.78.3
2023-06-18 18:56:42 -07:00
dependabot[bot]
1abaf9c161
chore(deps-dev): bump hypothesis from 6.76.0 to 6.78.3
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.76.0 to 6.78.3.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.76.0...hypothesis-python-6.78.3)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-16 03:09:21 +00:00
Mike
870ea499f2
Merge pull request #371 from jazzband/dependabot/pip/sphinx-rtd-theme-1.2.2
chore(deps): bump sphinx-rtd-theme from 1.2.1 to 1.2.2
2023-06-15 20:05:03 -07:00
Mike
15514ff671
Merge pull request #370 from jazzband/dependabot/pip/django-4.2.2
chore(deps): bump django from 4.2.1 to 4.2.2
2023-06-15 20:04:24 -07:00
dependabot[bot]
847c48ac78
chore(deps): bump sphinx-rtd-theme from 1.2.1 to 1.2.2
Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 1.2.1 to 1.2.2.
- [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst)
- [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/1.2.1...1.2.2)

---
updated-dependencies:
- dependency-name: sphinx-rtd-theme
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-08 03:00:35 +00:00
dependabot[bot]
07bc101e5e
chore(deps): bump django from 4.2.1 to 4.2.2
Bumps [django](https://github.com/django/django) from 4.2.1 to 4.2.2.
- [Commits](https://github.com/django/django/compare/4.2.1...4.2.2)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-06 03:11:55 +00:00
Mike
21ea6e584d
Merge pull request #369 from jazzband/dependabot/pip/hypothesis-6.76.0
chore(deps-dev): bump hypothesis from 6.75.3 to 6.76.0
2023-06-04 20:51:08 -07:00
dependabot[bot]
199c1c83f9
chore(deps-dev): bump hypothesis from 6.75.3 to 6.76.0
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.75.3 to 6.76.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.75.3...hypothesis-python-6.76.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-06-05 03:48:27 +00:00
Mike
ec664671b8
Merge pull request #366 from jazzband/dependabot/pip/nitpick-0.33.2
chore(deps-dev): bump nitpick from 0.33.1 to 0.33.2
2023-06-04 20:47:07 -07:00
Mike
4268ce318a
Merge pull request #364 from jazzband/dependabot/pip/pytest-cov-4.1.0
chore(deps-dev): bump pytest-cov from 4.0.0 to 4.1.0
2023-06-04 20:46:55 -07:00
Mike
074eba2b1f
Merge pull request #363 from jazzband/dependabot/pip/sphinx-rtd-theme-1.2.1
chore(deps): bump sphinx-rtd-theme from 1.2.0 to 1.2.1
2023-06-04 20:46:46 -07:00
Mike
a6b8c924de
Merge pull request #362 from jazzband/dependabot/pip/requests-2.31.0
chore(deps): bump requests from 2.28.2 to 2.31.0
2023-06-04 20:46:35 -07:00
dependabot[bot]
e4212676ae
chore(deps-dev): bump nitpick from 0.33.1 to 0.33.2
Bumps [nitpick](https://github.com/andreoliwa/nitpick) from 0.33.1 to 0.33.2.
- [Release notes](https://github.com/andreoliwa/nitpick/releases)
- [Changelog](https://github.com/andreoliwa/nitpick/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/andreoliwa/nitpick/compare/v0.33.1...v0.33.2)

---
updated-dependencies:
- dependency-name: nitpick
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-30 03:00:36 +00:00
dependabot[bot]
c52ef43b9c
chore(deps-dev): bump pytest-cov from 4.0.0 to 4.1.0
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 4.0.0 to 4.1.0.
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v4.0.0...v4.1.0)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-25 03:01:17 +00:00
dependabot[bot]
254fdfa16d
chore(deps): bump sphinx-rtd-theme from 1.2.0 to 1.2.1
Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 1.2.0 to 1.2.1.
- [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst)
- [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/1.2.0...1.2.1)

---
updated-dependencies:
- dependency-name: sphinx-rtd-theme
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-24 02:58:50 +00:00
dependabot[bot]
fc9864ffcb
chore(deps): bump requests from 2.28.2 to 2.31.0
Bumps [requests](https://github.com/psf/requests) from 2.28.2 to 2.31.0.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.28.2...v2.31.0)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-23 06:14:04 +00:00
Mike
3d91eb7df7
Merge pull request #361 from jazzband/dependabot/pip/hypothesis-6.75.3
chore(deps-dev): bump hypothesis from 6.74.1 to 6.75.3
2023-05-20 06:38:19 -07:00
dependabot[bot]
09563d839e
chore(deps-dev): bump hypothesis from 6.74.1 to 6.75.3
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.74.1 to 6.75.3.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.74.1...hypothesis-python-6.75.3)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-19 20:44:08 +00:00
Mike
93445341e1
Merge pull request #360 from jazzband/dependabot/pip/mypy-1.3.0
chore(deps-dev): bump mypy from 1.2.0 to 1.3.0
2023-05-19 13:42:50 -07:00
Mike
e0c3ef3db3
Merge pull request #358 from jazzband/dependabot/pip/django-4.2.1
chore(deps): bump django from 4.2 to 4.2.1
2023-05-19 13:41:59 -07:00
dependabot[bot]
674d5ecb2b
chore(deps-dev): bump mypy from 1.2.0 to 1.3.0
Bumps [mypy](https://github.com/python/mypy) from 1.2.0 to 1.3.0.
- [Commits](https://github.com/python/mypy/compare/v1.2.0...v1.3.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-11 02:59:18 +00:00
dependabot[bot]
2cf8c86bc5
chore(deps): bump django from 4.2 to 4.2.1
Bumps [django](https://github.com/django/django) from 4.2 to 4.2.1.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/4.2...4.2.1)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-04 03:03:21 +00:00
Mike
1a0df67fed
Merge pull request #356 from jazzband/dependabot/pip/tomlkit-0.11.8
chore(deps): bump tomlkit from 0.11.7 to 0.11.8
2023-04-28 07:08:00 -07:00
Mike
38a5516500
Merge pull request #355 from jazzband/dependabot/pip/hypothesis-6.74.1
chore(deps-dev): bump hypothesis from 6.72.2 to 6.74.1
2023-04-28 07:07:53 -07:00
Mike
811e981eb4
Merge pull request #353 from jazzband/dependabot/pip/sphinx-6.2.1
chore(deps): bump sphinx from 6.2.0 to 6.2.1
2023-04-28 07:07:43 -07:00
dependabot[bot]
579fd904fc
chore(deps): bump tomlkit from 0.11.7 to 0.11.8
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.11.7 to 0.11.8.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.11.7...0.11.8)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-28 02:59:47 +00:00
dependabot[bot]
21a74f377b
chore(deps-dev): bump hypothesis from 6.72.2 to 6.74.1
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.72.2 to 6.74.1.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.72.2...hypothesis-python-6.74.1)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-28 02:59:05 +00:00
dependabot[bot]
634b8c14ad
chore(deps): bump sphinx from 6.2.0 to 6.2.1
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 6.2.0 to 6.2.1.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v6.2.0...v6.2.1)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-26 02:59:58 +00:00
Mike
7164ba4aac
Merge pull request #351 from jazzband/dependabot/pip/hypothesis-6.72.2
chore(deps-dev): bump hypothesis from 6.72.0 to 6.72.2
2023-04-25 18:54:46 -07:00
Mike
a2aef1fe06
Merge pull request #350 from jazzband/dependabot/pip/sphinx-6.2.0
chore(deps): bump sphinx from 6.1.3 to 6.2.0
2023-04-25 18:54:35 -07:00
Mike
fce27c840f
Merge pull request #349 from jazzband/dependabot/pip/sqlparse-0.4.4
chore(deps): bump sqlparse from 0.4.3 to 0.4.4
2023-04-25 18:54:26 -07:00
dependabot[bot]
ae04b34925
chore(deps-dev): bump hypothesis from 6.72.0 to 6.72.2
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.72.0 to 6.72.2.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.72.0...hypothesis-python-6.72.2)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-25 03:01:17 +00:00
dependabot[bot]
4dc89cfd20
chore(deps): bump sphinx from 6.1.3 to 6.2.0
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 6.1.3 to 6.2.0.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v6.1.3...v6.2.0)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 03:04:09 +00:00
dependabot[bot]
fbd671903f
chore(deps): bump sqlparse from 0.4.3 to 0.4.4
Bumps [sqlparse](https://github.com/andialbrecht/sqlparse) from 0.4.3 to 0.4.4.
- [Release notes](https://github.com/andialbrecht/sqlparse/releases)
- [Changelog](https://github.com/andialbrecht/sqlparse/blob/master/CHANGELOG)
- [Commits](https://github.com/andialbrecht/sqlparse/compare/0.4.3...0.4.4)

---
updated-dependencies:
- dependency-name: sqlparse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-21 22:45:54 +00:00
Mike
667680d479
Merge pull request #347 from jazzband/dependabot/pip/hypothesis-6.72.0
chore(deps-dev): bump hypothesis from 6.70.2 to 6.72.0
2023-04-16 21:38:26 -07:00
Mike
fb124d533b
Merge pull request #346 from jazzband/dependabot/pip/sphinx-autodoc-typehints-1.23.0
chore(deps): bump sphinx-autodoc-typehints from 1.22 to 1.23.0
2023-04-16 21:38:17 -07:00
dependabot[bot]
30112dc805
chore(deps-dev): bump hypothesis from 6.70.2 to 6.72.0
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.70.2 to 6.72.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.70.2...hypothesis-python-6.72.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-17 03:03:30 +00:00
dependabot[bot]
8ed82e9173
chore(deps): bump sphinx-autodoc-typehints from 1.22 to 1.23.0
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.22 to 1.23.0.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.22...1.23.0)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-14 02:59:29 +00:00
Mike
891b257a50
Merge pull request #344 from jazzband/dependabot/pip/mypy-1.2.0
chore(deps-dev): bump mypy from 1.1.1 to 1.2.0
2023-04-09 19:04:29 -07:00
dependabot[bot]
0b8d20d07c
chore(deps-dev): bump mypy from 1.1.1 to 1.2.0
Bumps [mypy](https://github.com/python/mypy) from 1.1.1 to 1.2.0.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v1.1.1...v1.2.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-07 03:02:37 +00:00
Mike
b352f3ef30
Merge pull request #343 from jazzband/dependabot/pip/django-4.2
chore(deps): bump django from 4.1.7 to 4.2
2023-04-05 07:24:25 -07:00
dependabot[bot]
95a2d5217b
chore(deps): bump django from 4.1.7 to 4.2
Bumps [django](https://github.com/django/django) from 4.1.7 to 4.2.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/4.1.7...4.2)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-05 14:21:56 +00:00
Mike
437fcc4335
Merge pull request #342 from jazzband/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2023-04-05 07:20:06 -07:00
Mike
e55af3f1fc
Merge pull request #341 from jazzband/dependabot/pip/hypothesis-6.70.2
chore(deps-dev): bump hypothesis from 6.70.0 to 6.70.2
2023-04-05 07:19:58 -07:00
Mike
0a3ca02876
Merge pull request #340 from jazzband/dependabot/pip/nitpick-0.33.1
chore(deps-dev): bump nitpick from 0.33.0 to 0.33.1
2023-04-05 07:19:48 -07:00
pre-commit-ci[bot]
b7aae3980d
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 23.1.0 → 23.3.0](https://github.com/psf/black/compare/23.1.0...23.3.0)
2023-04-03 20:19:05 +00:00
dependabot[bot]
4ae6d71c28
chore(deps-dev): bump hypothesis from 6.70.0 to 6.70.2
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.70.0 to 6.70.2.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.70.0...hypothesis-python-6.70.2)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-03 03:05:04 +00:00
dependabot[bot]
1a6dc445db
chore(deps-dev): bump nitpick from 0.33.0 to 0.33.1
Bumps [nitpick](https://github.com/andreoliwa/nitpick) from 0.33.0 to 0.33.1.
- [Release notes](https://github.com/andreoliwa/nitpick/releases)
- [Changelog](https://github.com/andreoliwa/nitpick/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/andreoliwa/nitpick/compare/v0.33.0...v0.33.1)

---
updated-dependencies:
- dependency-name: nitpick
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-30 03:00:16 +00:00
Mike
2f9f41b153
Merge pull request #338 from jazzband/dependabot/pip/tomlkit-0.11.7
chore(deps): bump tomlkit from 0.11.6 to 0.11.7
2023-03-27 20:03:50 -07:00
Mike
9818ec12f8
Merge pull request #337 from jazzband/dependabot/pip/nitpick-0.33.0
chore(deps-dev): bump nitpick from 0.32.0 to 0.33.0
2023-03-27 20:02:42 -07:00
dependabot[bot]
15de2e054c
chore(deps): bump tomlkit from 0.11.6 to 0.11.7
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.11.6 to 0.11.7.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.11.6...0.11.7)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-28 03:01:40 +00:00
dependabot[bot]
6b9e32e256
chore(deps-dev): bump nitpick from 0.32.0 to 0.33.0
Bumps [nitpick](https://github.com/andreoliwa/nitpick) from 0.32.0 to 0.33.0.
- [Release notes](https://github.com/andreoliwa/nitpick/releases)
- [Changelog](https://github.com/andreoliwa/nitpick/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/andreoliwa/nitpick/compare/v0.32.0...v0.33.0)

---
updated-dependencies:
- dependency-name: nitpick
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-28 03:00:30 +00:00
Mike
c3c009d5ea
Merge pull request #335 from jazzband/dependabot/pip/hypothesis-6.70.0
chore(deps-dev): bump hypothesis from 6.68.2 to 6.70.0
2023-03-25 19:01:08 -07:00
dependabot[bot]
c426a99907
chore(deps-dev): bump hypothesis from 6.68.2 to 6.70.0
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.68.2 to 6.70.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.68.2...hypothesis-python-6.70.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-17 03:01:39 +00:00
Mike
ef2da8b68a
Merge pull request #333 from jazzband/dependabot/pip/mypy-1.1.1
chore(deps-dev): bump mypy from 1.0.1 to 1.1.1
2023-03-15 09:17:58 -07:00
dependabot[bot]
75f70aa3d6
chore(deps-dev): bump mypy from 1.0.1 to 1.1.1
Bumps [mypy](https://github.com/python/mypy) from 1.0.1 to 1.1.1.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v1.0.1...v1.1.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-07 03:01:07 +00:00
Mike
a6ade067cc chore: release 1.3.1 2023-02-22 10:37:41 -07:00
Mike
4c67210346
Merge pull request #329 from jazzband/dependabot/pip/hypothesis-6.68.2
chore(deps-dev): bump hypothesis from 6.68.1 to 6.68.2
2023-02-22 10:33:33 -07:00
Mike
48e90dd276
Merge pull request #332 from Dresdn/Dresdn/issue-331
chore: generate migrations for model changes
2023-02-22 10:33:09 -07:00
Mike
daf7975fe0 ci: specify additional_dependencies for migration hook check to install 2023-02-22 08:18:43 -07:00
Mike
8fbd18bf79 fix: generating migration for model text changes 2023-02-22 08:09:36 -07:00
Mike
f1831deafa style: ignore string over-use in migrations files 2023-02-22 08:08:59 -07:00
Mike
8cc237e7a3 ci: check for missing migrations 2023-02-22 08:08:47 -07:00
dependabot[bot]
21ad1cc78a
chore(deps-dev): bump hypothesis from 6.68.1 to 6.68.2
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.68.1 to 6.68.2.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.68.1...hypothesis-python-6.68.2)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-22 05:51:12 +00:00
Mike
d8c3a47352
Merge pull request #328 from jazzband/dependabot/pip/flake8-pytest-style-1.7.2
chore(deps-dev): bump flake8-pytest-style from 1.7.0 to 1.7.2
2023-02-21 22:49:27 -07:00
dependabot[bot]
fc1638e5c9
chore(deps-dev): bump flake8-pytest-style from 1.7.0 to 1.7.2
Bumps [flake8-pytest-style](https://github.com/m-burst/flake8-pytest-style) from 1.7.0 to 1.7.2.
- [Release notes](https://github.com/m-burst/flake8-pytest-style/releases)
- [Commits](https://github.com/m-burst/flake8-pytest-style/compare/v1.7.0...v1.7.2)

---
updated-dependencies:
- dependency-name: flake8-pytest-style
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-22 05:44:00 +00:00
Mike
157e490815
Merge pull request #330 from jazzband/dependabot/pip/mypy-1.0.1
chore(deps-dev): bump mypy from 1.0.0 to 1.0.1
2023-02-21 22:41:47 -07:00
Mike
c9efddb009
Merge pull request #325 from jazzband/dependabot/pip/sphinx-6.1.3
chore(deps): bump sphinx from 5.3.0 to 6.1.3
2023-02-21 22:41:17 -07:00
dependabot[bot]
90de1963c9
chore(deps-dev): bump mypy from 1.0.0 to 1.0.1
Bumps [mypy](https://github.com/python/mypy) from 1.0.0 to 1.0.1.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v1.0.0...v1.0.1)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-20 03:27:43 +00:00
dependabot[bot]
97e7d1df85
chore(deps): bump sphinx from 5.3.0 to 6.1.3
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 5.3.0 to 6.1.3.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v5.3.0...v6.1.3)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-16 16:22:40 +00:00
Mike
5db82070e6
Merge pull request #326 from jazzband/dependabot/pip/django-4.1.7
chore(deps): bump django from 4.1.6 to 4.1.7
2023-02-16 08:38:07 -07:00
Mike
38c98515f9
Merge pull request #324 from jazzband/dependabot/pip/hypothesis-6.68.1
chore(deps-dev): bump hypothesis from 6.68.0 to 6.68.1
2023-02-16 08:37:52 -07:00
dependabot[bot]
1857129417
chore(deps): bump django from 4.1.6 to 4.1.7
Bumps [django](https://github.com/django/django) from 4.1.6 to 4.1.7.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/4.1.6...4.1.7)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-15 03:01:02 +00:00
dependabot[bot]
0c05f27771
chore(deps-dev): bump hypothesis from 6.68.0 to 6.68.1
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.68.0 to 6.68.1.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.68.0...hypothesis-python-6.68.1)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-13 03:31:16 +00:00
Mike
7cd0fb5295 chore: release 1.3.0 2023-02-10 10:22:32 -07:00
Mike
aa99a5a038
Merge pull request #323 from Dresdn/Dresdn/issue-322
Support Django 4.1
2023-02-10 10:11:14 -07:00
Mike
aa64b961d1 test: remove django_jsonfield_backport app 2023-02-10 10:05:48 -07:00
Mike
8718968a36 docs: update changelog 2023-02-10 10:02:49 -07:00
Mike
637e0ecf84 chore(deps): update all dependencies 2023-02-10 10:01:34 -07:00
Mike
9d6aad3924 feat: add support for Django 4.1 2023-02-10 09:59:54 -07:00
Mike
066ae8e310 chore: remove support for Django 2.2 2023-02-10 09:56:08 -07:00
Mike
a98c0d2904
Use SplitDateTimeField for date Attribute types (#321)
* fix: use field class SplitDateTimeField for type 'date'
Fixes #261

* refactor: remove import conflict of django.forms

* style: isort imports

* docs: add fix #261 to changelog
2023-02-10 08:35:05 -08:00
954
d6a05a0ccb
chore(locale): update translation of zh_Hans (#318) 2023-02-10 06:33:40 -08:00
dependabot[bot]
952e6a1ffa
chore(deps-dev): bump hypothesis from 6.67.1 to 6.68.0 (#320)
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.67.1 to 6.68.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.67.1...hypothesis-python-6.68.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-09 19:08:01 -08:00
dependabot[bot]
9746e0146a
chore(deps): bump sphinx-rtd-theme from 1.1.1 to 1.2.0 (#319)
Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 1.1.1 to 1.2.0.
- [Release notes](https://github.com/readthedocs/sphinx_rtd_theme/releases)
- [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst)
- [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/1.1.1...1.2.0)

---
updated-dependencies:
- dependency-name: sphinx-rtd-theme
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-07 19:45:56 -08:00
dependabot[bot]
92810bee53
chore(deps-dev): bump mypy from 0.991 to 1.0.0 (#317)
Bumps [mypy](https://github.com/python/mypy) from 0.991 to 1.0.0.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.991...v1.0.0)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-06 19:50:16 -08:00
pre-commit-ci[bot]
6047a9c486
[pre-commit.ci] pre-commit autoupdate (#316)
* [pre-commit.ci] pre-commit autoupdate

updates:
- [github.com/psf/black: 22.12.0 → 23.1.0](https://github.com/psf/black/compare/22.12.0...23.1.0)

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2023-02-06 19:48:54 -08:00
dependabot[bot]
ae5698e9bf
chore(deps-dev): bump hypothesis from 6.65.2 to 6.67.1 (#315)
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.65.2 to 6.67.1.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.65.2...hypothesis-python-6.67.1)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-06 08:08:11 -08:00
dependabot[bot]
bd52770377
chore(deps): bump django from 3.2.16 to 3.2.17 (#312)
Bumps [django](https://github.com/django/django) from 3.2.16 to 3.2.17.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.16...3.2.17)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-06 08:07:59 -08:00
954
116103b2a0
chore(models): fill verbose_name to most models. (#314)
* chore(models): fill `verbose_name` to most models.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2023-02-06 08:07:33 -08:00
dependabot[bot]
e6af204bbb
chore(deps): bump sphinx-autodoc-typehints from 1.21.8 to 1.22 (#311)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.21.8 to 1.22.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.21.8...1.22)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-31 07:36:09 -08:00
dependabot[bot]
f208f32010
chore(deps-dev): bump hypothesis from 6.65.1 to 6.65.2 (#310)
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.65.1 to 6.65.2.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.65.1...hypothesis-python-6.65.2)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-31 07:36:00 -08:00
dependabot[bot]
818ded9907
chore(deps-dev): bump hypothesis from 6.65.0 to 6.65.1 (#305)
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.65.0 to 6.65.1.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.65.0...hypothesis-python-6.65.1)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-28 06:58:51 -08:00
954
6bc1b19967
chore(locale): provide zh-Hans(Simplified Chinese) translation (#308)
* chore(locale): provide zh-Hans(Simplified Chinese) translation

* chore(locale/models): append `verbose_name` and `verbose_name_plural` for `eav.models`, to support translation.
2023-01-28 06:57:23 -08:00
dependabot[bot]
789f53bcc5
chore(deps-dev): bump hypothesis from 6.64.0 to 6.65.0 (#304)
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.64.0 to 6.65.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.64.0...hypothesis-python-6.65.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-26 12:40:14 -08:00
dependabot[bot]
eb0f2c80c8
chore(deps): bump sphinx-autodoc-typehints from 1.21.7 to 1.21.8 (#303)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.21.7 to 1.21.8.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.21.7...1.21.8)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-26 12:32:06 -08:00
dependabot[bot]
a85e808ac6
chore(deps-dev): bump hypothesis from 6.62.1 to 6.64.0 (#302)
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.62.1 to 6.64.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.62.1...hypothesis-python-6.64.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-22 19:36:09 -08:00
dependabot[bot]
8bd15f52e8
chore(deps): bump sphinx-autodoc-typehints from 1.21.5 to 1.21.7 (#301)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.21.5 to 1.21.7.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.21.5...1.21.7)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-22 19:35:54 -08:00
dependabot[bot]
90a7905190
chore(deps): bump sphinx-autodoc-typehints from 1.21.0 to 1.21.5 (#300)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.21.0 to 1.21.5.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.21.0...1.21.5)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-19 18:45:20 -08:00
dependabot[bot]
555c1e18c2
chore(deps): bump gitpython from 3.1.24 to 3.1.30 (#296)
Bumps [gitpython](https://github.com/gitpython-developers/GitPython) from 3.1.24 to 3.1.30.
- [Release notes](https://github.com/gitpython-developers/GitPython/releases)
- [Changelog](https://github.com/gitpython-developers/GitPython/blob/main/CHANGES)
- [Commits](https://github.com/gitpython-developers/GitPython/compare/3.1.24...3.1.30)

---
updated-dependencies:
- dependency-name: gitpython
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-16 12:06:48 -08:00
dependabot[bot]
f38d4ca762
chore(deps-dev): bump hypothesis from 6.61.0 to 6.62.1 (#295)
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.61.0 to 6.62.1.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.61.0...hypothesis-python-6.62.1)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-16 11:50:56 -08:00
dependabot[bot]
50275a50e7
chore(deps): bump sphinx-autodoc-typehints from 1.19.5 to 1.21.0 (#294)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.19.5 to 1.21.0.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.19.5...1.21.0)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-16 09:27:44 -08:00
dependabot[bot]
f8c820eaaf
chore(deps): bump setuptools from 65.3.0 to 65.5.1 (#290)
Bumps [setuptools](https://github.com/pypa/setuptools) from 65.3.0 to 65.5.1.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/CHANGES.rst)
- [Commits](https://github.com/pypa/setuptools/compare/v65.3.0...v65.5.1)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-01-16 06:56:33 -08:00
dependabot[bot]
02edf005d0
chore(deps-dev): bump hypothesis from 6.58.0 to 6.61.0 (#288)
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.58.0 to 6.61.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.58.0...hypothesis-python-6.61.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-15 11:59:03 -08:00
pre-commit-ci[bot]
a536ad4c6c
[pre-commit.ci] pre-commit autoupdate (#289)
updates:
- [github.com/psf/black: 22.10.0 → 22.12.0](https://github.com/psf/black/compare/22.10.0...22.12.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-12-15 11:52:35 -08:00
dependabot[bot]
387ebe5bfe
chore(deps-dev): bump black from 22.10.0 to 22.12.0 (#287)
Bumps [black](https://github.com/psf/black) from 22.10.0 to 22.12.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.10.0...22.12.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-15 11:52:21 -08:00
dependabot[bot]
674f58f6af
chore(deps-dev): bump safety from 2.3.2 to 2.3.5 (#286)
Bumps [safety](https://github.com/pyupio/safety) from 2.3.2 to 2.3.5.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/2.3.2...2.3.5)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-15 11:51:54 -08:00
dependabot[bot]
d02f9e6108
chore(deps): bump certifi from 2021.10.8 to 2022.12.7 (#285)
Bumps [certifi](https://github.com/certifi/python-certifi) from 2021.10.8 to 2022.12.7.
- [Release notes](https://github.com/certifi/python-certifi/releases)
- [Commits](https://github.com/certifi/python-certifi/compare/2021.10.08...2022.12.07)

---
updated-dependencies:
- dependency-name: certifi
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-15 11:51:29 -08:00
pre-commit-ci[bot]
9f7ce41be7
[pre-commit.ci] pre-commit autoupdate (#281)
updates:
- [github.com/pre-commit/pre-commit-hooks: v4.3.0 → v4.4.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.3.0...v4.4.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-11-28 18:29:18 -08:00
dependabot[bot]
71ccfb4751
chore(deps-dev): bump safety from 2.3.1 to 2.3.2 (#279)
Bumps [safety](https://github.com/pyupio/safety) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-21 18:52:58 -08:00
dependabot[bot]
7fb29e8ce5
chore(deps-dev): bump hypothesis from 6.56.4 to 6.58.0 (#278)
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.56.4 to 6.58.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.56.4...hypothesis-python-6.58.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-21 18:52:47 -08:00
Ihor Sychevskyi
ac070dba28
update links (#275) 2022-11-16 01:53:47 +02:00
dependabot[bot]
0e0572cf70
chore(deps-dev): bump mypy from 0.990 to 0.991 (#277)
Bumps [mypy](https://github.com/python/mypy) from 0.990 to 0.991.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.990...v0.991)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-14 18:17:34 -08:00
Ihor Sychevskyi
a06ac42fb6
update readme links (#273) 2022-11-13 11:36:49 +02:00
dependabot[bot]
e4122c413f
chore(deps): bump sphinx-rtd-theme from 1.0.0 to 1.1.1 (#271)
Bumps [sphinx-rtd-theme](https://github.com/readthedocs/sphinx_rtd_theme) from 1.0.0 to 1.1.1.
- [Release notes](https://github.com/readthedocs/sphinx_rtd_theme/releases)
- [Changelog](https://github.com/readthedocs/sphinx_rtd_theme/blob/master/docs/changelog.rst)
- [Commits](https://github.com/readthedocs/sphinx_rtd_theme/compare/1.0.0...1.1.1)

---
updated-dependencies:
- dependency-name: sphinx-rtd-theme
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-09 10:23:45 -08:00
dependabot[bot]
498727a5d8
chore(deps-dev): bump mypy from 0.982 to 0.990 (#270)
Bumps [mypy](https://github.com/python/mypy) from 0.982 to 0.990.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.982...v0.990)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-09 10:23:36 -08:00
dependabot[bot]
0d795fee5b
chore(deps): bump sphinx-autodoc-typehints from 1.19.4 to 1.19.5 (#269)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.19.4 to 1.19.5.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.19.4...1.19.5)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-11-09 10:23:23 -08:00
dependabot[bot]
09a651b76c
chore(deps-dev): bump hypothesis from 6.56.3 to 6.56.4 (#267)
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.56.3 to 6.56.4.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.56.3...hypothesis-python-6.56.4)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-31 09:13:31 -07:00
dependabot[bot]
451ccc3879
chore(deps): bump tomlkit from 0.11.5 to 0.11.6 (#266)
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.11.5 to 0.11.6.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.11.5...0.11.6)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-31 09:09:19 -07:00
dependabot[bot]
eba4502991
chore(deps-dev): bump hypothesis from 6.56.1 to 6.56.3 (#265)
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.56.1 to 6.56.3.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.56.1...hypothesis-python-6.56.3)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-17 19:34:03 -07:00
dependabot[bot]
996e5708ee
chore(deps): bump sphinx from 5.2.3 to 5.3.0 (#264)
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 5.2.3 to 5.3.0.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/master/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v5.2.3...v5.3.0)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-17 19:22:20 -07:00
pre-commit-ci[bot]
1ba5df9275
[pre-commit.ci] pre-commit autoupdate (#262)
updates:
- [github.com/psf/black: 22.8.0 → 22.10.0](https://github.com/psf/black/compare/22.8.0...22.10.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-10-17 19:21:35 -07:00
dependabot[bot]
ee1f4d7e96
chore(deps-dev): bump black from 22.8.0 to 22.10.0 (#260)
Bumps [black](https://github.com/psf/black) from 22.8.0 to 22.10.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.8.0...22.10.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-08 14:03:20 -07:00
dependabot[bot]
63a58197b1
chore(deps-dev): bump safety from 2.2.0 to 2.3.1 (#259)
Bumps [safety](https://github.com/pyupio/safety) from 2.2.0 to 2.3.1.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/2.2.0...2.3.1)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-08 13:58:14 -07:00
dependabot[bot]
3deb032ffa
chore(deps-dev): bump hypothesis from 6.55.0 to 6.56.1 (#258)
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.55.0 to 6.56.1.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.55.0...hypothesis-python-6.56.1)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-08 13:48:21 -07:00
dependabot[bot]
2bd846c72e
chore(deps): bump django from 3.2.15 to 3.2.16 (#256)
Bumps [django](https://github.com/django/django) from 3.2.15 to 3.2.16.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.15...3.2.16)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-08 13:40:35 -07:00
dependabot[bot]
de1bb112fd
chore(deps-dev): bump mypy from 0.981 to 0.982 (#255)
Bumps [mypy](https://github.com/python/mypy) from 0.981 to 0.982.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.981...v0.982)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-08 13:40:23 -07:00
dependabot[bot]
58aa89ca36
chore(deps): bump sphinx from 5.2.2 to 5.2.3 (#253)
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 5.2.2 to 5.2.3.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/5.x/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v5.2.2...v5.2.3)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-08 13:40:06 -07:00
dependabot[bot]
93d21ae67c
chore(deps): bump sphinx-autodoc-typehints from 1.19.2 to 1.19.4 (#252)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.19.2 to 1.19.4.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.19.2...1.19.4)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-01 09:28:33 -07:00
dependabot[bot]
c3fa502738
chore(deps-dev): bump hypothesis from 6.54.6 to 6.55.0 (#251)
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.54.6 to 6.55.0.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.54.6...hypothesis-python-6.55.0)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-01 09:27:51 -07:00
dependabot[bot]
fbdca16704
chore(deps-dev): bump pytest-cov from 3.0.0 to 4.0.0 (#250)
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 3.0.0 to 4.0.0.
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v3.0.0...v4.0.0)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-29 14:08:50 -07:00
dependabot[bot]
23b24ce5c3
chore(deps): bump sphinx from 5.1.1 to 5.2.2 (#249)
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 5.1.1 to 5.2.2.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/5.x/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v5.1.1...v5.2.2)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-29 12:00:06 -07:00
dependabot[bot]
26187c0624
chore(deps-dev): bump mypy from 0.971 to 0.981 (#248)
Bumps [mypy](https://github.com/python/mypy) from 0.971 to 0.981.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.971...v0.981)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-29 11:59:36 -07:00
dependabot[bot]
7a8701ef9d
chore(deps): bump tomlkit from 0.11.4 to 0.11.5 (#247)
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.11.4 to 0.11.5.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.11.4...0.11.5)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-29 11:44:38 -07:00
dependabot[bot]
f08c4e0b43
chore(deps-dev): bump wemake-python-styleguide from 0.16.1 to 0.17.0 (#246)
Bumps [wemake-python-styleguide](https://github.com/wemake-services/wemake-python-styleguide) from 0.16.1 to 0.17.0.
- [Release notes](https://github.com/wemake-services/wemake-python-styleguide/releases)
- [Changelog](https://github.com/wemake-services/wemake-python-styleguide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/wemake-services/wemake-python-styleguide/compare/0.16.1...0.17.0)

---
updated-dependencies:
- dependency-name: wemake-python-styleguide
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-09-29 11:43:55 -07:00
Mike
228c172422
Merge pull request #244 from jazzband/dependabot/pip/safety-2.2.0
chore(deps-dev): bump safety from 2.1.1 to 2.2.0
2022-09-20 09:10:07 -07:00
dependabot[bot]
7a0de05139
chore(deps-dev): bump safety from 2.1.1 to 2.2.0
Bumps [safety](https://github.com/pyupio/safety) from 2.1.1 to 2.2.0.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/2.1.1...2.2.0)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-20 15:57:21 +00:00
Mike
0049971936
Merge pull request #243 from jazzband/dependabot/pip/hypothesis-6.54.6
chore(deps-dev): bump hypothesis from 6.54.5 to 6.54.6
2022-09-20 08:55:01 -07:00
Mike
0790f9aa40
Merge pull request #242 from jazzband/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2022-09-20 08:54:37 -07:00
dependabot[bot]
3e953b2619
chore(deps-dev): bump hypothesis from 6.54.5 to 6.54.6
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.54.5 to 6.54.6.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.54.5...hypothesis-python-6.54.6)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-19 02:22:07 +00:00
pre-commit-ci[bot]
523dfd08eb
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 22.6.0 → 22.8.0](https://github.com/psf/black/compare/22.6.0...22.8.0)
2022-09-05 18:27:42 +00:00
Mike
34f2d51194
Merge pull request #241 from jazzband/dependabot/pip/hypothesis-6.54.5
chore(deps-dev): bump hypothesis from 6.54.4 to 6.54.5
2022-09-05 07:03:43 -07:00
dependabot[bot]
1daa336dbc
chore(deps-dev): bump hypothesis from 6.54.4 to 6.54.5
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.54.4 to 6.54.5.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.54.4...hypothesis-python-6.54.5)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-05 13:02:12 +00:00
Mike
fb453ab711
Merge pull request #240 from jazzband/dependabot/pip/black-22.8.0
chore(deps-dev): bump black from 22.6.0 to 22.8.0
2022-09-03 08:16:47 -07:00
dependabot[bot]
2c12fd009f
chore(deps-dev): bump black from 22.6.0 to 22.8.0
Bumps [black](https://github.com/psf/black) from 22.6.0 to 22.8.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.6.0...22.8.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-01 14:08:04 +00:00
Mike
adb3302560
Merge pull request #238 from jazzband/dependabot/pip/hypothesis-6.54.4
chore(deps-dev): bump hypothesis from 6.54.3 to 6.54.4
2022-09-01 07:06:15 -07:00
Mike
d39eb45f12
Merge pull request #239 from mikalai-hryb/master
fix: correct BaseEntityAdmin
2022-08-31 17:47:32 -07:00
Mikalai Hryb
5760f20f7a fix BaseEntityAdmin 2022-09-01 01:01:43 +02:00
dependabot[bot]
439d609fa7
chore(deps-dev): bump hypothesis from 6.54.3 to 6.54.4
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.54.3 to 6.54.4.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.54.3...hypothesis-python-6.54.4)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-22 02:22:03 +00:00
Mike
883ddfabea chore: release 1.2.3 2022-08-15 12:07:07 -07:00
Mike
8807a07eb4
Merge pull request #236 from Dresdn/Dresdn/issue-235
Restructure dependencies
2022-08-15 12:00:30 -07:00
Mike
c5af0cec2a docs: add changes to bug fix section 2022-08-15 11:56:59 -07:00
Mike
cb52c151ed chore: reorganize black dep 2022-08-15 11:54:46 -07:00
Mike
eb1184f889 fix: mark sphinx-rtd-theme as optional 2022-08-15 11:53:39 -07:00
Mike
b0e22dce17 fix: #235 move doc8 to dev dependency section 2022-08-15 11:53:14 -07:00
Mike
a77dfc3826
Merge pull request #234 from jazzband/dependabot/pip/hypothesis-6.54.3
chore(deps-dev): bump hypothesis from 6.54.2 to 6.54.3
2022-08-14 20:53:16 -07:00
dependabot[bot]
12a08e2f2d
chore(deps-dev): bump hypothesis from 6.54.2 to 6.54.3
Bumps [hypothesis](https://github.com/HypothesisWorks/hypothesis) from 6.54.2 to 6.54.3.
- [Release notes](https://github.com/HypothesisWorks/hypothesis/releases)
- [Commits](https://github.com/HypothesisWorks/hypothesis/compare/hypothesis-python-6.54.2...hypothesis-python-6.54.3)

---
updated-dependencies:
- dependency-name: hypothesis
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-15 02:26:30 +00:00
Mike
a3116ab263 chore: release 1.2.2 2022-08-13 10:56:30 -07:00
Mike
f9fd4eb51f
Merge pull request #232 from jazzband/dependabot/pip/tomlkit-0.11.4
chore(deps): bump tomlkit from 0.11.1 to 0.11.4
2022-08-13 10:37:49 -07:00
dependabot[bot]
e98823fb6e
chore(deps): bump tomlkit from 0.11.1 to 0.11.4
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.11.1 to 0.11.4.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.11.1...0.11.4)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-13 17:34:51 +00:00
Mike
676ea27a79
Merge pull request #231 from Dresdn/Dresdn/issue-230
Update read the docs config
2022-08-13 10:31:59 -07:00
Mike
fc94c29138 chore: remove unneeded files 2022-08-13 10:22:32 -07:00
Mike
943a63fd84 chore: use new theme and clean up style errors 2022-08-13 10:22:22 -07:00
Mike
5e1193c0ee chore(deps): add sphinx-rtd-theme 2022-08-13 10:08:16 -07:00
Mike
62184d8ccf docs: resolve docstring error 2022-08-13 10:07:54 -07:00
Mike
9cb71074ec
Merge pull request #229 from Dresdn/Dresdn/issue-93a
docs: update config file path
2022-08-12 18:20:10 -07:00
Mike
5cf6f1d708 docs: update config file path 2022-08-12 18:19:47 -07:00
Mike
1a9e442567
Merge pull request #228 from Dresdn/Dresdn/issue-93
Update Read the Docs build
2022-08-12 18:06:15 -07:00
Mike
b59f556187 chore(deps): mark django as main dependency 2022-08-12 17:59:17 -07:00
Mike
a0de1686bc fix: #93 add read the docs config file 2022-08-12 17:58:10 -07:00
Mike
ba0577a5ae
Merge pull request #224 from jazzband/dependabot/pip/sphinx-autodoc-typehints-1.19.2
chore(deps-dev): bump sphinx-autodoc-typehints from 1.19.1 to 1.19.2
2022-08-12 16:48:49 -07:00
dependabot[bot]
479cbf93d3
chore(deps-dev): bump sphinx-autodoc-typehints from 1.19.1 to 1.19.2
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.19.1 to 1.19.2.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.19.1...1.19.2)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-12 22:53:13 +00:00
Mike
8a7d16d783
Merge pull request #227 from Dresdn/Dresdn/issue-223
Update the way Attribute.slug field is generated
2022-08-12 15:50:53 -07:00
Mike
bbf12d5413 doc: update CHANGELOG 2022-08-12 15:00:59 -07:00
Mike
0a3a6f6fd7 fix: use typing_extensions 2022-08-12 14:56:47 -07:00
Mike
e24edcdc2d ci: bump base coverage to 90% 2022-08-12 14:46:16 -07:00
Mike
fb83744dd9 test: remove deprecated slug test 2022-08-12 14:45:30 -07:00
Mike
31e12a0ef9 chore: remove unused EavSlugField 2022-08-12 14:36:49 -07:00
Mike
8c183333d1 chore: update text description 2022-08-12 14:24:47 -07:00
Mike
653ed7fd38 refactor: move generate_slug to logic 2022-08-12 14:23:41 -07:00
Mike
f6afc45613 fix: ensure a proper slug is generated 2022-08-12 14:00:35 -07:00
Mike
e5f9ecb9e9 chore: use Django's SlugField() for Attribute.slug 2022-08-12 13:36:26 -07:00
Mike
cc2acd0724 test: add Attribute model tests 2022-08-12 13:31:55 -07:00
Mike
c0a6188405 chore(deps): add hypothesis 2022-08-12 13:27:46 -07:00
Mike
850ee17187
Merge pull request #221 from jazzband/dependabot/pip/django-3.2.15
chore(deps-dev): bump django from 3.2.14 to 3.2.15
2022-08-05 07:27:59 -07:00
Mike
ab3e7093ad
Merge pull request #220 from jazzband/dependabot/pip/sphinx-autodoc-typehints-1.19.1
chore(deps-dev): bump sphinx-autodoc-typehints from 1.18.3 to 1.19.1
2022-08-05 07:27:49 -07:00
dependabot[bot]
9c0c1365c6
chore(deps-dev): bump django from 3.2.14 to 3.2.15
Bumps [django](https://github.com/django/django) from 3.2.14 to 3.2.15.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.14...3.2.15)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-04 02:27:42 +00:00
dependabot[bot]
c1b44e24d1
chore(deps-dev): bump sphinx-autodoc-typehints from 1.18.3 to 1.19.1
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.18.3 to 1.19.1.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.18.3...1.19.1)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-08-01 02:32:50 +00:00
Mike
0a2f15628f
Merge pull request #218 from jazzband/dependabot/pip/doc8-1.0.0
chore(deps-dev): bump doc8 from 0.11.2 to 1.0.0
2022-07-30 08:06:15 -07:00
dependabot[bot]
9965ce16c9
chore(deps-dev): bump doc8 from 0.11.2 to 1.0.0
Bumps [doc8](https://github.com/pycqa/doc8) from 0.11.2 to 1.0.0.
- [Release notes](https://github.com/pycqa/doc8/releases)
- [Commits](https://github.com/pycqa/doc8/compare/0.11.2...v1.0.0)

---
updated-dependencies:
- dependency-name: doc8
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-28 02:22:56 +00:00
Mike
b8f9a49f39
Merge pull request #217 from jazzband/dependabot/pip/sphinx-5.1.1
chore(deps-dev): bump sphinx from 5.0.2 to 5.1.1
2022-07-27 08:04:59 -07:00
dependabot[bot]
edce1cfa58
chore(deps-dev): bump sphinx from 5.0.2 to 5.1.1
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 5.0.2 to 5.1.1.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/5.x/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v5.0.2...v5.1.1)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-27 02:25:21 +00:00
Mike
71c7615aba
Merge pull request #215 from jazzband/dependabot/pip/mypy-0.971
chore(deps-dev): bump mypy from 0.961 to 0.971
2022-07-25 19:36:34 -07:00
Mike
33a87cdb5c
Merge pull request #214 from jazzband/dependabot/pip/safety-2.1.1
chore(deps-dev): bump safety from 2.1.0 to 2.1.1
2022-07-25 19:24:37 -07:00
dependabot[bot]
3c201a453c
chore(deps-dev): bump mypy from 0.961 to 0.971
Bumps [mypy](https://github.com/python/mypy) from 0.961 to 0.971.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.961...v0.971)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-20 02:23:43 +00:00
dependabot[bot]
7c5f6fc8d2
chore(deps-dev): bump safety from 2.1.0 to 2.1.1
Bumps [safety](https://github.com/pyupio/safety) from 2.1.0 to 2.1.1.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/2.1.1/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/2.1.0...2.1.1)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-19 02:29:13 +00:00
Mike
0941a6899a
Merge pull request #212 from jazzband/dependabot/pip/tomlkit-0.11.1
chore(deps-dev): bump tomlkit from 0.11.0 to 0.11.1
2022-07-15 08:57:31 -07:00
dependabot[bot]
432217db0b
chore(deps-dev): bump tomlkit from 0.11.0 to 0.11.1
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.11.0 to 0.11.1.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.11.0...0.11.1)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-15 15:47:12 +00:00
Mike
a3165f095c
Merge pull request #213 from jazzband/dependabot/pip/safety-2.1.0
chore(deps-dev): bump safety from 2.0.0 to 2.1.0
2022-07-15 08:45:04 -07:00
Mike
aa09555875
Merge pull request #211 from jazzband/dependabot/pip/django-3.2.14
chore(deps-dev): bump django from 3.2.13 to 3.2.14
2022-07-14 20:34:51 -07:00
Mike
0abd935cf1
Merge pull request #210 from jazzband/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2022-07-14 20:34:34 -07:00
dependabot[bot]
b9f745cdfe
chore(deps-dev): bump safety from 2.0.0 to 2.1.0
Bumps [safety](https://github.com/pyupio/safety) from 2.0.0 to 2.1.0.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/2.0.0...2.1.0)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-15 02:28:55 +00:00
dependabot[bot]
a6b3dcaaf3
chore(deps-dev): bump django from 3.2.13 to 3.2.14
Bumps [django](https://github.com/django/django) from 3.2.13 to 3.2.14.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.13...3.2.14)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-05 02:28:43 +00:00
Mike
af700aa9d0
Merge pull request #209 from jazzband/dependabot/pip/safety-2.0.0
chore(deps-dev): bump safety from 1.10.3 to 2.0.0
2022-07-04 11:31:19 -07:00
pre-commit-ci[bot]
be09b47bff
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/psf/black: 22.3.0 → 22.6.0](https://github.com/psf/black/compare/22.3.0...22.6.0)
2022-07-04 18:11:46 +00:00
dependabot[bot]
4d96b48091
chore(deps-dev): bump safety from 1.10.3 to 2.0.0
Bumps [safety](https://github.com/pyupio/safety) from 1.10.3 to 2.0.0.
- [Release notes](https://github.com/pyupio/safety/releases)
- [Changelog](https://github.com/pyupio/safety/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/pyupio/safety/compare/1.10.3...2.0.0)

---
updated-dependencies:
- dependency-name: safety
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-07-04 16:49:27 +00:00
Mike
f5a5fe9530
Merge pull request #208 from jazzband/dependabot/pip/black-22.6.0
chore(deps-dev): bump black from 22.3.0 to 22.6.0
2022-07-04 09:45:59 -07:00
dependabot[bot]
9d6953fedc
chore(deps-dev): bump black from 22.3.0 to 22.6.0
Bumps [black](https://github.com/psf/black) from 22.3.0 to 22.6.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.3.0...22.6.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-28 02:28:24 +00:00
Mike
b3b6410187
Merge pull request #207 from jazzband/dependabot/pip/sphinx-5.0.2
chore(deps-dev): bump sphinx from 5.0.1 to 5.0.2
2022-06-20 07:52:31 -07:00
Mike
2c6f1480bc
Merge pull request #206 from jazzband/pre-commit-ci-update-config
[pre-commit.ci] pre-commit autoupdate
2022-06-20 07:52:13 -07:00
dependabot[bot]
57e2c0caf6
chore(deps-dev): bump sphinx from 5.0.1 to 5.0.2
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 5.0.1 to 5.0.2.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/5.x/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v5.0.1...v5.0.2)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-17 02:37:02 +00:00
pre-commit-ci[bot]
a9061e8fe0
[pre-commit.ci] pre-commit autoupdate
updates:
- [github.com/pre-commit/pre-commit-hooks: v4.2.0 → v4.3.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.2.0...v4.3.0)
2022-06-13 18:09:33 +00:00
Mike
b5702fb68e
Merge pull request #205 from Dresdn/Dresdn/issue-187
fix: #187 return csv field value in widget
2022-06-12 22:05:57 -07:00
Mike
361eebf8cb chore: update changelog for #187 2022-06-12 22:00:29 -07:00
Mike
8332a39def fix: #187 provide eav value during field cleaning 2022-06-12 21:58:44 -07:00
Mike
d643bddb95 test: add TYPE_CSV form tests 2022-06-12 21:53:01 -07:00
dependabot[bot]
5a6cc40084
chore(deps-dev): bump sphinx-autodoc-typehints from 1.18.2 to 1.18.3 (#204)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.18.2 to 1.18.3.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.18.2...1.18.3)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-12 20:17:31 -07:00
dependabot[bot]
04f5fa4790
chore(deps): bump actions/setup-python from 3 to 4 (#202)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 3 to 4.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-11 14:51:04 -07:00
dependabot[bot]
e34ca74c86
chore(deps-dev): bump mypy from 0.960 to 0.961 (#201)
Bumps [mypy](https://github.com/python/mypy) from 0.960 to 0.961.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.960...v0.961)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-11 14:50:23 -07:00
dependabot[bot]
d5356317b9
chore(deps-dev): bump sphinx-autodoc-typehints from 1.18.1 to 1.18.2 (#200)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.18.1 to 1.18.2.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.18.1...1.18.2)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-06 19:42:50 -07:00
dependabot[bot]
75261682dc
chore(deps-dev): bump sphinx from 5.0.0 to 5.0.1 (#199)
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 5.0.0 to 5.0.1.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/5.x/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v5.0.0...v5.0.1)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-04 12:07:37 -07:00
dependabot[bot]
ba0c1d397d
chore(deps-dev): bump sphinx from 4.5.0 to 5.0.0 (#198)
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 4.5.0 to 5.0.0.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/5.x/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v4.5.0...v5.0.0)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-30 10:48:26 -07:00
dependabot[bot]
90a70f1ad6
chore(deps-dev): bump mypy from 0.950 to 0.960 (#197)
Bumps [mypy](https://github.com/python/mypy) from 0.950 to 0.960.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.950...v0.960)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-26 08:09:09 -07:00
dependabot[bot]
e37fbf4130
chore(deps-dev): bump pytest-randomly from 3.11.0 to 3.12.0 (#193)
Bumps [pytest-randomly](https://github.com/pytest-dev/pytest-randomly) from 3.11.0 to 3.12.0.
- [Release notes](https://github.com/pytest-dev/pytest-randomly/releases)
- [Changelog](https://github.com/pytest-dev/pytest-randomly/blob/main/HISTORY.rst)
- [Commits](https://github.com/pytest-dev/pytest-randomly/compare/3.11.0...3.12.0)

---
updated-dependencies:
- dependency-name: pytest-randomly
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-24 20:47:53 -07:00
dependabot[bot]
0e7f15a8fb
chore(deps-dev): bump tomlkit from 0.10.2 to 0.11.0 (#196)
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.10.2 to 0.11.0.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.10.2...0.11.0)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-24 20:41:48 -07:00
dependabot[bot]
5135fd164d
chore(deps-dev): bump doc8 from 0.11.1 to 0.11.2 (#194)
Bumps [doc8](https://github.com/pycqa/doc8) from 0.11.1 to 0.11.2.
- [Release notes](https://github.com/pycqa/doc8/releases)
- [Commits](https://github.com/pycqa/doc8/compare/0.11.1...0.11.2)

---
updated-dependencies:
- dependency-name: doc8
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-05-20 12:12:26 -07:00
cocorocho
4f9b34dacc
fix version typo (#195) 2022-05-20 12:12:08 -07:00
dependabot[bot]
470972405c
chore(deps-dev): bump mypy from 0.942 to 0.950 (#192)
Bumps [mypy](https://github.com/python/mypy) from 0.942 to 0.950.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.942...v0.950)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-27 19:26:36 -07:00
dependabot[bot]
a9489c817f
chore(deps-dev): bump tomlkit from 0.10.1 to 0.10.2 (#191)
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.10.1 to 0.10.2.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.10.1...0.10.2)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-24 22:31:12 -07:00
dependabot[bot]
482e05133f
chore(deps-dev): bump sphinx-autodoc-typehints from 1.17.0 to 1.18.1 (#190)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.17.0 to 1.18.1.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.17.0...1.18.1)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-18 07:59:35 -07:00
dependabot[bot]
9fd792e0a9
chore(deps-dev): bump django from 3.2.12 to 3.2.13 (#188)
Bumps [django](https://github.com/django/django) from 3.2.12 to 3.2.13.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.12...3.2.13)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-18 07:59:22 -07:00
dependabot[bot]
7b57853033
chore(deps): bump codecov/codecov-action from 2 to 3 (#186)
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 2 to 3.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-18 07:59:03 -07:00
pre-commit-ci[bot]
af46e14522
[pre-commit.ci] pre-commit autoupdate (#185)
updates:
- [github.com/pre-commit/pre-commit-hooks: v4.1.0 → v4.2.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.1.0...v4.2.0)
- [github.com/psf/black: 22.1.0 → 22.3.0](https://github.com/psf/black/compare/22.1.0...22.3.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-04-18 07:58:03 -07:00
dependabot[bot]
ed5b985f63
chore(deps-dev): bump doc8 from 0.10.1 to 0.11.1 (#184)
Bumps [doc8](https://github.com/pycqa/doc8) from 0.10.1 to 0.11.1.
- [Release notes](https://github.com/pycqa/doc8/releases)
- [Commits](https://github.com/pycqa/doc8/compare/0.10.1...0.11.1)

---
updated-dependencies:
- dependency-name: doc8
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-31 20:57:40 -07:00
dependabot[bot]
d4409e5ff9
chore(deps-dev): bump black from 22.1.0 to 22.3.0 (#182)
Bumps [black](https://github.com/psf/black) from 22.1.0 to 22.3.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.1.0...22.3.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-31 20:52:19 -07:00
dependabot[bot]
b1ac69a4dd
chore(deps-dev): bump sphinx from 4.4.0 to 4.5.0 (#180)
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 4.4.0 to 4.5.0.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/4.x/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v4.4.0...v4.5.0)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-31 20:26:53 -07:00
dependabot[bot]
ae7dfcb16b
chore(deps-dev): bump tomlkit from 0.10.0 to 0.10.1 (#181)
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.10.0 to 0.10.1.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.10.0...0.10.1)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-31 20:02:25 -07:00
dependabot[bot]
ff824d1470
chore(deps-dev): bump nitpick from 0.31.0 to 0.32.0 (#179)
Bumps [nitpick](https://github.com/andreoliwa/nitpick) from 0.31.0 to 0.32.0.
- [Release notes](https://github.com/andreoliwa/nitpick/releases)
- [Changelog](https://github.com/andreoliwa/nitpick/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/andreoliwa/nitpick/compare/v0.31.0...v0.32.0)

---
updated-dependencies:
- dependency-name: nitpick
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-31 20:01:38 -07:00
dependabot[bot]
c013a5dca3
chore(deps-dev): bump mypy from 0.931 to 0.942 (#178)
Bumps [mypy](https://github.com/python/mypy) from 0.931 to 0.942.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.931...v0.942)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-25 06:18:22 -07:00
dependabot[bot]
ae509f5500
chore(deps): bump actions/cache from 2.1.7 to 3 (#177)
Bumps [actions/cache](https://github.com/actions/cache) from 2.1.7 to 3.
- [Release notes](https://github.com/actions/cache/releases)
- [Commits](https://github.com/actions/cache/compare/v2.1.7...v3)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-25 06:18:12 -07:00
dependabot[bot]
d95e639895
chore(deps-dev): bump wemake-python-styleguide from 0.16.0 to 0.16.1 (#175)
Bumps [wemake-python-styleguide](https://github.com/wemake-services/wemake-python-styleguide) from 0.16.0 to 0.16.1.
- [Release notes](https://github.com/wemake-services/wemake-python-styleguide/releases)
- [Changelog](https://github.com/wemake-services/wemake-python-styleguide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/wemake-services/wemake-python-styleguide/compare/0.16.0...0.16.1)

---
updated-dependencies:
- dependency-name: wemake-python-styleguide
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-25 06:17:48 -07:00
dependabot[bot]
404d1098e1
chore(deps): bump actions/checkout from 2 to 3 (#173)
Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-01 18:50:18 -08:00
dependabot[bot]
262ad0c6aa
chore(deps): bump actions/setup-python from 2 to 3 (#172)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2 to 3.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-01 18:50:10 -08:00
dependabot[bot]
8021708999
chore(deps): bump django-jsonfield-backport from 1.0.4 to 1.0.5 (#171)
Bumps [django-jsonfield-backport](https://github.com/laymonage/django-jsonfield-backport) from 1.0.4 to 1.0.5.
- [Release notes](https://github.com/laymonage/django-jsonfield-backport/releases)
- [Commits](https://github.com/laymonage/django-jsonfield-backport/compare/v1.0.4...v1.0.5)

---
updated-dependencies:
- dependency-name: django-jsonfield-backport
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-24 18:57:26 -08:00
dependabot[bot]
2cfb00b9a0
chore(deps-dev): bump tomlkit from 0.9.2 to 0.10.0 (#170)
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.9.2 to 0.10.0.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.9.2...0.10.0)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-20 20:40:39 -08:00
dependabot[bot]
ff70b46d0f
chore(deps-dev): bump sphinx-autodoc-typehints from 1.16.0 to 1.17.0 (#169)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.16.0 to 1.17.0.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.16.0...1.17.0)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-20 19:59:31 -08:00
dependabot[bot]
e39cc14363
chore(deps-dev): bump pytest-pythonpath from 0.7.3 to 0.7.4 (#168)
Bumps [pytest-pythonpath](https://github.com/bigsassy/pytest-pythonpath) from 0.7.3 to 0.7.4.
- [Release notes](https://github.com/bigsassy/pytest-pythonpath/releases)
- [Commits](https://github.com/bigsassy/pytest-pythonpath/commits)

---
updated-dependencies:
- dependency-name: pytest-pythonpath
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-13 14:16:40 -08:00
Mike
8541928a4f chore: release 1.2.1 2022-02-08 18:33:09 -08:00
dependabot[bot]
f445ffbc56
chore(deps-dev): bump tomlkit from 0.9.1 to 0.9.2 (#167)
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.9.1 to 0.9.2.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.9.1...0.9.2)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-08 18:24:58 -08:00
dependabot[bot]
642794e816
chore(deps-dev): bump tomlkit from 0.8.0 to 0.9.1 (#166)
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.8.0 to 0.9.1.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.8.0...0.9.1)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-08 18:13:48 -08:00
David
99b9bfc3ef
fixes https://github.com/jazzband/django-eav2/issues/163 (#164)
* fixes https://github.com/jazzband/django-eav2/issues/163

* chore: revert content to master

* fix: don't expand relational fields

* chore: ignore .vscode

* chore: update changelog

* chore: remove stale code

Co-authored-by: Mike <mike@zivix.com>
Co-authored-by: Mike <22396211+Dresdn@users.noreply.github.com>
2022-02-08 18:13:12 -08:00
dependabot[bot]
027c98adfc
chore(deps-dev): bump django from 3.2.11 to 3.2.12 (#161)
Bumps [django](https://github.com/django/django) from 3.2.11 to 3.2.12.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.11...3.2.12)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-02 14:35:29 -08:00
pre-commit-ci[bot]
d1f3f67ceb
[pre-commit.ci] pre-commit autoupdate (#160)
updates:
- [github.com/psf/black: 21.12b0 → 22.1.0](https://github.com/psf/black/compare/21.12b0...22.1.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2022-02-01 13:34:21 -08:00
dependabot[bot]
ba4ec1654d
chore(deps-dev): bump black from 21.12b0 to 22.1.0 (#159)
Bumps [black](https://github.com/psf/black) from 21.12b0 to 22.1.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits/22.1.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-01 13:33:52 -08:00
dependabot[bot]
e45196e596
chore(deps-dev): bump sphinx-autodoc-typehints from 1.15.3 to 1.16.0 (#158)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.15.3 to 1.16.0.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.15.3...1.16.0)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-27 09:18:44 -08:00
dependabot[bot]
779a6c9673
chore(deps-dev): bump sphinx-autodoc-typehints from 1.15.2 to 1.15.3 (#157)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.15.2 to 1.15.3.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.15.2...1.15.3)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-21 16:50:18 -08:00
dependabot[bot]
0830d5503e
chore(deps-dev): bump sphinx from 4.3.2 to 4.4.0 (#156)
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 4.3.2 to 4.4.0.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/4.x/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v4.3.2...v4.4.0)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-17 16:28:18 -08:00
dependabot[bot]
87bdcddd7d
chore(deps-dev): bump nitpick from 0.30.0 to 0.31.0 (#155)
Bumps [nitpick](https://github.com/andreoliwa/nitpick) from 0.30.0 to 0.31.0.
- [Release notes](https://github.com/andreoliwa/nitpick/releases)
- [Changelog](https://github.com/andreoliwa/nitpick/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/andreoliwa/nitpick/compare/v0.30.0...v0.31.0)

---
updated-dependencies:
- dependency-name: nitpick
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-17 15:40:40 -08:00
dependabot[bot]
f38e6326f0
chore(deps-dev): bump nitpick from 0.29.0 to 0.30.0 (#154)
Bumps [nitpick](https://github.com/andreoliwa/nitpick) from 0.29.0 to 0.30.0.
- [Release notes](https://github.com/andreoliwa/nitpick/releases)
- [Changelog](https://github.com/andreoliwa/nitpick/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/andreoliwa/nitpick/compare/v0.29.0...v0.30.0)

---
updated-dependencies:
- dependency-name: nitpick
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-13 20:24:20 -08:00
dependabot[bot]
463e12f801
chore(deps-dev): bump sphinx-autodoc-typehints from 1.14.1 to 1.15.2 (#153)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.14.1 to 1.15.2.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.14.1...1.15.2)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-13 20:20:20 -08:00
dependabot[bot]
4003eefb9c
chore(deps-dev): bump pytest-randomly from 3.10.3 to 3.11.0 (#152)
Bumps [pytest-randomly](https://github.com/pytest-dev/pytest-randomly) from 3.10.3 to 3.11.0.
- [Release notes](https://github.com/pytest-dev/pytest-randomly/releases)
- [Changelog](https://github.com/pytest-dev/pytest-randomly/blob/main/HISTORY.rst)
- [Commits](https://github.com/pytest-dev/pytest-randomly/compare/3.10.3...3.11.0)

---
updated-dependencies:
- dependency-name: pytest-randomly
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-13 20:10:02 -08:00
dependabot[bot]
b92f623c87
chore(deps-dev): bump mypy from 0.930 to 0.931 (#150)
Bumps [mypy](https://github.com/python/mypy) from 0.930 to 0.931.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.930...v0.931)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-09 22:15:24 -08:00
dependabot[bot]
b95503ff58
chore(deps-dev): bump sphinx-autodoc-typehints from 1.14.0 to 1.14.1 (#149)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.14.0 to 1.14.1.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.14.0...1.14.1)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-09 21:58:45 -08:00
dependabot[bot]
c4c338347e
chore(deps-dev): bump sphinx-autodoc-typehints from 1.13.1 to 1.14.0 (#148)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.13.1 to 1.14.0.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.13.1...1.14.0)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-08 07:44:22 -08:00
dependabot[bot]
10a92249e9
chore(deps-dev): bump sphinx-autodoc-typehints from 1.13.0 to 1.13.1 (#147)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.13.0 to 1.13.1.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.13.0...1.13.1)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-06 10:51:54 -08:00
dependabot[bot]
b5c7dbf1f9
chore(deps-dev): bump django from 3.2.10 to 3.2.11 (#146)
Bumps [django](https://github.com/django/django) from 3.2.10 to 3.2.11.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.10...3.2.11)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-06 10:51:35 -08:00
dependabot[bot]
104966d31a
chore(deps-dev): bump sphinx-autodoc-typehints from 1.12.0 to 1.13.0 (#145)
Bumps [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/tox-dev/sphinx-autodoc-typehints/releases)
- [Changelog](https://github.com/tox-dev/sphinx-autodoc-typehints/blob/main/CHANGELOG.md)
- [Commits](https://github.com/tox-dev/sphinx-autodoc-typehints/compare/1.12.0...1.13.0)

---
updated-dependencies:
- dependency-name: sphinx-autodoc-typehints
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-04 13:36:58 -08:00
dependabot[bot]
6c79c6c873
chore(deps-dev): bump flake8-pytest-style from 1.5.1 to 1.6.0 (#143)
Bumps [flake8-pytest-style](https://github.com/m-burst/flake8-pytest-style) from 1.5.1 to 1.6.0.
- [Release notes](https://github.com/m-burst/flake8-pytest-style/releases)
- [Commits](https://github.com/m-burst/flake8-pytest-style/compare/v1.5.1...v1.6.0)

---
updated-dependencies:
- dependency-name: flake8-pytest-style
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-28 08:35:31 -08:00
dependabot[bot]
fa014e25ce
chore(deps-dev): bump mypy from 0.921 to 0.930 (#142)
Bumps [mypy](https://github.com/python/mypy) from 0.921 to 0.930.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.921...v0.930)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-28 08:23:31 -08:00
pre-commit-ci[bot]
cf040d2f2e
[pre-commit.ci] pre-commit autoupdate (#144)
updates:
- [github.com/pre-commit/pre-commit-hooks: v4.0.1 → v4.1.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.0.1...v4.1.0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2021-12-28 08:23:22 -08:00
dependabot[bot]
c99369d970
chore(deps-dev): bump mypy from 0.920 to 0.921 (#141)
Bumps [mypy](https://github.com/python/mypy) from 0.920 to 0.921.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.920...v0.921)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-22 08:15:46 -08:00
dependabot[bot]
f9d7363a03
chore(deps-dev): bump tomlkit from 0.7.2 to 0.8.0 (#140)
Bumps [tomlkit](https://github.com/sdispater/tomlkit) from 0.7.2 to 0.8.0.
- [Release notes](https://github.com/sdispater/tomlkit/releases)
- [Changelog](https://github.com/sdispater/tomlkit/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sdispater/tomlkit/compare/0.7.2...0.8.0)

---
updated-dependencies:
- dependency-name: tomlkit
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-22 08:01:26 -08:00
dependabot[bot]
2c373a6faa
chore(deps-dev): bump sphinx from 4.3.1 to 4.3.2 (#139)
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 4.3.1 to 4.3.2.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/4.x/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v4.3.1...v4.3.2)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-20 07:13:17 -08:00
Mike
bba383bc0a release 1.2.0 2021-12-18 20:25:44 -08:00
Mike
79daf02d66 release 1.2.0 2021-12-18 20:21:31 -08:00
Mike
dac24f4df7
Add Django 4.0 support (#138)
* chore: bump min python version to 3.7

* test: update test matrix versions

* doc: update changelog

* test: use strings for versions

* test: use major.minor for django version
2021-12-18 20:17:20 -08:00
Mike
ed7a808ee8
Allow for integer values larger than 32-bits (#137)
* style: apply ignores to all migrations

* feat: support 64-bit integers

* doc: update changelog

* test: add test for bigger than 32-bit integer
2021-12-18 19:29:38 -08:00
dependabot[bot]
6416477dad
chore(deps-dev): bump mypy from 0.910 to 0.920 (#134)
Bumps [mypy](https://github.com/python/mypy) from 0.910 to 0.920.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.910...v0.920)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-18 17:24:23 -08:00
dependabot[bot]
559d9abcc8
chore(deps-dev): bump wemake-python-styleguide from 0.15.3 to 0.16.0 (#133)
Bumps [wemake-python-styleguide](https://github.com/wemake-services/wemake-python-styleguide) from 0.15.3 to 0.16.0.
- [Release notes](https://github.com/wemake-services/wemake-python-styleguide/releases)
- [Changelog](https://github.com/wemake-services/wemake-python-styleguide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/wemake-services/wemake-python-styleguide/compare/0.15.3...0.16.0)

---
updated-dependencies:
- dependency-name: wemake-python-styleguide
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-14 16:32:33 -08:00
dependabot[bot]
11dc1b5090
chore(deps-dev): bump m2r2 from 0.3.1 to 0.3.2 (#132)
Bumps [m2r2](https://github.com/crossnox/m2r2) from 0.3.1 to 0.3.2.
- [Release notes](https://github.com/crossnox/m2r2/releases)
- [Changelog](https://github.com/CrossNox/m2r2/blob/development/CHANGES.md)
- [Commits](https://github.com/crossnox/m2r2/compare/v0.3.1...v0.3.2)

---
updated-dependencies:
- dependency-name: m2r2
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-14 16:29:52 -08:00
dependabot[bot]
37e6180ddc
chore(deps-dev): bump pytest-django from 4.5.1 to 4.5.2 (#131)
Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.5.1 to 4.5.2.
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/master/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.5.1...v4.5.2)

---
updated-dependencies:
- dependency-name: pytest-django
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-08 06:52:19 -08:00
dependabot[bot]
1f3f4d826c
chore(deps-dev): bump django from 3.2.9 to 3.2.10 (#130)
Bumps [django](https://github.com/django/django) from 3.2.9 to 3.2.10.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.9...3.2.10)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-08 06:52:00 -08:00
pre-commit-ci[bot]
a01485189b
[pre-commit.ci] pre-commit autoupdate (#129)
updates:
- [github.com/psf/black: 21.11b1 → 21.12b0](https://github.com/psf/black/compare/21.11b1...21.12b0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2021-12-07 07:34:53 -08:00
dependabot[bot]
8ea7c505b1
chore(deps-dev): bump black from 21.11b1 to 21.12b0 (#128)
Bumps [black](https://github.com/psf/black) from 21.11b1 to 21.12b0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-06 04:29:31 +00:00
dependabot[bot]
194c2809af
chore(deps-dev): bump pytest-django from 4.4.0 to 4.5.1 (#127)
Bumps [pytest-django](https://github.com/pytest-dev/pytest-django) from 4.4.0 to 4.5.1.
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/master/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.4.0...v4.5.1)

---
updated-dependencies:
- dependency-name: pytest-django
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-06 03:32:26 +00:00
dependabot[bot]
ea72dc164f
chore(deps-dev): bump pytest-randomly from 3.10.2 to 3.10.3 (#125)
Bumps [pytest-randomly](https://github.com/pytest-dev/pytest-randomly) from 3.10.2 to 3.10.3.
- [Release notes](https://github.com/pytest-dev/pytest-randomly/releases)
- [Changelog](https://github.com/pytest-dev/pytest-randomly/blob/main/HISTORY.rst)
- [Commits](https://github.com/pytest-dev/pytest-randomly/compare/3.10.2...3.10.3)

---
updated-dependencies:
- dependency-name: pytest-randomly
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-12-06 02:09:37 +00:00
dependabot[bot]
5f694b87af
chore(deps-dev): bump sphinx from 4.3.0 to 4.3.1 (#124)
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 4.3.0 to 4.3.1.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/4.x/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v4.3.0...v4.3.1)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-30 08:12:21 -08:00
dependabot[bot]
c76a3631b3
chore(deps): bump actions/cache from 2.1.6 to 2.1.7 (#123)
Bumps [actions/cache](https://github.com/actions/cache) from 2.1.6 to 2.1.7.
- [Release notes](https://github.com/actions/cache/releases)
- [Commits](https://github.com/actions/cache/compare/v2.1.6...v2.1.7)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-28 15:20:00 -08:00
pre-commit-ci[bot]
cef3089ecf
[pre-commit.ci] pre-commit autoupdate (#122)
updates:
- [github.com/psf/black: 21.10b0 → 21.11b1](https://github.com/psf/black/compare/21.10b0...21.11b1)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2021-11-22 12:08:06 -08:00
dependabot[bot]
89bf3a9649
chore(deps-dev): bump black from 21.10b0 to 21.11b1 (#121)
Bumps [black](https://github.com/psf/black) from 21.10b0 to 21.11b1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-22 07:57:49 -08:00
dependabot[bot]
e742ec8597
chore(deps-dev): bump doc8 from 0.9.1 to 0.10.1 (#119)
Bumps [doc8](https://github.com/pycqa/doc8) from 0.9.1 to 0.10.1.
- [Release notes](https://github.com/pycqa/doc8/releases)
- [Commits](https://github.com/pycqa/doc8/compare/0.9.1...0.10.1)

---
updated-dependencies:
- dependency-name: doc8
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-10 21:00:31 -08:00
dependabot[bot]
5f329128b1
chore(deps-dev): bump sphinx from 4.2.0 to 4.3.0 (#118)
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 4.2.0 to 4.3.0.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/4.x/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v4.2.0...v4.3.0)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-10 20:52:27 -08:00
dependabot[bot]
341a88f4f4
chore(deps-dev): bump pytest-randomly from 3.10.1 to 3.10.2 (#117)
Bumps [pytest-randomly](https://github.com/pytest-dev/pytest-randomly) from 3.10.1 to 3.10.2.
- [Release notes](https://github.com/pytest-dev/pytest-randomly/releases)
- [Changelog](https://github.com/pytest-dev/pytest-randomly/blob/main/HISTORY.rst)
- [Commits](https://github.com/pytest-dev/pytest-randomly/compare/3.10.1...3.10.2)

---
updated-dependencies:
- dependency-name: pytest-randomly
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-10 20:52:13 -08:00
Mike
9f624b7f00
chore: bump version to 1.1.0 (#116) 2021-11-07 19:06:20 -08:00
dependabot[bot]
814aebac4c
chore(deps-dev): bump flake8-pytest-style from 1.5.0 to 1.5.1 (#115)
Bumps [flake8-pytest-style](https://github.com/m-burst/flake8-pytest-style) from 1.5.0 to 1.5.1.
- [Release notes](https://github.com/m-burst/flake8-pytest-style/releases)
- [Commits](https://github.com/m-burst/flake8-pytest-style/compare/v1.5.0...v1.5.1)

---
updated-dependencies:
- dependency-name: flake8-pytest-style
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-07 18:28:43 -08:00
dependabot[bot]
8ec8826313
chore(deps-dev): bump nitpick from 0.28.0 to 0.29.0 (#114)
Bumps [nitpick](https://github.com/andreoliwa/nitpick) from 0.28.0 to 0.29.0.
- [Release notes](https://github.com/andreoliwa/nitpick/releases)
- [Changelog](https://github.com/andreoliwa/nitpick/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/andreoliwa/nitpick/compare/v0.28.0...v0.29.0)

---
updated-dependencies:
- dependency-name: nitpick
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-07 18:28:25 -08:00
dependabot[bot]
b632788fa7
chore(deps-dev): bump django from 3.2.5 to 3.2.9 (#113)
Bumps [django](https://github.com/django/django) from 3.2.5 to 3.2.9.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.5...3.2.9)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-02 06:59:51 -07:00
pre-commit-ci[bot]
eacdc7c082
[pre-commit.ci] pre-commit autoupdate (#112)
updates:
- [github.com/psf/black: 21.9b0 → 21.10b0](https://github.com/psf/black/compare/21.9b0...21.10b0)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
2021-11-02 06:59:39 -07:00
dependabot[bot]
b22669b517
chore(deps-dev): bump black from 21.9b0 to 21.10b0 (#111)
Bumps [black](https://github.com/psf/black) from 21.9b0 to 21.10b0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-11-01 02:46:12 +00:00
dependabot[bot]
219b28ac1a
chore(deps-dev): bump pytest-randomly from 3.6.0 to 3.10.1 (#110)
Bumps [pytest-randomly](https://github.com/pytest-dev/pytest-randomly) from 3.6.0 to 3.10.1.
- [Release notes](https://github.com/pytest-dev/pytest-randomly/releases)
- [Changelog](https://github.com/pytest-dev/pytest-randomly/blob/main/HISTORY.rst)
- [Commits](https://github.com/pytest-dev/pytest-randomly/compare/3.6.0...3.10.1)

---
updated-dependencies:
- dependency-name: pytest-randomly
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-30 19:18:33 -07:00
dependabot[bot]
ab2ea0d084
chore(deps-dev): bump black from 21.6b0 to 21.9b0 (#109)
Bumps [black](https://github.com/psf/black) from 21.6b0 to 21.9b0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/commits)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-30 19:12:17 -07:00
Mike
d9bb51ff79
chore: misc repository clean up (#108)
* chore: remove tox

* chore: bump min python version to 3.6.2

* chore: remove old test runner

* chore: initial changelog

* chore: clean up pr template

* chore: remove manifest file

Co-authored-by: Mike Stralek <mike.stralek@gmail.com>
2021-10-31 02:02:30 +00:00
dependabot[bot]
19bdee7ad5
chore(deps-dev): bump doc8 from 0.8.1 to 0.9.1 (#105)
Bumps [doc8](https://github.com/pycqa/doc8) from 0.8.1 to 0.9.1.
- [Release notes](https://github.com/pycqa/doc8/releases)
- [Commits](https://github.com/pycqa/doc8/compare/0.8.1...0.9.1)

---
updated-dependencies:
- dependency-name: doc8
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-28 21:59:19 -07:00
dependabot[bot]
b9b511bf87
chore(deps-dev): bump nitpick from 0.26.0 to 0.28.0 (#104)
Bumps [nitpick](https://github.com/andreoliwa/nitpick) from 0.26.0 to 0.28.0.
- [Release notes](https://github.com/andreoliwa/nitpick/releases)
- [Changelog](https://github.com/andreoliwa/nitpick/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/andreoliwa/nitpick/compare/v0.26.0...v0.28.0)

---
updated-dependencies:
- dependency-name: nitpick
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-28 21:49:31 -07:00
dependabot[bot]
421e88ae61
chore(deps-dev): bump mypy from 0.902 to 0.910 (#103)
Bumps [mypy](https://github.com/python/mypy) from 0.902 to 0.910.
- [Release notes](https://github.com/python/mypy/releases)
- [Commits](https://github.com/python/mypy/compare/v0.902...v0.910)

---
updated-dependencies:
- dependency-name: mypy
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-28 21:41:13 -07:00
dependabot[bot]
c9581c69a0
chore(deps-dev): bump m2r2 from 0.2.7 to 0.3.1 (#101)
Bumps [m2r2](https://github.com/crossnox/m2r2) from 0.2.7 to 0.3.1.
- [Release notes](https://github.com/crossnox/m2r2/releases)
- [Changelog](https://github.com/CrossNox/m2r2/blob/development/CHANGES.md)
- [Commits](https://github.com/crossnox/m2r2/compare/v0.2.7...v0.3.1)

---
updated-dependencies:
- dependency-name: m2r2
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-28 21:25:34 -07:00
dependabot[bot]
2a965eeef2
chore(deps-dev): bump sphinx from 4.0.2 to 4.2.0 (#99)
Bumps [sphinx](https://github.com/sphinx-doc/sphinx) from 4.0.2 to 4.2.0.
- [Release notes](https://github.com/sphinx-doc/sphinx/releases)
- [Changelog](https://github.com/sphinx-doc/sphinx/blob/4.x/CHANGES)
- [Commits](https://github.com/sphinx-doc/sphinx/compare/v4.0.2...v4.2.0)

---
updated-dependencies:
- dependency-name: sphinx
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 03:34:36 +00:00
dependabot[bot]
ca6fbca166
chore(deps-dev): bump django from 3.2.4 to 3.2.5 (#107)
Bumps [django](https://github.com/django/django) from 3.2.4 to 3.2.5.
- [Release notes](https://github.com/django/django/releases)
- [Commits](https://github.com/django/django/compare/3.2.4...3.2.5)

---
updated-dependencies:
- dependency-name: django
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 03:04:14 +00:00
dependabot[bot]
5d121ef49d
chore(deps): bump sqlparse from 0.4.1 to 0.4.2 (#106)
Bumps [sqlparse](https://github.com/andialbrecht/sqlparse) from 0.4.1 to 0.4.2.
- [Release notes](https://github.com/andialbrecht/sqlparse/releases)
- [Changelog](https://github.com/andialbrecht/sqlparse/blob/master/CHANGELOG)
- [Commits](https://github.com/andialbrecht/sqlparse/compare/0.4.1...0.4.2)

---
updated-dependencies:
- dependency-name: sqlparse
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 03:03:23 +00:00
dependabot[bot]
00385f8243
chore(deps-dev): bump pytest from 6.2.4 to 6.2.5 (#102)
Bumps [pytest](https://github.com/pytest-dev/pytest) from 6.2.4 to 6.2.5.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/6.2.4...6.2.5)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 03:02:39 +00:00
dependabot[bot]
899c34c240
chore(deps-dev): bump pytest-cov from 2.12.1 to 3.0.0 (#98)
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 2.12.1 to 3.0.0.
- [Release notes](https://github.com/pytest-dev/pytest-cov/releases)
- [Changelog](https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest-cov/compare/v2.12.1...v3.0.0)

---
updated-dependencies:
- dependency-name: pytest-cov
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 03:00:55 +00:00
dependabot[bot]
7c0bc6329e
chore(deps-dev): bump flake8-pytest-style from 1.4.4 to 1.5.0 (#97)
Bumps [flake8-pytest-style](https://github.com/m-burst/flake8-pytest-style) from 1.4.4 to 1.5.0.
- [Release notes](https://github.com/m-burst/flake8-pytest-style/releases)
- [Commits](https://github.com/m-burst/flake8-pytest-style/compare/v1.4.4...v1.5.0)

---
updated-dependencies:
- dependency-name: flake8-pytest-style
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 02:42:50 +00:00
dependabot[bot]
bdd115e3cd
chore(deps-dev): bump wemake-python-styleguide from 0.15.2 to 0.15.3 (#96)
Bumps [wemake-python-styleguide](https://github.com/wemake-services/wemake-python-styleguide) from 0.15.2 to 0.15.3.
- [Release notes](https://github.com/wemake-services/wemake-python-styleguide/releases)
- [Changelog](https://github.com/wemake-services/wemake-python-styleguide/blob/master/CHANGELOG.md)
- [Commits](https://github.com/wemake-services/wemake-python-styleguide/compare/0.15.2...0.15.3)

---
updated-dependencies:
- dependency-name: wemake-python-styleguide
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2021-10-29 02:41:52 +00:00
Mike
bb68d7cec7
fix: correct str() and repr() for EnumGroup and EnumValue (#92)
* test: add tests for Enum represtations

* chore: correct str() and repr() for EnumGroup and EnumValue
2021-10-26 07:04:44 -07:00
PUYUP
9b5df1c99e
fix: handle models with empty local_managers (#90)
* Fix value error

* test: add test for models with empty local_managers

* fix: check for local_managers being empty

Co-authored-by: Mike <22396211+Dresdn@users.noreply.github.com>
2021-10-26 06:10:36 -07:00
Mike
a98766fc55
Add support for Entity models with UUID as a primary key. (#89)
* chore: fix repo links

* style: flake8 format models.Value

* test: add test for an entity with uuid pk

* feat: support entity models with uuid as pk

* test: check Value repr and str methods
2021-10-22 15:36:17 -07:00
Mike
edd050dd98
chore: fix repo links 2021-10-21 12:55:47 -07:00
Jannis Leidel
5ca7791b57
Merge pull request #85 from jazzband/jazzband/sync/default
Jazzband: Synced file(s) with jazzband/.github
2021-10-21 21:31:23 +02:00
Mike
b84e7da265
chore: update badges 2021-10-21 11:37:45 -07:00
Mike
4490cdfed5
Release 1.0.0 (#86)
* chore: update docs for django 2.2 config

* chore: bump version to 1.0.0
2021-10-21 10:57:37 -07:00
Jannis Leidel
068db31001
Update badge. 2021-10-21 16:43:15 +02:00
jazzband-bot
63ff3e517f Jazzband: Created local 'CODE_OF_CONDUCT.md' from remote 'CODE_OF_CONDUCT.md' 2021-10-21 14:35:01 +00:00
Jannis Leidel
a303c841ff
Add release workflow. 2021-10-21 16:02:54 +02:00
Mike
990bdbd1cf
Add pre-commit configuration (#83)
chore: add pre-commit configuration
2021-10-20 12:52:15 -07:00
Mike
013cd58109
Merge pull request #82 from Dresdn/issue-69-codecov
Add codecov.io upload
2021-10-20 15:11:43 +00:00
Mike
53dc297cee chore: add codecov badge 2021-10-20 08:03:18 -07:00
Mike
eeea0e1dbe chore: add upload to codecov step 2021-10-20 08:03:03 -07:00
Mike
f10444ed78
Merge pull request #81 from Dresdn/issue-72
Handle defaults keyword in get_or_create()
2021-10-20 14:39:58 +00:00
Mike
f8773956ed chore: add system version check for type imports 2021-10-20 07:31:08 -07:00
Mike
fe65a9f542 fix: handle defaults keyword with get_or_create() 2021-10-20 07:08:08 -07:00
Mike
6013220684 test: Add new get_or_create() with defaults test 2021-10-20 07:06:09 -07:00
Mike
98c6be3ba5 chore: add new field and basic typing 2021-10-20 07:05:23 -07:00
Mike
21e9accecf
Merge pull request #80 from jazzband/dependabot/github_actions/actions/cache-2.1.6
Bump actions/cache from 1 to 2.1.6
2021-10-20 01:44:39 +00:00
Mike
8e4aabf182
Merge pull request #79 from Dresdn/master
Style code with black and isort
2021-10-20 01:44:25 +00:00
dependabot[bot]
1a85e7f018
Bump actions/cache from 1 to 2.1.6
Bumps [actions/cache](https://github.com/actions/cache) from 1 to 2.1.6.
- [Release notes](https://github.com/actions/cache/releases)
- [Commits](https://github.com/actions/cache/compare/v1...v2.1.6)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-10-16 18:07:27 +00:00
Mike
24a03bf6fc
Merge branch 'jazzband:master' into master 2021-10-16 18:07:24 +00:00
Mike
640e974dcf
Create dependabot.yml 2021-10-16 11:07:08 -07:00
Mike
6a32bd90e8
Create dependabot.yml 2021-10-16 11:05:30 -07:00
Mike
5b9e5f2615 style: explicitly define import path 2021-10-16 10:45:01 -07:00
Mike
065de53ba4 style: run isort 2021-10-16 10:43:20 -07:00
Mike
b1badf8dc5 style: run black formatter 2021-10-16 10:43:02 -07:00
Mike
e35258dc31
Merge pull request #78 from Dresdn/master
Use django_jsonfield_backport for django 2.2 JSONField ; Adds 'test' github action workflow
2021-10-16 00:36:03 +00:00
Mike
575e2480ca Add test github action 2021-10-15 17:25:30 -07:00
Mike
eb21c74a21 Implement django_jsonfield_backport 2021-10-15 17:25:10 -07:00
Mike
670ca66d7c
Merge pull request #77 from Dresdn/master
Fix poetry build
2021-10-15 23:09:58 +00:00
Mike
6220f0f466
Merge pull request #75 from PUYUP/fix-maxlength
fix max_length
2021-10-15 23:09:47 +00:00
Mike
b85439b12c fix: include eav package in final distribution 2021-10-15 13:01:15 -07:00
Mike
de41a8050a fix: use correct name for package 2021-10-15 12:41:06 -07:00
PUYUP
198911582a fix max_length 2021-10-12 12:49:25 +07:00
Tomáš Mládek
3f5aa35dd7
fix link to documentation in README.md
redirect to the main page instead, as there's no mention of "improvement docs" anymore

also replace `<hr><br>` with markdown's native `---`
2021-08-23 14:24:10 +02:00
Mike
ac05b63690
Merge pull request #70 from Dresdn/issue-69-tooling
New tooling and test refactoring
2021-07-19 14:30:25 +00:00
Mike
198cc422bb chore: remove django 3.0 from testing 2021-07-05 07:18:41 -07:00
Mike
9a204bb11d chore: cleanup to match current package version and supported versions 2021-07-05 07:18:11 -07:00
Mike
2d7d54e788 test: disable pytest-randomly (for now) 2021-07-04 09:51:19 -07:00
Mike
53387f81da test: cleanup tox config 2021-07-04 09:17:08 -07:00
Mike
d8c9c162f1 chore: remove old test_app 2021-07-04 08:59:40 -07:00
Mike
1e3c547551 test: use new test_project 2021-07-04 08:59:24 -07:00
Mike
86ccff34e9 test: flatten test project 2021-07-04 08:58:33 -07:00
Mike
f1c4328327 chore: correct exclusion description 2021-06-17 17:13:35 -07:00
Mike
cc57b7b47e fix: repository url 2021-06-17 17:11:37 -07:00
Mike
cae35d1032 chore: clean up tox, remove travis, add recommended files 2021-06-17 16:39:24 -07:00
Mike
9849f8356d chore: remove version from __init__ 2021-06-17 16:39:03 -07:00
Mike
3ebbf8d8e7 tests: refactor tests to use pytest 2021-06-17 16:38:46 -07:00
Mike
597a5374dc tests: add new django_test_app to use for testing 2021-06-17 16:38:06 -07:00
Mike
db1a2d0358 chore: migrate to poetry 2021-06-17 16:36:29 -07:00
~lmn
c9a80834ac
Update CONTRIBUTING.md 2021-06-05 14:59:17 -03:00
~lmn
0b6335b737
Update README.md 2021-06-05 14:56:38 -03:00
~lmn
09918b6224
Fix sphinx deprecated add_stylesheet -> add_css_file 2021-05-11 15:41:11 -03:00
~lmn
6d10892c20
Update 0005 migration - Default to empty str instead of list 2021-05-11 11:01:16 -03:00
Mauro
668caf39e3 Merge branch 'master' of github.com:lvm/django-eav2 2021-05-10 18:06:52 -03:00
Mauro
6a470e2567 Update docs 2021-05-10 18:06:29 -03:00
~lmn
9178644d0f
Merge pull request #68 from lvm/csvfield
CSVField + CSV Datatype
2021-05-10 18:04:10 -03:00
Mauro
3d2c48ae36 Updating docs 2021-05-10 17:17:49 -03:00
Mauro
b2c16c05c4 Adding CSV datatype + CSVField (widget, formfield also) + validators + tests 2021-05-10 17:13:42 -03:00
~lmn
58762a914d
Update Docs 2021-04-27 12:51:26 -03:00
~lmn
493e63645e
Adding secret_key to sphinx conf 2021-04-27 09:35:40 -03:00
~lmn
c638065c9b
Updated requirements. Django >= 3.1 2021-04-24 12:16:11 -03:00
Mauro
6f8f3b7b4b updating contrib 2021-04-23 16:15:19 -03:00
Mauro
fcc0dcb29e Bump readme 2021-04-23 16:13:26 -03:00
Mauro
841ffd623d Bump readme 2021-04-23 16:12:59 -03:00
Mauro
47efd09cb2 Bump ver + update setup 2021-04-23 16:08:07 -03:00
Mauro
4e9f04bdc6 Adding value_bool migration 2021-04-23 16:07:55 -03:00
Mauro
11a23d7c03 leaving out djangotip (4.0) for now, until its release (december 2021) 2021-04-23 12:43:59 -03:00
Mauro
49ee47c399 Updating translations from ugettext_lazy to gettext_lazy and deprecating djangotip from python <3.8 2021-04-23 12:19:06 -03:00
Mauro
000fd963dc Fix url for 'djangotip' 2021-04-23 12:08:05 -03:00
Mauro
75c1b72d5b Updating python and django versions on travis / tox 2021-04-23 11:53:24 -03:00
~lmn
ef3f5d9df6
Merge pull request #66 from lvm/json-datatype
Adds a JSON datatype
2021-04-23 10:42:32 -03:00
~lmn
056ff88926
Merge pull request #65 from lvm/nullboolean-deprecated
Replaces NullBoolean with Boolean (closes: #56)
2021-04-19 19:36:52 -03:00
~lmn
8ecd0e241b
Merge branch 'master' into json-datatype 2021-04-14 10:40:13 -03:00
~lmn
6cce6d8347
Merge pull request #1 from lvm/nullboolean-deprecated
Replaces NullBoolean with Boolean (closes: #56)
2021-04-14 10:36:58 -03:00
Mauro
621ca5791f More docs to the json datatype 2021-04-05 08:35:00 -03:00
Mauro
80323b1c87 Added an example to the docs 2021-04-05 08:20:34 -03:00
Mauro
d8ab935654 Updated docs 2021-04-05 00:04:29 -03:00
Mauro
851ca4cc74 Replaces NullBoolean with Boolean (closes: #56) 2021-04-04 23:57:52 -03:00
Mauro
39e1ff35f7 Adding a JSON Datatype 2021-04-04 23:53:45 -03:00
Daniel Indictor
6cd8163099
Merge pull request #63 from Dresdn/fix/#59_migrations
Move Attribute.entity_ct to own migration file
2021-01-31 22:12:23 -05:00
Mike Stralek
9983786184 create manage.py; move new field to own migration 2021-01-04 17:41:57 -08:00
Daniel Indictor
715dea0626
Merge pull request #59 from wackerservices/feature/model-specific-attributes
New feature: many to many to content type on attribute
2020-11-13 00:41:31 -05:00
Daniel Indictor
71a517d1da
Merge pull request #60 from wackerservices/feature/instance-level-attributes
Add instance parameter to config get_attributes
2020-11-13 00:39:49 -05:00
Daniel Indictor
f60639bec6
Merge pull request #58 from wackerservices/bug/null-enum-fields
Allow enum value to be None on save
2020-10-23 04:55:27 -04:00
Zach Taylor
9a4c8f3ad3 Add instance parameter to config get_attributes 2020-10-22 15:53:34 -05:00
Zach Taylor
5d8ba99361 Change foreign key to many to many to allow more flexibility 2020-10-21 16:03:20 -05:00
Zach Taylor
aaaa813b9b Remove verbose_name and add documentation 2020-10-20 15:02:45 -05:00
Zach Taylor
2c5e1e6602 Add entity_ct to Attribute model 2020-10-20 11:28:14 -05:00
Zach Taylor
def1bc5ade Allow attribute_value to be None if enum type 2020-10-19 14:45:29 -05:00
Daniel Indictor
1f629506a8
Merge pull request #49 from radalin/master
fix generic entity filter problem
2020-07-25 05:07:24 -04:00
Daniel Indictor
a9c54f6ce3
Merge pull request #52 from jayvdb/dj31
Django 3.1 support
2020-07-16 17:52:02 -04:00
John Vandenberg
7a71df16b0 tox.ini: Include Django 2.1 and 2.2 and master 2020-07-15 07:49:39 +07:00
John Vandenberg
e5c3ec600b Update import for Django 3.1 support 2020-07-15 07:49:04 +07:00
Daniel Indictor
3a008f2fb9
Merge pull request #50 from DanielIndictor/master
Made changes necessary to bump supported Django version to 3.0
2020-07-13 15:56:00 -04:00
Daniel Indictor
89358a6c46
Made changes necessary to bump supported Django version to 3.0 2020-04-13 04:18:02 -04:00
roy simkes
bfc48aab6e fix generic entity filter problem 2020-02-06 18:04:18 +03:00
Iwo Herka
1a0c9d0cc0 Bump version to 0.13.0 2019-06-20 16:18:31 +00:00
Alexander Anikeev
e857819fce Add ability to assign enum values as strings (#46)
* Add ability to assign enum values as strings
* Remove unreachable code (enum validation now fails earlier)
* Enable filtering by enum value
2019-06-20 18:14:19 +02:00
Evgeny Pisemsky
27cf385f58 Provide russian translation (#45) 2019-02-25 20:04:17 +01:00
Alexander Anikeev
cf8f95dfa7 Fix ordering with custom config (#44) 2019-02-01 20:38:41 +01:00
Iwo Herka
08104f8c0e Bump version to 0.12.0 2018-09-21 11:49:03 +00:00
Siegmeyer
92ba7992d7
Add support for order_by clause to EavQuerySet (#39) 2018-09-21 13:47:03 +02:00
Siegmeyer
2891175221
Improve README; add introduction to EAV (#36) 2018-08-10 12:57:52 +02:00
Iwo Herka
c033ee64a2 Add form test involving enums 2018-08-10 08:19:37 +00:00
Iwo Herka
fbe5f5ce3d Exclude package "tests" from distribution (#32) 2018-08-03 13:46:08 +00:00
Iwo Herka
8d00f86517 Add contributing guidelines 2018-08-03 13:09:56 +00:00
Iwo Herka
4d8a2044ff Update issue templates 2018-08-03 12:23:52 +00:00
Iwo Herka
d520b6c474 Create PULL_REQUEST_TEMPLATE.md 2018-08-03 12:12:19 +00:00
Iwo Herka
9f1f04de27 Update issue templates 2018-08-03 08:15:15 +00:00
Iwo Herka
bb79ad1ca3 Add John to contributors 2018-08-02 09:18:48 +00:00
John Carter
5ba33e7e6e patch migration, made tox check for missing migrations (#35)
Add tox for missing migrations; fix verbose names in models and migration
2018-08-02 11:16:44 +02:00
Iwo Herka
be0197d5f3 Bump to version 0.11.1 2018-08-01 07:36:22 +00:00
Iwo Herka
c182c515ae Use find_packages in setuptools (#33) 2018-08-01 07:22:12 +00:00
Iwo Herka
d49031c8e6 Bump version to 0.11.0 2018-07-27 14:02:45 +00:00
MajekX
f35ceaed22 Add registration via metaclass (#23)
Example:

    class SomeModel(metaclass=EAVModelMeta):
        pass
2018-07-27 14:01:38 +00:00
Iwo Herka
99254cd578 Move remaining docstrings to Google-stype format (#10) 2018-07-27 13:23:57 +00:00
Iwo Herka
e0a76f86b2 Rename "enums" attribute on the EnumGroup to "values" (#20) 2018-07-27 12:54:05 +00:00
MajekX
9d044ee8e2 Fix tests for Django 2.1+ (tip) (#25) 2018-07-27 13:47:01 +02:00
Iwo Herka
0c8bd2208c
Add Adam to contributors 2018-07-26 09:02:02 +00:00
Iwo Herka
d9dba5703c Rewrite documentation for modern Sphinx (#5) 2018-07-23 16:27:12 +00:00
MajekX
b755c778d6 Fix TravisCI configuration for Tox (#24) 2018-07-23 15:55:03 +02:00
Iwo Herka
a652894a81 Fix Travis' tox config 2018-07-20 12:58:48 +00:00
Iwo Herka
d26bcfdbe7 Fix test compatibility 2018-07-20 12:17:19 +00:00
107 changed files with 9663 additions and 2450 deletions

View file

@ -1,5 +0,0 @@
[run]
omit =
*/migrations/*
eav/__init__.py
eav/utils.py

17
.editorconfig Normal file
View file

@ -0,0 +1,17 @@
# Check https://editorconfig.org for more information
# This is the main config file for this project:
root = true
[*]
charset = utf-8
trim_trailing_whitespace = true
end_of_line = lf
indent_style = space
insert_final_newline = true
indent_size = 2
[*.py]
indent_size = 4
[*.pyi]
indent_size = 4

2
.git-blame-ignore-revs Normal file
View file

@ -0,0 +1,2 @@
# Apply ruff linter rules and standardize code style
c4d7cedeb8b7a8bded8db9a658ae635195071ce3

31
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,31 @@
---
name: Bug report
about: Create a report to help us improve
---
Provide a general summary of the issue in the title above.
## Expected Behavior
Tell us what should happen.
## Actual Behavior
Tell us what happens instead.
## Possible Fix
Not obligatory, but you can suggest a fix or reason for the bug.
## Steps to Reproduce
This is not required, but it would be highly appreciated if you
provided a link to a live example, or an unambiguous set of steps to
reproduce this bug. Include code to reproduce, if relevant.
## Your Environment
Include relevant details about the environment you experienced the bug in.
* Version used:
* Environment name and version (e.g. Django 2.0.4, pip 9.0.1):
* Operating System and version:
* Link to your project (if applicable):

View file

@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
---
Provide a general summary of the issue in the title above.
## Detailed Description
Provide a description of the change or addition you are proposing.
## Context
Why is this change important to you? How would you use it?
How can it benefit other users?
## Possible Implementation
Not obligatory, but you may suggest an idea for implementing addition or change.

15
.github/dependabot.yml vendored Normal file
View file

@ -0,0 +1,15 @@
version: 2
updates:
- package-ecosystem: pip
directory: "/"
schedule:
interval: daily
time: "02:00"
open-pull-requests-limit: 10
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: daily
time: "02:00"
open-pull-requests-limit: 10

54
.github/pull_request_template.md vendored Normal file
View file

@ -0,0 +1,54 @@
# I'm helping!
<!--
Thank you for submitting a Pull Request. We appreciate it!
Please, fill in all the required information
to make our review and merging processes easier.
-->
## Checklist
<!--
Please check everything that applies:
-->
- [ ] I have double checked that there are no unrelated changes in this pull request (old patches, accidental config files, etc.)
- [ ] I have created at least one test case for the changes I have made
- [ ] I have updated the documentation for the changes I have made
- [ ] I have added my changes to the `CHANGELOG.md`
## Pull Request type
<!--
Please try to limit your pull request to one type, submit multiple pull requests if needed.
-->
Please check the type of change your PR introduces:
- [ ] Bugfix
- [ ] Feature
- [ ] Code style update (formatting, renaming)
- [ ] Refactoring (no functional changes, no api changes)
- [ ] Build related changes
- [ ] Documentation content changes
- [ ] Other (please describe):
## Related issue(s)
<!--
Mark what issues this Pull Request closes or references.
Format is:
- Closes #issue-number
- Refs #issue-number
Example. Refs #0
Documentation: https://blog.github.com/2013-05-14-closing-issues-via-pull-requests/
-->
## Other Information
<!--
If you have any other comments, feel free to share!
-->

39
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,39 @@
name: Release
on:
push:
tags:
- '*'
jobs:
build:
if: github.repository == 'jazzband/django-eav2'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.8
- name: Install dependencies
run: |
python -m pip install -U pip
python -m pip install -U poetry twine
- name: Build package
run: |
poetry build
twine check dist/*
- name: Upload packages to Jazzband
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@release/v1
with:
user: jazzband
password: ${{ secrets.JAZZBAND_RELEASE_KEY }}
repository_url: https://jazzband.co/projects/django-eav2/upload

65
.github/workflows/test.yml vendored Normal file
View file

@ -0,0 +1,65 @@
# https://docs.djangoproject.com/en/stable/faq/install/#what-python-version-can-i-use-with-django
name: test
"on":
push:
branches:
- '**'
pull_request:
workflow_dispatch:
jobs:
test-matrix:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
django-version: ['4.2', '5.1', '5.2']
exclude:
# Exclude Python 3.9 with Django 5.1 and 5.2
- python-version: '3.9'
django-version: '5.1'
- python-version: '3.9'
django-version: '5.2'
# Exclude Python 3.13 with Django 4.2
- python-version: '3.13'
django-version: '4.2'
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
uses: snok/install-poetry@v1
with:
version: 1.8.4
virtualenvs-create: true
virtualenvs-in-project: true
installer-parallel: true
- name: Set up cache
uses: actions/cache@v4
with:
path: .venv
key: venv-${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }}
- name: Install dependencies
run: |
poetry install
poetry run pip install --upgrade pip
poetry run pip install --upgrade "django==${{ matrix.django-version }}.*"
- name: Run tests
run: |
poetry run pytest
poetry check
poetry run pip check
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
file: ./coverage.xml

8
.gitignore vendored
View file

@ -123,3 +123,11 @@ venv.bak/
*~
# Auto-generated tag files
tags
## Mac
.DS_Store
## IDE
.idea
.vscode

27
.pre-commit-config.yaml Normal file
View file

@ -0,0 +1,27 @@
# See https://pre-commit.com for more information
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-added-large-files
- id: mixed-line-ending
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.11.12
hooks:
# Run the linter.
- id: ruff
args: [ --fix ]
# Run the formatter.
- id: ruff-format
- repo: https://github.com/remastr/pre-commit-django-check-migrations
rev: v0.1.0
hooks:
- id: check-migrations-created
args: [--manage-path=manage.py]
additional_dependencies: [django==4.1]

24
.readthedocs.yml Normal file
View file

@ -0,0 +1,24 @@
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
version: 2
# Set the version of Python and other tools you might need
build:
os: ubuntu-20.04
tools:
python: '3.9'
jobs:
# See https://github.com/readthedocs/readthedocs.org/issues/4912
pre_create_environment:
- asdf plugin add poetry
- asdf install poetry latest
- asdf global poetry latest
- poetry config virtualenvs.create false
post_install:
- . "$(pwd | rev | sed 's/stuokcehc/svne/' | rev)/bin/activate" && poetry install --only main --only docs
# Build documentation in the docs/ directory with Sphinx
sphinx:
configuration: docs/source/conf.py
fail_on_warning: true

View file

@ -1,22 +0,0 @@
language: python
matrix:
include:
- python: 2.7
env: TOXENV=py27
- python: 3.5
env: TOXENV=py35
- python: 3.6
env: TOXENV=py36
- python: 3.7-dev
env: TOXENV=py37
install:
- pip install -r requirements.txt
- pip install tox==3.0.0
- pip install coveralls==1.3.0
- pip install coverage==4.5.1
before_script:
- coverage erase
script:
- coverage run --source=eav runtests; tox
after_success:
- COVERALLS_REPO_TOKEN=71NkMDQFpFKB9QYXoK12LYuWUEmQ2wD6V coveralls

171
CHANGELOG.md Normal file
View file

@ -0,0 +1,171 @@
# Version History
We follow [Semantic Versions](https://semver.org/) starting at the `0.14.0` release.
## 1.8.1 (2025-06-02)
## What's Changed
- Added support for Django 5.2
- Updated dependencies to their latest versions
## 1.8.0 (2025-02-24)
## What's Changed
- Add database constraints to Value model for data integrity by @Dresdn in https://github.com/jazzband/django-eav2/pull/706
- Fix for issue #648: Ensure choices are valid (value, label) tuples by @altimore in https://github.com/jazzband/django-eav2/pull/707
## 1.7.1 (2024-09-01)
## What's Changed
* Restore backward compatibility for Attribute creation with invalid slugs by @Dresdn in https://github.com/jazzband/django-eav2/pull/639
## 1.7.0 (2024-09-01)
### What's Changed
- Enhance slug validation for Python identifier compliance
- Migrate to ruff
- Drop support for Django 3.2
- Add support for Django 5.1
## 1.6.1 (2024-06-23)
### What's Changed
- Ensure eav.register() Maintains Manager Order by @Dresdn in https://github.com/jazzband/django-eav2/pull/595
- Update downstream dependencies by @Dresdn in https://github.com/jazzband/django-eav2/pull/597
## 1.6.0 (2024-03-14)
### What's Changed
- Corrects `BaseEntityAdmin` integration into Django Admin site
- Split model modules by @iacobfred in https://github.com/jazzband/django-eav2/pull/467
- Add Django 5.0 and Python 3.12 to the testing by @cclauss in https://github.com/jazzband/django-eav2/pull/487
- Fix typos with codespell by @cclauss in https://github.com/jazzband/django-eav2/pull/489
- Enhance BaseEntityAdmin by @Dresdn in https://github.com/jazzband/django-eav2/pull/541
- Remove support for Django < 3.2 and Python < 3.8 by @Dresdn in https://github.com/jazzband/django-eav2/pull/542
## 1.5.0 (2023-11-08)
### Bug Fixes
- Fixes querying with multiple eav kwargs [#395](https://github.com/jazzband/django-eav2/issues/395)
### Features
- Support for many type of primary key (UUIDField, BigAutoField)
- Support for natural key use for some models for serialization (EnumValue, EnumGroup, Attribute, Value)
- Add support for Django 4.2
- Add support for Python 3.11
## 1.4.0 (2023-07-07)
### Features
- Support Bahasa Indonesia Translations
- Support Django 4.2
## 1.3.1 (2023-02-22)
### Bug Fixes
- Generate missing migrations [#331](https://github.com/jazzband/django-eav2/issues/331)
## 1.3.0 (2023-02-10)
### Features
- Add support for Django 4.1
### Bug Fixes
- Fixes missing `Add another` button for inlines in `BaseEntityAdmin`
- Fixes saving of Attribute date types rendering using `BaseDynamicEntityForm` [#261](https://github.com/jazzband/django-eav2/issues/261)
### Misc
- Drops support for Django 2.2 and Python 3.7
## 1.2.3 (2022-08-15)
### Bug Fixes
- Don't mark doc8 as a dependency [#235](https://github.com/jazzband/django-eav2/issues/235)
- Make Read the Docs dependencies all optional
## 1.2.2 (2022-08-13)
### Bug Fixes
- Fixes AttributeError when using CSVFormField [#187](https://github.com/jazzband/django-eav2/issues/187)
- Fixes slug generation for Attribute.name fields longer than 50 characters [#223](https://github.com/jazzband/django-eav2/issues/223)
- Migrates Attribute.slug to django.db.models.SlugField() [#223](https://github.com/jazzband/django-eav2/issues/223)
## 1.2.1 (2022-02-08)
### Bug Fixes
- Fixes FieldError when filtering on foreign keys [#163](https://github.com/jazzband/django-eav2/issues/163)
## 1.2.0 (2021-12-18)
### Features
- Adds 64-bit support for `Value.value_int`
- Adds Django 4.0 and Python 3.10 support
### Misc
- Drops support for Django 3.1 and Python 3.6
## 1.1.0 (2021-11-07)
### Features
- Adds support for entity models with UUId as a primary key #38
### Bug Fixes
- Fixes `ValueError` for models without local managers #41
- Fixes `str()` and `repr()` for `EnumGroup` and `EnumValue` objects #91
### Misc
- Bumps min python version to `3.6.2`
**Full Changelog**: <https://github.com/jazzband/django-eav2/compare/1.0.0...1.1.0>
## 1.0.0 (2021-10-21)
### Breaking Changes
- Drops support for `django1.x`
- Drops support for `django3.0`
- Moves `JSONField()` datatype to `django-jsonfield-backport` for Django2.2 instances
### Features
- Adds support for `django3.2`
- Adds support for `python3.9`
- Adds support for `defaults` keyword on `get_or_create()`
### #Misc
- Revamps all tooling, including moving to `poetry`, `pytest`, and `black`
- Adds Github Actions and Dependabot
**Full Changelog**: <https://github.com/jazzband/django-eav2/compare/0.14.0...1.0.0>
## 0.14.0 (2021-04-23)
### Misc
- This release will be the last to support this range of Django versions: 1.11, 2.0, 2.1, 2.2, 3.0. SInce all of their extended support was ended by Django Project.
- From the next release only will be supported 2.2 LTS, 3.1, and 3.2 LTS (eventually 4.x)
**Full Changelog**: <https://github.com/jazzband/django-eav2/compare/0.13.0...0.14.0>
(Anything before 0.14.0 was not recorded.)

46
CODE_OF_CONDUCT.md Normal file
View file

@ -0,0 +1,46 @@
# Code of Conduct
As contributors and maintainers of the Jazzband projects, and in the interest of
fostering an open and welcoming community, we pledge to respect all people who
contribute through reporting issues, posting feature requests, updating documentation,
submitting pull requests or patches, and other activities.
We are committed to making participation in the Jazzband a harassment-free experience
for everyone, regardless of the level of experience, gender, gender identity and
expression, sexual orientation, disability, personal appearance, body size, race,
ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery
- Personal attacks
- Trolling or insulting/derogatory comments
- Public or private harassment
- Publishing other's private information, such as physical or electronic addresses,
without explicit permission
- Other unethical or unprofessional conduct
The Jazzband roadies have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are not
aligned to this Code of Conduct, or to ban temporarily or permanently any contributor
for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
By adopting this Code of Conduct, the roadies commit themselves to fairly and
consistently applying these principles to every aspect of managing the jazzband
projects. Roadies who do not follow or enforce the Code of Conduct may be permanently
removed from the Jazzband roadies.
This code of conduct applies both within project spaces and in public spaces when an
individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by
contacting the roadies at `roadies@jazzband.co`. All complaints will be reviewed and
investigated and will result in a response that is deemed necessary and appropriate to
the circumstances. Roadies are obligated to maintain confidentiality with regard to the
reporter of an incident.
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version
1.3.0, available at [https://contributor-covenant.org/version/1/3/0/][version]
[homepage]: https://contributor-covenant.org
[version]: https://contributor-covenant.org/version/1/3/0/

65
CONTRIBUTING.md Normal file
View file

@ -0,0 +1,65 @@
[![Jazzband](https://jazzband.co/static/img/jazzband.svg)](https://jazzband.co/)
This is a [Jazzband](https://jazzband.co/) project. By contributing you agree to abide by the [Contributor Code of Conduct](https://jazzband.co/about/conduct) and follow the [guidelines](https://jazzband.co/about/guidelines).
# Contributing
We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's:
- Reporting a bug
- Discussing the current state of the code
- Submitting a fix
- Proposing new features
- Becoming a maintainer
## Dependencies
We use [poetry](https://github.com/sdispater/poetry) to manage the dependencies.
To install them you would need to run `install` command:
```bash
poetry install
```
To activate your `virtualenv` run `poetry shell`.
## Tests
We use `pytest` and `flake8` for quality control.
To run all tests:
```bash
pytest
```
## We develop with Github
We use github to host code, to track issues and feature requests, as well as accept pull requests.
### We use [Github Flow](https://guides.github.com/introduction/flow/index.html), so all code changes from community happen through pull requests
Pull requests are the best way to propose changes to the codebase (we use [Github Flow](https://guides.github.com/introduction/flow/index.html)). We actively welcome your pull requests:
1. Fork the repo and create your branch from `master`.
2. If you've added code that should be tested, add tests.
3. If you've changed APIs, update the documentation.
4. Ensure the test suite passes.
5. Make sure your code lints.
6. Describe the pull request using [this](https://github.com/jazzband/django-eav2/blob/master/PULL_REQUEST_TEMPLATE.md) template.
### Any contributions you make will be under the GNU Lesser General Public License v3.0
In short, when you submit code changes, your submissions are understood to be under the same [LGPLv3](https://choosealicense.com/licenses/lgpl-3.0/) that covers the project. Feel free to contact the maintainers if that's a concern.
### Report bugs using Github's [issues](https://github.com/jazzband/django-eav2/issues)
We use GitHub issues to track public bugs. Report a bug by opening a new issue. Use [this](https://github.com/jazzband/django-eav2/blob/master/.github/ISSUE_TEMPLATE/bug_report.md) template to describe your reports.
### Use a consistent coding style
We use [Black](https://github.com/psf/black) and (working towards) [wemake-python-styleguide](https://github.com/wemake-services/wemake-python-styleguide) for code and [Google-style](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) reStructuredText for doc-strings.
<hr>
<br>
<br>
This document was adapted from the open-source contribution guidelines for [Facebook's Draft](https://github.com/facebook/draft-js/blob/a9316a723f9e918afde44dea68b5f9f39b7d9b00/CONTRIBUTING.md).

View file

@ -1,15 +1,19 @@
Contributors, alphabetically:
* amarder (Andrew Marder)
* daveycrockett (David McCann)
* dgelvin (David Gelvin)
* dorey
* fosil (Filip Novák)
* gingerjoos
* IwoHerka (Iwo Herka)
* jpwhite3
* katembu (Moses Katembu)
* madEng84
* nicpottier (Nic Pottier)
* tavaresb (Bruno Tavares)
* timlinux (Tim Sutton)
* amarder (Andrew Marder)
* daveycrockett (David McCann)
* dgelvin (David Gelvin)
* dorey
* fosil (Filip Novák)
* gingerjoos
* IwoHerka (Iwo Herka)
* jpwhite3
* katembu (Moses Katembu)
* lvm (Mauro Lizaur)
* madEng84
* MajekX (Adam Majczyk)
* nicpottier (Nic Pottier)
* pisemsky (Evgeny Pisemsky)
* tavaresb (Bruno Tavares)
* therefromhere (John Carter)
* timlinux (Tim Sutton)

View file

@ -1,6 +1,6 @@
This software is derived from Django EAV (https://github.com/mvpdev/django-eav)
which, in turn, was derived from EAV Django, originally written and copyrighted
by Andrey Mikhaylenko <http://pypi.python.org/pypi/eav-django>.
by Andrey Mikhaylenko <https://pypi.org/project/eav-django/>.
This is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published

176
README.md
View file

@ -1,33 +1,158 @@
[![Build Status](https://travis-ci.org/makimo/django-eav2.svg?branch=master)](https://travis-ci.org/makimo/django-eav2)
[![Coverage Status](https://coveralls.io/repos/github/makimo/django-eav2/badge.svg?branch=master)](https://coveralls.io/github/makimo/django-eav2?branch=master)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/159540d899bd41bb860f0ce996427e1f)](https://www.codacy.com/app/IwoHerka/django-eav2?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=makimo/django-eav2&amp;utm_campaign=Badge_Grade)
[![Maintainability](https://api.codeclimate.com/v1/badges/b90eacf7a90db4b58f13/maintainability)](https://codeclimate.com/github/makimo/django-eav2/maintainability)
![Python Version](https://img.shields.io/badge/Python-2.7,%203.5,%203.6,%203.7dev-blue.svg)
![Django Version](https://img.shields.io/badge/Django-1.11,%202.0,%20tip-green.svg)
[![Build Status](https://github.com/jazzband/django-eav2/actions/workflows/test.yml/badge.svg)](https://github.com/jazzband/django-eav2/actions/workflows/test.yml)
[![codecov](https://codecov.io/gh/jazzband/django-eav2/branch/master/graph/badge.svg?token=BJk3zS22BS)](https://codecov.io/gh/jazzband/django-eav2)
[![Python Version](https://img.shields.io/pypi/pyversions/django-eav2.svg)](https://pypi.org/project/django-eav2/)
[![Django Version](https://img.shields.io/pypi/djversions/django-eav2.svg?color=green)](https://pypi.org/project/django-eav2/)
[![Jazzband](https://jazzband.co/static/img/badge.svg)](https://jazzband.co/)
## Django EAV 2 - Entity-Attribute-Value storage for Django
Django EAV 2 is a fork of django-eav (which itself was derived from eav-django).
You can find documentation <a href="https://django-eav-2.readthedocs.io/en/improvement-docs/">here</a>.
Django EAV 2 is a fork of django-eav (which itself was derived from eav-django).
You can find documentation <a href="https://django-eav2.rtfd.io">here</a>.
## What is EAV anyway?
> Entityattributevalue model (EAV) is a data model to encode, in a space-efficient manner, entities where the number of attributes (properties, parameters) that can be used to describe them is potentially vast, but the number that will actually apply to a given entity is relatively modest. Such entities correspond to the mathematical notion of a sparse matrix. (Wikipedia)
Data in EAV is stored as a 3-tuple (typically corresponding to three distinct tables):
- The entity: the item being described, e.g. `Person(name='Mike')`.
- The attribute: often a foreign key into a table of attributes, e.g. `Attribute(slug='height', datatype=FLOAT)`.
- The value of the attribute, with links both an attribute and an entity, e.g. `Value(value_float=15.5, person=mike, attr=height)`.
Entities in **django-eav2** are your typical Django model instances. Attributes (name and type) are stored in their own table, which makes it easy to manipulate the list of available attributes in the system. Values are an intermediate table between attributes and entities, each instance holding a single value.
This implementation also makes it easy to edit attributes in Django Admin and form instances.
You will find detailed description of the EAV here:
- [Wikipedia - Entityattributevalue model](https://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model)
## EAV - The Good, the Bad or the Ugly?
EAV is a trade-off between flexibility and complexity. As such, it should not be thought of as either an amelioration pattern, nor an anti-pattern. It is more of a [gray pattern](https://wiki.c2.com/?GreyPattern) - it exists in some context, to solve certain set of problems. When used appropriately, it can introduce great flexibility, cut prototyping time or deacrease complexity. When used carelessly, however, it can complicate database schema, degrade the performance and make maintenance hard. **As with every tool, it should not be overused.** In the following paragraphs we briefly discuss the pros, the cons and pointers to keep in mind when using EAV.
### When to use EAV?
Originally, EAV was introduced to workaround a problem which cannot be easily solved within relational model. In order to achieve this, EAV bypasses normal schema restrictions. Some refer to this as an example of the [inner-platform effect](https://en.wikipedia.org/wiki/Inner-platform_effect#Examples). Naturally, in such scenarios RDMS resources cannot be used efficiently.
Typical application of the EAV model sets to solve the problem of sparse data with a large number of applicable attributes, but only a small fraction that applies to a given entity that may not be known beforehand. Consider the classic example:
> A problem that data modelers commonly encounter in the biomedical domain is organizing and storing highly diverse and heterogeneous data. For example, a single patient may have thousands of applicable descriptive parameters, all of which need to be easily accessible in an electronic patient record system. These requirements pose significant modeling and implementation challenges. [1]
And:
> [...] what do you do when you have customers that demand real-time, on-demand addition of attributes that they want to store? In one of the systems I manage, our customers wanted to do exactly this. Since we run a SaaS (software as a service) application, we have many customers across several different industries, who in turn want to use our system to store different types of information about _their_ customers. A salon chain might want to record facts such as 'hair color,' 'hair type,' and 'haircut frequency'; while an investment company might want to record facts such as 'portfolio name,' 'last portfolio adjustment date,' and 'current portfolio balance.' [2]
In both of these problems we have to deal with sparse and heterogeneous properties that apply only to potentially different subsets of particular entities. Applying EAV to a sub-schema of the database allows to model the desired behaviour. Traditional solution would involves wide tables with many columns storing NULL values for attributes that don't apply to an entity.
Very common use case for EAV are custom product attributes in E-commerce implementations, such as Magento. [3]
As a rule of thumb, EAV can be used when:
- Model attributes are to be added and removed by end users (or are unknowable in some different way). EAV supports these without ALTER TABLE statements and allows the attributes to be strongly typed and easily searchable.
- There will be many attributes and values are sparse, in contrast to having tables with mostly-null columns.
- The data is highly dynamic/volatile/vulnerable to change. This problem is present in the second example given above. Other example would be rapidly evolving system, such as a prototype with constantly changing requirements.
- We want to store meta-data or supporting information, e.g. to customize system's behavior.
- Numerous classes of data need to be represented, each class has a limited number of attributes, but the number of instances of each class is very small.
- We want to minimise programmer's input when changing the data model.
For more throughout discussion on the appropriate use-cases see:
1. [Wikipedia - Scenarios that are appropriate for EAV modeling](https://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model#Scenarios_that_are_appropriate_for_EAV_modeling)
2. [StackOverflow - Entity Attribute Value Database vs. strict Relational Model E-commerce](https://stackoverflow.com/questions/870808/entity-attribute-value-database-vs-strict-relational-model-ecommerce)
3. [WikiWikiWeb - Generic Data Model](https://wiki.c2.com/?GenericDataModel)
## When to avoid it?
As we outlined in the opening section, EAV is a trade-off. It should not be used when:
##### 1. System is performance critical
> Attribute-centric query is inherently more difficult when data are stored in EAV form than when they are stored conventionally. [4]
In general, the more structured your data model, the more efficiently you can deal with it. Therefore, loose data storage such as EAV has obvious trade-off in performance. Specifically, application of the EAV model makes performing JOINs on tables more complicated.
##### 2. Low complexity/low maintenance cost is of priority
EAV complicates data model by splitting information across tables. This increases conceptual complexity as well as SQL statements required to query the data. In consequence, optimization in one area that also makes the system harder to understand and maintain.
However, it is important to note that:
> An EAV design should be employed only for that sub-schema of a database where sparse attributes need to be modeled: even here, they need to be supported by third normal form metadata tables. There are relatively few database-design problems where sparse attributes are encountered: this is why the circumstances where EAV design is applicable are relatively rare. [1]
## Alternatives
In some use-cases, JSONB (binary JSON data) datatype (Postgres 9.4+ and analogous in other RDMSs) can be used as an alternative to EAV. JSONB supports indexing, which amortizes performance trade-off. It's important to keep in mind that JSONB is not RDMS-agnostic solution and has it's own problems, such as typing.
## Installation
You can install **django-eav2** from three sources:
Install with pip
```bash
# From PyPI via pip
pip install django-eav2
```
# From source via pip
pip install git+https://github.com/makimo/django-eav2@master
## Configuration
# From source via setuptools
git clone git@github.com:makimo/django-eav2.git
cd django-eav2
python setup.py install
Add `eav` to `INSTALLED_APPS` in your settings.
# To uninstall:
python setup.py install --record files.txt
rm $(cat files.txt)
```python
INSTALLED_APPS = [
...
'eav',
]
```
Add `django.db.models.UUIDField` or `django.db.models.BigAutoField` as value of `EAV2_PRIMARY_KEY_FIELD` in your settings
``` python
EAV2_PRIMARY_KEY_FIELD = "django.db.models.UUIDField" # as example
```
### Note: Primary key mandatory modification field
If the primary key of eav models are to be modified (UUIDField -> BigAutoField, BigAutoField -> UUIDField) in the middle of the project when the migrations are already done, you have to change the value of `EAV2_PRIMARY_KEY_FIELD` in your settings.
##### Step 1
Change the value of `EAV2_PRIMARY_KEY_FIELD` into `django.db.models.CharField` in your settings.
```python
EAV2_PRIMARY_KEY_FIELD = "django.db.models.CharField"
```
Run the migrations
```bash
python manage.py makemigrations
python manage.py migrate
```
##### Step 2
Change the value of `EAV2_PRIMARY_KEY_FIELD` into the desired value (`django.db.models.BigAutoField` or `django.db.models.UUIDField`) in your settings.
```python
EAV2_PRIMARY_KEY_FIELD = "django.db.models.BigAutoField" # as example
```
Run again the migrations.
```bash
python manage.py makemigrations
python manage.py migrate
```
### Note: Django 2.2 Users
Since `models.JSONField()` isn't supported in Django 2.2, we use [django-jsonfield-backport](https://github.com/laymonage/django-jsonfield-backport) to provide [JSONField](https://docs.djangoproject.com/en/dev/releases/3.1/#jsonfield-for-all-supported-database-backends) functionality.
This requires adding `django_jsonfield_backport` to your `INSTALLED_APPS` as well.
```python
INSTALLED_APPS = [
...
'eav',
'django_jsonfield_backport',
]
```
## Getting started
@ -65,4 +190,13 @@ Supplier.objects.filter(eav__city='London')
# = <EavQuerySet [<Supplier: Supplier object (1)>]>
```
### What next? Check out <a href="https://django-eav-2.readthedocs.io/en/improvement-docs/">documentation</a>.
**What next? Check out the <a href="https://django-eav2.readthedocs.io/en/latest/#documentation">documentation</a>.**
---
### References
[1] Exploring Performance Issues for a Clinical Database Organized Using an Entity-Attribute-Value Representation, https://doi.org/10.1136/jamia.2000.0070475 <br>
[2] What is so bad about EAV, anyway?, https://sqlblog.org/2009/11/19/what-is-so-bad-about-eav-anyway <br>
[3] Magento for Developers: Part 7—Advanced ORM: Entity Attribute Value, https://devdocs.magento.com/guides/m1x/magefordev/mage-for-dev-7.html <br>
[4] Data Extraction and Ad Hoc Query of an Entity— Attribute— Value Database, https://www.ncbi.nlm.nih.gov/pmc/articles/PMC61332/

View file

@ -1,89 +1,20 @@
# Makefile for Sphinx documentation
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
SPHINXPROJ = DjangoEAV2
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
clean:
-rm -rf $(BUILDDIR)/*
.PHONY: help Makefile
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/django-eav.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/django-eav.qhc"
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
"run these through (pdf)latex."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

View file

@ -1,199 +0,0 @@
# -*- coding: utf-8 -*-
#
# django-eav documentation build configuration file, created by
# sphinx-quickstart on Fri Sep 24 10:48:33 2010.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.append(os.path.abspath(os.path.join('..','..')))
# django setup
import settings
from django.core.management import setup_environ
setup_environ(settings)
# -- General configuration -----------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo','sphinxtogithub']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'django-eav'
copyright = u'2010, MVP Africa'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0.9'
# The full version, including alpha/beta/rc tags.
release = '0.9.1'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of documents that shouldn't be included in the build.
#unused_docs = []
# List of directories, relative to source directory, that shouldn't be searched
# for source files.
exclude_trees = ['_build']
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
html_theme = 'default'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_use_modindex = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = ''
# Output file base name for HTML help builder.
htmlhelp_basename = 'django-eavdoc'
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
#latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
#latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'django-eav.tex', u'django-eav Documentation',
u'MVP Africa', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# Additional stuff for the LaTeX preamble.
#latex_preamble = ''
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_use_modindex = True

View file

@ -1,24 +0,0 @@
Docstrings
==========
.. automodule:: eav
:members:
.. automodule:: eav.models
:members:
.. automodule:: eav.validators
:members:
.. automodule:: eav.fields
:members:
.. automodule:: eav.forms
:members:
.. automodule:: eav.managers
:members:
.. automodule:: eav.registry
:members:

View file

@ -1,240 +0,0 @@
.. django-eav documentation master file, created by
sphinx-quickstart on Fri Sep 24 10:48:33 2010.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
##########
django-eav
##########
Introduction
============
django-eav provides an Entity-Attribute-Value storage model for django apps.
For a decent explanation of what an Entity-Attribute-Value storage model is,
check `Wikipedia
<http://en.wikipedia.org/wiki/Entity-attribute-value_model>`_.
.. note::
This software was inspired / derived from the excellent `eav-django
<http://pypi.python.org/pypi/eav-django/1.0.2>`_ written by Andrey
Mikhaylenko.
There are a few notable differences between this implementation and the
eav-django implementation.
* This one is called django-eav, whereas the other is called eav-django.
* This app allows you to to 'attach' EAV attributes to any existing django
model (even from third-party apps) without making any changes to the those
models' code.
* This app has slightly more robust (but still not perfect) filtering.
Installation
============
You can install django-eav directly from guthub::
pip install -e git+git://github.com/mvpdev/django-eav.git#egg=django-eav
After installing, add ``eav`` to your ``INSTALLED_APPS`` in your
project's ``settings.py`` file.
Usage
=====
In order to attach EAV attributes to a model, you first need to register it
(just like you may register your models with django.contrib.admin).
Registration
------------
Registering a model with eav does a few things:
* Adds the eav :class:`eav.managers.EntityManager` to your class. By default,
it will replace the default ``objects`` manager of the model, but you can
choose to have the eav manager named something else if you don't want it to
replace ``objects`` (see :ref:`advancedregistration`).
* Connects the model's ``post_init`` signal to
:meth:`~eav.registry.Registry.attach_eav_attr`. This function will attach
the eav :class:`eav.models.Entity` helper class to every instance of your
model when it is instatiated. By default, it will be attached to your models
as an attribute named ``eav``, which will allow you to access it through
``my_model_instance.eav``, but you can choose to name it something else if you
want (again see :ref:`advancedregistration`).
* Connect's the model's ``pre_save`` signal to
:meth:`eav.models.Entity.pre_save_handler`.
* Connect's the model's ``post_save`` signal to
:meth:`eav.models.Entity.post_save_handler`.
* Adds a generic relation helper to the class.
* Sets an attribute called ``_eav_config_cls`` on the model class to either
the default :class:`eav.registry.EavConfig` config class, or to the config
class you provided during registration.
If that all sounds too complicated, don't worry, you really don't need to think
about it. Just thought you should know.
Simple Registration
^^^^^^^^^^^^^^^^^^^
To register any model with EAV, you simply need to add the registration line
somewhere that will be executed when django starts::
import eav
eav.register(MyModel)
Generally, the most appropriate place for this would be in your ``models.py``
immediately after your model definition.
.. _advancedregistration:
Advanced Registration
^^^^^^^^^^^^^^^^^^^^^
Advanced registration is only required if:
* You don't want eav to replace your model's default ``objects`` manager.
* You want to name the :class:`~eav.models.Entity` helper attribute something
other than ``eav``
* You don't want all eav :class:`~eav.models.Attribute` objects to
be able to be set for all of your registered models. In other words, you
have different types of entities, each with different attributes.
Advanced registration is simple, and is performed the exact same way
you override the django.contrib.admin registration defaults.
You just need to define your own config class that subclasses
:class:`~eav.registry.EavConfig` and override the default class attributes
and method.
There are five :class:`~eav.registry.EavConfig` class attributes you can
override:
================================= ================================== ==========================================================================
Class Attribute Default Description
================================= ================================== ==========================================================================
``manager_attr`` ``'objects'`` The name of the eav manager
``manager_only`` ``False`` *boolean* Whether to *only* replace the manager, and do nothing else
``eav_attr`` ``'eav'`` The attribute name of the entity helper
``generic_relation_attr`` ``'eav_values'`` The attribute name of the generic relation helper
``generic_relation_related_name`` The model's ``__class__.__name__`` The related name of the related name of the generic relation to your model
================================= ================================== ==========================================================================
An example of just choosing a different name for the manager (and thus leaving
``objects`` intact)::
class MyEavConfigClass(EavConfig):
manager_attr = 'eav_objects'
eav.register(MyModel, MyEavConfigClass)
Additionally, :class:`~eav.registry.EavConfig` defines a classmethod called
``get_attributes`` that, by default will return ``Attribute.objects.all()``
This method is used to determine which :class:`~eav.models.Attribute` can be
applied to the entity model you are registering. If you want to limit which
attributes can be applied to your entity, you would need to override it.
For example::
class MyEavConfigClass(EavConfig):
@classmethod
def get_attributes(cls):
return Attribute.objects.filter(type='person')
eav.register(MyModel, MyEavConfigClass)
Using Attributes
================
Once you've registered your model(s), you can begin to use them with EAV
attributes. Let's assume your model is called ``Person`` and it has one
normal django ``CharField`` called name, but you want to be able to dynamically
store other data about each Person.
First, let's create some attributes::
>>> Attribute.objects.create(name='Weight', datatype=Attribute.TYPE_FLOAT)
>>> Attribute.objects.create(name='Height', datatype=Attribute.TYPE_INT)
>>> Attribute.objects.create(name='Is pregant?', datatype=Attribute.TYPE_BOOLEAN)
Now let's create a patient, and set some of these attributes::
>>> p = Patient.objects.create(name='Bob')
>>> p.eav.height = 46
>>> p.eav.weight = 42.2
>>> p.eav.is_pregnant = False
>>> p.save()
>>> bob = Patient.objects.get(name='Bob')
>>> bob.eav.height
46
>>> bob.eav.weight
42.2
>>> bob.is_pregnant
False
Additionally, assuming we're using the eav manager, we can also do::
>>> p = Patient.objects.create(name='Jen', eav__height=32, eav__pregnant=True)
Filtering
=========
eav attributes are filterable, using the same __ notation as django foreign
keys::
Patient.objects.filter(eav__weight=42.2)
Patient.objects.filter(eav__weight__gt=42)
Patient.objects.filter(name='Bob', eav__weight__gt=42)
Patient.objects.exclude(eav__is_pregnant=False)
You can even use Q objects, however there are some known issues
(see :ref:`qobjectissue`) with Q object filters::
Patient.objects.filter(Q(name='Bob') | Q(eav__is_pregnant=False))
What about if you have a foreign key to a model that uses eav, but you want
to filter from a model that doesn't use eav? For example, let's say you have
a ``Patient`` model that **doesn't** use eav, but it has a foreign key to
``Encounter`` that **does** use eav. You can even filter through eav across
this relationship, but you need to use the eav manager for ``Patient``.
Just register ``Patient`` with eav, but set ``manager_only = True``
see (see :ref:`advancedregistration`). Then you can do::
Patient.objects.filter(encounter__eav__weight=2)
Admin Integration
=================
You can even have your eav attributes show up just like normal fields in your
models admin pages. Just register using the eav admin class::
from django.contrib import admin
from eav.forms import BaseDynamicEntityForm
from eav.admin import BaseEntityAdmin
class PatientAdminForm(BaseDynamicEntityForm):
model = Patient
class PatientAdmin(BaseEntityAdmin):
form = PatientAdminForm
admin.site.register(Patient, PatientAdmin)
Known Issues
============
.. _qobjectissue:
Q Object Filters
----------------
Due to an unexplained Q object / generic relation issue, exclude filters with
EAV Q objects, or EAV Q objects ANDed together may produce inaccurate results.
Additional Resources
====================
.. toctree::
:maxdepth: 2
docstrings

View file

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,4 @@
{% extends "!layout.html" %}
{% block extrahead %}
<a href="https://github.com/jazzband/django-eav2"><img style="position: fixed; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub"></a>
{% endblock %}

View file

@ -0,0 +1,11 @@
<h3>About</h3>
<p>
Django EAV 2 is an entity-attribute-value storage for modern Django.
</p>
<h3>Useful Links</h3>
<ul>
<li><a href="index.html">Home</a></li>
<li><a href="https://pypi.org/project/django-eav2/">PyPI</a></li>
<li><a href="https://github.com/jazzband/django-eav2">GitHub</a></li>
<li><a href="https://github.com/jazzband/django-eav2/issues">Issue Tracker</a></li>
</ul>

View file

@ -0,0 +1,3 @@
<p class="logo"><a href="{{ pathto(master_doc) }}">
<img class="logo" src="{{ pathto('_static/logo.png', 1) }}" width="250" height="50" alt="Logo">
</a></p>

74
docs/source/api.rst Normal file
View file

@ -0,0 +1,74 @@
.. rst-class:: doc-api
API Reference
=============
If you are looking for information on a specific function, class, or method,
this part of the documentation is for you.
.. toctree::
Admin
-----
.. automodule:: eav.admin
:members:
:member-order: bysource
Decorators
----------
.. automodule:: eav.decorators
:members:
:member-order: bysource
Fields
------
.. automodule:: eav.fields
:members:
:member-order: bysource
Forms
-----
.. automodule:: eav.forms
:members:
:member-order: bysource
:exclude-members: FIELD_CLASSES
Managers
--------
.. automodule:: eav.managers
:members:
:member-order: bysource
Models
------
.. automodule:: eav.models
:members:
:member-order: bysource
Queryset
--------
.. automodule:: eav.queryset
:members:
:member-order: bysource
Registry
--------
.. automodule:: eav.registry
:members:
:member-order: bysource
Validators
----------
.. automodule:: eav.validators
:members:
:member-order: bysource

162
docs/source/conf.py Normal file
View file

@ -0,0 +1,162 @@
# Sphinx documentation generator configuration.
#
# More information on the configuration options is available at:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
from __future__ import annotations
import os
import sys
from pathlib import Path
import django
from django.conf import settings
from sphinx.ext.autodoc import between
# For discovery of Python modules
sys.path.insert(0, str(Path().cwd()))
# For finding the django_settings.py file
sys.path.insert(0, str(Path("../../").resolve()))
# Pass settings into configure.
settings.configure(
INSTALLED_APPS=[
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"eav",
],
SECRET_KEY=os.environ.get("DJANGO_SECRET_KEY", "this-is-not-s3cur3"),
EAV2_PRIMARY_KEY_FIELD="django.db.models.BigAutoField",
)
# Call django.setup to load installed apps and other stuff.
django.setup()
# -- Project information -----------------------------------------------------
project = "Django EAV 2"
copyright = "2018, Iwo Herka and team at MAKIMO" # noqa: A001
author = "-"
# The short X.Y version
version = ""
# The full version, including alpha/beta/rc tags
release = "0.10.0"
def setup(app):
"""Use the configuration file itself as an extension."""
app.connect(
"autodoc-process-docstring",
between(
"^.*IGNORE.*$",
exclude=True,
),
)
return app
# -- General configuration ---------------------------------------------------
extensions = [
"sphinx.ext.napoleon",
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx.ext.coverage",
"sphinx.ext.viewcode",
"sphinx_rtd_theme",
]
templates_path = ["_templates"]
source_suffix = ".rst"
master_doc = "index"
language = "en"
exclude_patterns = ["build"]
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx"
# -- Options for HTML output -------------------------------------------------
html_theme = "sphinx_rtd_theme"
html_static_path = ["_static"]
html_sidebars = {
"index": ["sidebarintro.html", "localtoc.html"],
"**": [
"sidebarintro.html",
"localtoc.html",
"relations.html",
"searchbox.html",
],
}
htmlhelp_basename = "DjangoEAV2doc"
# -- Options for LaTeX output ------------------------------------------------
latex_elements: dict[str, str] = {}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, "DjangoEAV2.tex", "Django EAV 2 Documentation", "-", "manual"),
]
# -- Options for manual page output ------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(
master_doc,
"djangoeav2",
"Django EAV 2 Documentation",
[author],
1,
),
]
# -- Options for Texinfo output ----------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(
master_doc,
"DjangoEAV2",
"Django EAV 2 Documentation",
author,
"DjangoEAV2",
"One line description of project.",
"Miscellaneous",
),
]
# -- Extension configuration -------------------------------------------------
# -- Options for intersphinx extension ---------------------------------------
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {"python": ("https://docs.python.org/3", None)}
# -- Autodoc configuration ---------------------------------------------------
add_module_names = False

View file

@ -0,0 +1,37 @@
Getting Started
===============
Installation
------------
::
pip install django-eav2
Configuration
-------------
After you've installed the package, you have to add it to your Django apps
::
INSTALLED_APPS = [
...
'eav',
]
Note: Django 2.2 Users
^^^^^^^^^^^^^^^^^^^^^^
Since ``models.JSONField()`` isn't supported in Django 2.2, we use `django-jsonfield-backport <https://github.com/laymonage/django-jsonfield-backport>`_
to provide `JSONField <https://docs.djangoproject.com/en/dev/releases/3.1/#jsonfield-for-all-supported-database-backends>`_
functionality.
This requires adding ``django_jsonfield_backport`` to your INSTALLED_APPS as well.
::
INSTALLED_APPS = [
...
'eav',
'django_jsonfield_backport',
]

72
docs/source/index.rst Normal file
View file

@ -0,0 +1,72 @@
.. .. image:: _static/logo.png
.. :align: center
.. rst-class:: doc-title
Django EAV 2
============
Django EAV 2 is an entity-attribute-value storage for modern Django.
Getting started is very easy.
**Step 1.** Register a model:
.. code-block:: python
import eav
eav.register(Supplier)
or with decorators:
.. code-block:: python
from eav.decorators import register_eav
@register_eav
class Supplier(models.Model):
...
**Step 2.** Create an attribute:
.. code-block:: python
Attribute.objects.create(name='City', datatype=Attribute.TYPE_TEXT)
**Step 3.** That's it! You're ready to go:
.. code-block:: python
supplier.eav.city = 'London'
supplier.save()
Supplier.objects.filter(eav__city='London')
# = <EavQuerySet [<Supplier: Supplier object (1)>]>
Documentation
-------------
.. toctree::
:maxdepth: 2
getting_started
usage
API Reference
-------------
If you are looking for information on a specific function, class, or
method, this part of the documentation is for you.
.. toctree::
:maxdepth: 2
api
Indices and tables
------------------
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

314
docs/source/usage.rst Normal file
View file

@ -0,0 +1,314 @@
Usage
=====
This part of the documentation will take you through all of library's
usage patterns. Before you can use EAV attributes, however, you need to
register your models.
Simple Registration
-------------------
Basic registration is very simple. You can do it with :func:`~eav.register` method:
.. code-block:: python
import eav
eav.register(Parts)
or with decorators:
.. code-block:: python
from eav.decorators import register_eav
@register_eav
class Supplier(models.Model):
...
Generally, if you chose the former, the most appropriate place for the
statement would be at the bottom of your ``models.py`` or immediately after
model definition.
Advanced Registration
---------------------
Under the hood, registration does a couple of things:
1. Attaches :class:`~eav.managers.EntityManager` to your class. By default,
it replaces standard manager (*objects*). You can configure under which
attribute it is accessible with :class:`~.eav.registry.EavConfig` (see below).
2. Binds your model's *post_init* signal with
:meth:`~eav.registry.Registry.attach_eav_attr` method. It is used to
attach :class:`~eav.models.Entity` helper object to each model instance.
Entity, in turn, is used to retrieve, store and validate attribute values.
By default, it's accessible under *eav* attribute:
.. code-block:: python
part.eav.weight = 0.56
part.save()
3. Binds your model's *pre_save* and *post_save* signals to
:meth:`~eav.models.Entity.pre_save_handler` and
:meth:`~eav.models.Entity.post_save_hander`, respectively.
Those methods are responsible for validation and storage
of attribute values.
4. Setups up generic relation to :class:`~eav.models.Value` set.
By default, it's accessed under *eav_values*:
.. code-block:: python
patient.eav_values.all()
# = <QuerySet [has fever?: "True" (1), temperature: 37.7 (2)]>
5. Sets *_eav_config_cls* attribute storing model of the config class
used by :class:`~eav.registry.Registry`. Defaults
to :class:`~eav.registry.EavConfig`; can be overridden (see below).
With that out of the way, almost every aspect of the registration can
be customized. All available options are provided to registration
via config class: :class:`~eav.registry.EavConfig` passed to
:meth:`~eav.register`. You can change them by overriding the class and passing
it as a second argument. Available options are as follows:
1. ``manager_attr`` - Specifies manager name. Used to refer to the
manager from Entity class, "objects" by default.
2. ``manager_only`` - Specifies whether signals and generic relation should
be setup for the registered model.
3. ``eav_attr`` - Named of the Entity toolkit instance on the registered
model instance. "eav" by default. See attach_eav_attr.
4. ``generic_relation_attr`` - Name of the GenericRelation to Value
objects. "eav_values" by default.
5. ``generic_relation_related_name`` - Name of the related name for
GenericRelation from Entity to Value. None by default. Therefore,
if not overridden, it is not possible to query Values by Entities.
Example registration may look like:
.. code-block:: python
class SupplierEavConfig(EavConfig):
manager_attr = 'eav_objects'
eav.register(supplier, SupplierEavConfig)
.. note::
As of now, configurable registration is not supported via
class decorator. You have to use explicit method call.
Additionally, :class:`~eav.registry.EavConfig` provides *classmethod*
:meth:`~eav.registry.EavConfig.get_attributes` which is used to determine
a set of attributes available to a given model. By default, it returns
``Attribute.objects.all()``. As usual, it can be customized:
.. code-block:: python
from eav.models import Attribute
class SomeModelEavConfig(EavConfig):
@classmethod
def get_attributes(cls):
return Attribute.objects.filter(slug__startswith='a')
Attribute validation includes checks against illegal attribute value
assignments. This means that value assignments for attributes which are
excluded for the model are treated with
:class:`~eav.exceptions.IllegalAssignmentException`. For example (extending
previous one):
.. code-block:: python
some_model.eav.beard = True
some_model.save()
will throw an exception.
Creating Attributes
-------------------
Once your models are registered, you can starting creating attributes for
them. Two most important attributes of ``Attribute`` class are *slug* and
*datatype*. *slug* is a unique global identifier (there must be at most
one ``Attribute`` instance with given `slug`) and must be a valid Python
variable name, as it's used to access values for that attribute from
:class:`~eav.models.Entity` helper:
.. code-block:: python
from eav.models import Attribute
Attribute.objects.create(slug='color', datatype=Attribute.TYPE_TEXT)
flower.eav.color = 'red'
# Alternatively, assuming you're using default EntityManager:
Attribute.objects.create(slug='color', datatype=Attribute.TYPE_TEXT)
Flower.objects.create(name='rose', eav__color='red')
*datatype* determines type of attribute (and by extension type of value
stored in :class:`~eav.models.Value`). Available choices are:
========= ==================
Type Attribute Constant
========= ==================
*int* ``TYPE_INT``
*float* ``TYPE_FLOAT``
*text* ``TYPE_TEXT``
*date* ``TYPE_DATE``
*bool* ``TYPE_BOOLEAN``
*object* ``TYPE_OBJECT``
*enum* ``TYPE_ENUM``
*json* ``TYPE_JSON``
*csv* ``TYPE_CSV``
========= ==================
If you want to create an attribute with data-type *enum*, you need to provide
it with ``enum_group``:
.. code-block:: python
from eav.models import EnumValue, EnumGroup, Attribute
true = EnumValue.objects.create(value='Yes')
false = EnumValue.objects.create(value='No')
bool_group = EnumGroup.objects.create(name='Yes / No')
bool_group.enums.add(true, false)
Attribute.objects.create(
name='hungry?',
datatype=Attribute.TYPE_ENUM,
enum_group=bool_group
)
# = <Attribute: hungry? (Multiple Choice)>
The attribute type *json* allows to store them in JSON format, which internally use JSONField:
.. code-block:: python
Attribute.objects.create(name='name_intl', datatype=Attribute.TYPE_JSON)
prod = Product.objects.create(sku='PRD00001', eav__name_intl={
"es": "Escoba Verde",
"en": "Green Broom",
"it": "Scopa Verde"
})
prod2 = Product.objects.create(sku='PRD00002', eav__name_intl={
"es": "Escoba Roja",
"en": "Red Broom"
})
prod3 = Product.objects.create(sku='PRD00003', eav__name_intl={
"es": "Escoba Azul",
"it": "Scopa Blu"
})
prod.eav.name_intl
{'es': 'Escoba Verde', 'en': 'Green Broom', 'it': 'Scopa Verde'}
type(prod.eav.name_intl)
dict
Product.objects.filter(eav__name_intl__has_key="it")
<EavQuerySet [<Product: PRD00001>, <Product: PRD00003>]>
The attribute type *csv* allows to store Comma Separated Values, using ";" as a separator:
.. code-block:: python
Attribute.objects.create(name='colors', datatype=Attribute.TYPE_CSV)
prod = Product.objects.create(sku='PRD00001', eav__colors="red;green;blue")
prod2 = Product.objects.create(sku='PRD00002', eav__colors="red;green")
prod3 = Product.objects.create(sku='PRD00003', eav__colors="red;blue")
prod4 = Product.objects.create(sku='PRD00004', eav__colors="")
prod.eav.colors
["red", "green", "blue"]
type(prod.eav.name_intl)
list
Product.objects.filter(eav__name_colors="green")
<EavQuerySet [<Product: PRD00001>, <Product: PRD00002>]>
Product.objects.filter(~Q(eav__name_colors__isnull=False))
<EavQuerySet [<Product: PRD00004>]>
Finally, attribute type *object* allows to relate Django model instances
via generic foreign keys:
.. code-block:: python
Attribute.objects.create(name='Supplier', datatype=Attribute.TYPE_OBJECT)
steve = Supplier.objects.create(name='Steve')
cog = Part.objects.create(name='Cog', eav__supplier=steve)
cog.eav.supplier
# = <Supplier: Steve (1)>
Filtering By Attributes
-----------------------
Once you've created your attributes and values for them, you can use them
to filter Django models. Django EAV 2 is using the same notation as Django's
foreign-keys:
.. code-block:: python
Part.objects.filter(eav__weight=10)
Part.objects.filter(eav__weight__gt=10)
Part.objects.filter(eav__code__startswith='A')
# Of course, you can mix them with regular queries:
Part.objects.filter(name='Cog', eav__height=7.8)
# Querying enums works either by enum instance or by it's text representation as follows:
yes = EnumValue.objects.get(name='Yes')
Part.objects.filter(eav__is_available=yes) # via EnumValue
Part.objects.filter(eav__is_available='yes) # via EnumValue's value
You can use ``Q`` expressions too:
.. code-block:: python
Patient.objects.filter(
Q(eav__sex='male', eav__fever=no) | Q(eav__city='Nice') & Q(eav__age__gt=32)
)
Admin Integration
-----------------
Django EAV 2 seamlessly integrates with Django's admin interface by providing
dynamic attribute management directly within the admin panel. This feature
provides the EAV Attributes as a separate fieldset, whether use the base
fieldset or when providing your own.
.. code-block:: python
from django.contrib import admin
from eav.forms import BaseDynamicEntityForm
from eav.admin import BaseEntityAdmin
class PatientAdminForm(BaseDynamicEntityForm):
model = Patient
class PatientAdmin(BaseEntityAdmin):
form = PatientAdminForm
admin.site.register(Patient, PatientAdmin)
Customizing the EAV Fieldset
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The Django EAV 2 integration allows you to customize the presentation of EAV
attributes in the admin interface through the use of a dedicated fieldset. You
can configure this fieldset by setting ``eav_fieldset_title`` and
``eav_fieldset_description`` within your admin class.

View file

@ -1,9 +1,10 @@
__version__ = '0.10.2'
def register(model_cls, config_cls=None):
from .registry import Registry
from eav.registry import Registry
Registry.register(model_cls, config_cls)
def unregister(model_cls):
from .registry import Registry
from eav.registry import Registry
Registry.unregister(model_cls)

View file

@ -1,65 +1,147 @@
'''Admin. This module contains classes used for admin integration.'''
"""This module contains classes used for admin integration."""
from __future__ import annotations
from typing import TYPE_CHECKING, Any, ClassVar, Dict, List, Union
from django.contrib import admin
from django.contrib.admin.options import InlineModelAdmin
from django.contrib.admin.options import ModelAdmin
from django.contrib.admin.options import InlineModelAdmin, ModelAdmin
from django.forms.models import BaseInlineFormSet
from django.utils.safestring import mark_safe
from .models import Attribute, EnumGroup, EnumValue, Value
from eav.models import Attribute, EnumGroup, EnumValue, Value
if TYPE_CHECKING:
from collections.abc import Sequence
_FIELDSET_TYPE = List[Union[str, Dict[str, Any]]] # type: ignore[misc]
some_attribute = ClassVar[Dict[str, str]]
class BaseEntityAdmin(ModelAdmin):
"""Custom admin model to support dynamic EAV fieldsets.
Overrides the default rendering of the change form in the Django admin to
dynamically integrate EAV fields into the form fieldsets. This approach
allows EAV attributes to be rendered alongside standard model fields within
the admin interface.
Attributes:
eav_fieldset_title (str): Title for the dynamically added EAV fieldset.
eav_fieldset_description (str): Optional description for the EAV fieldset.
"""
eav_fieldset_title: str = "EAV Attributes"
eav_fieldset_description: str | None = None
def render_change_form(self, request, context, *args, **kwargs):
"""
Wrapper for `ModelAdmin.render_change_form`. Replaces standard static
`AdminForm` with an EAV-friendly one. The point is that our form generates
fields dynamically and fieldsets must be inferred from a prepared and
validated form instance, not just the form class. Django does not seem
to provide hooks for this purpose, so we simply wrap the view and
substitute some data.
"""
form = context['adminform'].form
"""Dynamically modifies the admin form to include EAV fields.
# Infer correct data from the form.
fieldsets = self.fieldsets or [(None, {'fields': form.fields.keys()})]
adminform = admin.helpers.AdminForm(form, fieldsets, self.prepopulated_fields)
media = mark_safe(self.media + adminform.media)
Identifies EAV fields associated with the instance being edited and
dynamically inserts them into the admin form's fieldsets. This method
ensures EAV fields are appropriately displayed in a dedicated fieldset
and avoids field duplication.
Args:
request: HttpRequest object representing the current request.
context: Dictionary containing context data for the form template.
*args: Variable length argument list.
**kwargs: Arbitrary keyword arguments.
Returns:
HttpResponse object representing the rendered change form.
"""
form = context["adminform"].form
# Identify EAV fields based on the form instance's configuration.
eav_fields = self._get_eav_fields(form.instance)
# # Fallback to default if no EAV fields exist
if not eav_fields:
return super().render_change_form(request, context, *args, **kwargs)
# Get the non-EAV fieldsets and then append our own
fieldsets = list(self.get_fieldsets(request, kwargs["obj"]))
fieldsets.append(self._get_eav_fieldset(eav_fields))
# Reconstruct the admin form with updated fieldsets.
adminform = admin.helpers.AdminForm(
form,
fieldsets,
# Clear prepopulated fields on a view-only form to avoid a crash.
(
self.prepopulated_fields
if self.has_change_permission(request, kwargs["obj"])
else {}
),
readonly_fields=self.readonly_fields,
model_admin=self,
)
media = mark_safe(context["media"] + adminform.media) # noqa: S308
context.update(adminform=adminform, media=media)
return super(BaseEntityAdmin, self).render_change_form(
request, context, *args, **kwargs
)
return super().render_change_form(request, context, *args, **kwargs)
def _get_eav_fields(self, instance) -> list[str]:
"""Retrieves a list of EAV field slugs for the given instance.
Args:
instance: The model instance for which EAV fields are determined.
Returns:
A list of strings representing the slugs of EAV fields.
"""
entity = getattr(instance, instance._eav_config_cls.eav_attr) # noqa: SLF001
return list(entity.get_all_attributes().values_list("slug", flat=True))
def _get_eav_fieldset(self, eav_fields) -> _FIELDSET_TYPE:
"""Constructs an EAV Attributes fieldset for inclusion in admin form fieldsets.
Generates a list representing a fieldset specifically for Entity-Attribute-Value
(EAV) fields, intended to be appended to the admin form's fieldsets
configuration. This facilitates the dynamic inclusion of EAV fields within the
Django admin interface by creating a designated section for these attributes.
Args:
eav_fields (List[str]): A list of slugs representing the EAV fields to be
included in the EAV Attributes fieldset.
"""
return [
self.eav_fieldset_title,
{"fields": eav_fields, "description": self.eav_fieldset_description},
]
class BaseEntityInlineFormSet(BaseInlineFormSet):
"""
An inline formset that correctly initializes EAV forms.
"""
def add_fields(self, form, index):
if self.instance:
setattr(form.instance, self.fk.name, self.instance)
form._build_dynamic_fields()
super(BaseEntityInlineFormSet, self).add_fields(form, index)
form._build_dynamic_fields() # noqa: SLF001
super().add_fields(form, index)
class BaseEntityInline(InlineModelAdmin):
"""
Inline model admin that works correctly with EAV attributes. You should mix
in the standard StackedInline or TabularInline classes in order to define
formset representation, e.g.::
in the standard ``StackedInline`` or ``TabularInline`` classes in order to
define formset representation, e.g.::
class ItemInline(BaseEntityInline, StackedInline):
model = Item
form = forms.ItemForm
.. warning: TabularInline does *not* work out of the box. There is,
however, a patched template `admin/edit_inline/tabular.html` bundled
with EAV-Django. You can copy or symlink the `admin` directory to your
templates search path (see Django documentation).
.. warning:: ``TabularInline`` does *not* work out of the box. There is,
however, a patched template ``admin/edit_inline/tabular.html`` bundled
with EAV-Django. You can copy or symlink the ``admin`` directory to
your templates search path (see Django documentation).
"""
formset = BaseEntityInlineFormSet
def get_fieldsets(self, request, obj=None):
@ -72,15 +154,15 @@ class BaseEntityInline(InlineModelAdmin):
instance = self.model(**kw)
form = formset.form(request.POST, instance=instance)
return [(None, {'fields': form.fields.keys()})]
return [(None, {"fields": form.fields.keys()})]
class AttributeAdmin(ModelAdmin):
list_display = ('name', 'slug', 'datatype', 'description')
prepopulated_fields = {'slug': ('name',)}
list_display = ("name", "slug", "datatype", "description")
prepopulated_fields: ClassVar[dict[str, Sequence[str]]] = {"slug": ("name",)}
admin.site.register(Attribute, AttributeAdmin)
admin.site.register(Value)
admin.site.register(EnumValue)
admin.site.register(EnumGroup)
admin.site.register(Value)

View file

@ -1,25 +1,25 @@
'''
Decorators.
"""
This module contains pure wrapper functions used as decorators.
Functions in this module should be simple and not involve complex logic.
'''
"""
def register_eav(**kwargs):
'''
Registers the given model(s) classes and wrapped Model class with
django-eav::
"""
Registers the given model(s) classes and wrapped ``Model`` class with
Django EAV 2::
@register_eav
class Author(models.Model):
pass
'''
from . import register
"""
from django.db.models import Model
from eav import register
def _model_eav_wrapper(model_class):
if not issubclass(model_class, Model):
raise ValueError('Wrapped class must subclass Model.')
raise TypeError("Wrapped class must subclass Model.")
register(model_class, **kwargs)
return model_class

View file

@ -1,2 +1,2 @@
class IllegalAssignmentException(Exception):
pass
class IllegalAssignmentException(Exception): # noqa: N818
pass

View file

@ -1,67 +1,83 @@
'''
Fields.
Contains two custom fields:
* :class:`EavSlugField`
* :class:`EavDatatypeField`
'''
import re
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
class EavSlugField(models.SlugField):
'''
The slug field used by :class:`~eav.models.Attribute`
'''
def validate(self, value, instance):
'''
Slugs are used to convert the Python attribute name to a database
lookup and vice versa. We need it to be a valid Python identifier.
We don't want it to start with a '_', underscore will be used
var variables we don't want to be saved in db.
'''
super(EavSlugField, self).validate(value, instance)
slug_regex = r'[a-z][a-z0-9_]*'
if not re.match(slug_regex, value):
raise ValidationError(_(u"Must be all lower case, " \
u"start with a letter, and contain " \
u"only letters, numbers, or underscores."))
@staticmethod
def create_slug_from_name(name):
'''
Creates a slug based on the name
'''
name = name.strip().lower()
# Change spaces to underscores
name = '_'.join(name.split())
# Remove non alphanumeric characters
return re.sub('[^\w]', '', name)
from eav.forms import CSVFormField
class EavDatatypeField(models.CharField):
'''
The datatype field used by :class:`~eav.models.Attribute`
'''
"""
The datatype field used by :class:`~eav.models.Attribute`.
"""
def validate(self, value, instance):
'''
"""
Raise ``ValidationError`` if they try to change the datatype of an
:class:`~eav.models.Attribute` that is already used by
:class:`~eav.models.Value` objects.
'''
super(EavDatatypeField, self).validate(value, instance)
"""
super().validate(value, instance)
if not instance.pk:
return
# added
if not type(instance).objects.filter(pk=instance.pk).exists():
return
if type(instance).objects.get(pk=instance.pk).datatype == instance.datatype:
return
if instance.value_set.count():
raise ValidationError(_(u"You cannot change the datatype of an "
u"attribute that is already in use."))
raise ValidationError(
_(
"You cannot change the datatype of an "
+ "attribute that is already in use.",
),
)
class CSVField(models.TextField): # (models.Field):
description = _("A Comma-Separated-Value field.")
default_separator = ";"
def __init__(self, separator=";", *args, **kwargs):
self.separator = separator
kwargs.setdefault("default", "")
super().__init__(*args, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super().deconstruct()
if self.separator != self.default_separator:
kwargs["separator"] = self.separator
return name, path, args, kwargs
def formfield(self, **kwargs):
defaults = {"form_class": CSVFormField}
defaults.update(kwargs)
return super().formfield(**defaults)
def from_db_value(self, value, expression, connection):
if value is None:
return []
return value.split(self.separator)
def to_python(self, value):
if value is None:
return []
if isinstance(value, list):
return value
return value.split(self.separator)
def get_prep_value(self, value):
if not value:
return ""
if isinstance(value, str):
return value
if isinstance(value, list):
return self.separator.join(value)
return value
def value_to_string(self, obj):
value = self.value_from_object(obj)
return self.get_prep_value(value)

View file

@ -1,98 +1,152 @@
'''Forms. This module contains forms used for admin integration.'''
"""This module contains forms used for admin integration."""
from __future__ import annotations
from copy import deepcopy
from typing import ClassVar
from django.contrib.admin.widgets import AdminSplitDateTime
from django.forms import (BooleanField, CharField, ChoiceField, DateTimeField,
FloatField, IntegerField, ModelForm)
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError
from django.forms import (
BooleanField,
CharField,
ChoiceField,
Field,
FloatField,
IntegerField,
JSONField,
ModelForm,
SplitDateTimeField,
)
from django.utils.translation import gettext_lazy as _
from eav.widgets import CSVWidget
class CSVFormField(Field):
message = _("Enter comma-separated-values. eg: one;two;three.")
code = "invalid"
widget = CSVWidget
default_separator = ";"
def __init__(self, *args, **kwargs):
kwargs.pop("max_length", None)
self.separator = kwargs.pop("separator", self.default_separator)
super().__init__(*args, **kwargs)
def to_python(self, value):
if not value:
return []
return [v.strip() for v in value.split(self.separator) if v]
def validate(self, field_value):
super().validate(field_value)
if not isinstance(field_value, list):
raise ValidationError(self.message, code=self.code)
class BaseDynamicEntityForm(ModelForm):
'''
ModelForm for entity with support for EAV attributes. Form fields are
created on the fly depending on Schema defined for given entity instance.
"""
``ModelForm`` for entity with support for EAV attributes. Form fields are
created on the fly depending on schema defined for given entity instance.
If no schema is defined (i.e. the entity instance has not been saved yet),
only static fields are used. However, on form validation the schema will be
retrieved and EAV fields dynamically added to the form, so when the
validation is actually done, all EAV fields are present in it (unless
Rubric is not defined).
'''
FIELD_CLASSES = {
'text': CharField,
'float': FloatField,
'int': IntegerField,
'date': DateTimeField,
'bool': BooleanField,
'enum': ChoiceField,
Mapping between attribute types and field classes is as follows:
===== =============
Type Field
===== =============
text CharField
float IntegerField
int DateTimeField
date SplitDateTimeField
bool BooleanField
enum ChoiceField
json JSONField
csv CSVField
===== =============
"""
FIELD_CLASSES: ClassVar[dict[str, Field]] = {
"text": CharField,
"float": FloatField,
"int": IntegerField,
"date": SplitDateTimeField,
"bool": BooleanField,
"enum": ChoiceField,
"json": JSONField,
"csv": CSVFormField,
}
def __init__(self, data=None, *args, **kwargs):
super(BaseDynamicEntityForm, self).__init__(data, *args, **kwargs)
config_cls = self.instance._eav_config_cls
super().__init__(data, *args, **kwargs)
config_cls = self.instance._eav_config_cls # noqa: SLF001
self.entity = getattr(self.instance, config_cls.eav_attr)
self._build_dynamic_fields()
def _build_dynamic_fields(self):
# reset form fields
# Reset form fields.
self.fields = deepcopy(self.base_fields)
for attribute in self.entity.get_all_attributes():
value = getattr(self.entity, attribute.slug)
defaults = {
'label': attribute.name.capitalize(),
'required': attribute.required,
'help_text': attribute.help_text,
'validators': attribute.get_validators(),
"label": attribute.name.capitalize(),
"required": attribute.required,
"help_text": attribute.help_text,
"validators": attribute.get_validators(),
}
datatype = attribute.datatype
if datatype == attribute.TYPE_ENUM:
enums = attribute.get_choices() \
.values_list('id', 'value')
values = attribute.get_choices().values_list("id", "value")
choices = [("", ""), ("-----", "-----"), *list(values)]
defaults.update({"choices": choices})
choices = [('', '-----')] + list(enums)
defaults.update({'choices': choices})
if value:
defaults.update({'initial': value.pk})
defaults.update({"initial": value.pk})
elif datatype == attribute.TYPE_DATE:
defaults.update({'widget': AdminSplitDateTime})
defaults.update({"widget": AdminSplitDateTime})
elif datatype == attribute.TYPE_OBJECT:
continue
MappedField = self.FIELD_CLASSES[datatype]
MappedField = self.FIELD_CLASSES[datatype] # noqa: N806
self.fields[attribute.slug] = MappedField(**defaults)
# fill initial data (if attribute was already defined)
if value and not datatype == attribute.TYPE_ENUM: #enum done above
# Fill initial data (if attribute was already defined).
if value and datatype != attribute.TYPE_ENUM:
self.initial[attribute.slug] = value
def save(self, commit=True):
def save(self, *, commit=True):
"""
Saves this ``form``'s cleaned_data into model instance
``self.instance`` and related EAV attributes.
Returns ``instance``.
``self.instance`` and related EAV attributes. Returns ``instance``.
"""
if self.errors:
raise ValueError(_(u"The %s could not be saved because the data"
u"didn't validate.") % \
self.instance._meta.object_name)
raise ValueError(
_(
"The %s could not be saved because the data didn't validate.",
)
% self.instance._meta.object_name, # noqa: SLF001
)
# Create entity instance, don't save yet.
instance = super(BaseDynamicEntityForm, self).save(commit=False)
instance = super().save(commit=False)
# Assign attributes.
for attribute in self.entity.get_all_attributes():
value = self.cleaned_data.get(attribute.slug)
if attribute.datatype == attribute.TYPE_ENUM:
if value:
value = attribute.enum_group.enums.get(pk=value)
else:
value = None
value = attribute.enum_group.values.get(pk=value) if value else None
setattr(self.entity, attribute.slug, value)

View file

@ -0,0 +1,278 @@
# Indonesian translation for django-eav2
# Copyright (C) 2023
# This file is distributed under the same license as the django-eav2 package.
# Kira <kiraware@github.com>, 2023.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: django-eav2 1.3.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-06-29 16:43+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Kira <kiraware@github.com>, 2023\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: id\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: .\eav\fields.py:30
msgid "You cannot change the datatype of an attribute that is already in use."
msgstr "Anda tidak dapat mengubah tipe data atribut yang sudah digunakan."
#: .\eav\fields.py:36
msgid "A Comma-Separated-Value field."
msgstr "Bidang Nilai-yang-Dipisahkan-Koma."
#: .\eav\forms.py:28
msgid "Enter comma-separated-values. eg: one;two;three."
msgstr "Masukkan nilai-yang-dipisahkan-koma. misalnya: satu;dua;tiga."
#: .\eav\forms.py:138
#, python-format
msgid "The %s could not be saved because the datadidn't validate."
msgstr "%s tidak dapat disimpan karena datanya tidak tervalidasi."
#: .\eav\models.py:77
msgid "EnumValue"
msgstr "EnumValue"
#: .\eav\models.py:78
msgid "EnumValues"
msgstr "EnumValues"
#: .\eav\models.py:81 .\eav\models.py:439
msgid "Value"
msgstr "Nilai"
#: .\eav\models.py:106
msgid "EnumGroup"
msgstr "EnumGroup"
#: .\eav\models.py:107
msgid "EnumGroups"
msgstr "EnumGroups"
#: .\eav\models.py:112 .\eav\models.py:218
msgid "Name"
msgstr "Nama"
#: .\eav\models.py:116
msgid "Enum group"
msgstr "Grup enum"
#: .\eav\models.py:182 .\eav\models.py:447
msgid "Attribute"
msgstr "Atribut"
#: .\eav\models.py:183
msgid "Attributes"
msgstr "Atribut"
#: .\eav\models.py:196
msgid "Text"
msgstr "Teks"
#: .\eav\models.py:197
msgid "Date"
msgstr "Tanggal"
#: .\eav\models.py:198
msgid "Float"
msgstr "Bilangan desimal"
#: .\eav\models.py:199
msgid "Integer"
msgstr "Bilangan bulat"
#: .\eav\models.py:200
msgid "True / False"
msgstr "Benar / Salah"
#: .\eav\models.py:201
msgid "Django Object"
msgstr "Objek Django"
#: .\eav\models.py:202
msgid "Multiple Choice"
msgstr "Pilihan Ganda"
#: .\eav\models.py:203
msgid "JSON Object"
msgstr "Objek JSON"
#: .\eav\models.py:204
msgid "Comma-Separated-Value"
msgstr "Nilai-yang-Dipisahkan-Koma"
#: .\eav\models.py:212
msgid "Data Type"
msgstr "Tipe Data"
#: .\eav\models.py:217
msgid "User-friendly attribute name"
msgstr "Nama atribut yang ramah pengguna"
#: .\eav\models.py:230
msgid "Short unique attribute label"
msgstr "Label atribut unik yang pendek"
#: .\eav\models.py:231
msgid "Slug"
msgstr "Slug"
#: .\eav\models.py:242
msgid "Required"
msgstr "Diperlukan"
#: .\eav\models.py:248
msgid "Entity content type"
msgstr "Jenis konten entitas"
#: .\eav\models.py:262
msgid "Choice Group"
msgstr "Grup Pilihan"
#: .\eav\models.py:269
msgid "Short description"
msgstr "Deskripsi singkat"
#: .\eav\models.py:270
msgid "Description"
msgstr "Deskripsi"
#: .\eav\models.py:277
msgid "Display order"
msgstr "Urutan tampilan"
#: .\eav\models.py:282 .\eav\models.py:490
msgid "Modified"
msgstr "Dimodifikasi"
#: .\eav\models.py:288 .\eav\models.py:485
msgid "Created"
msgstr "Dibuat"
#: .\eav\models.py:332
#, python-format
msgid "%(val)s is not a valid choice for %(attr)s"
msgstr "%(val)s bukan pilihan yang valid untuk %(attr)s"
#: .\eav\models.py:355
msgid "You must set the choice group for multiple choice attributes"
msgstr "Anda harus mengatur grup pilihan untuk atribut pilihan ganda"
#: .\eav\models.py:360
msgid "You can only assign a choice group to multiple choice attributes"
msgstr "Anda hanya dapat menetapkan grup pilihan ke atribut pilihan ganda"
#: .\eav\models.py:440
msgid "Values"
msgstr "Nilai"
#: .\eav\models.py:456
msgid "Entity id"
msgstr "id entitas"
#: .\eav\models.py:462
msgid "Entity uuid"
msgstr "uuid entitas"
#: .\eav\models.py:469
msgid "Entity ct"
msgstr "Entitas ct"
#: .\eav\models.py:497
msgid "Value bool"
msgstr "Nilai bool"
#: .\eav\models.py:502
msgid "Value CSV"
msgstr "Nilai CSV"
#: .\eav\models.py:507
msgid "Value date"
msgstr "Nilai tanggal"
#: .\eav\models.py:512
msgid "Value float"
msgstr "Nilai float"
#: .\eav\models.py:517
msgid "Value int"
msgstr "Nilai int"
#: .\eav\models.py:522
msgid "Value text"
msgstr "Nilai teks"
#: .\eav\models.py:530
msgid "Value JSON"
msgstr "Nilai JSON"
#: .\eav\models.py:539
msgid "Value enum"
msgstr "Nilai enum"
#: .\eav\models.py:546
msgid "Generic value id"
msgstr "Id nilai generik"
#: .\eav\models.py:555
msgid "Generic value content type"
msgstr "Jenis konten nilai generik"
#: .\eav\models.py:653
#, python-format
msgid "%(obj)s has no EAV attribute named %(attr)s"
msgstr "%(obj)s tidak memiliki atribut EAV bernama %(attr)s"
#: .\eav\models.py:725
msgid "{} EAV field cannot be blank"
msgstr "{} Bidang EAV tidak boleh kosong"
#: .\eav\models.py:732
#, python-format
msgid "%(attr)s EAV field %(err)s"
msgstr "%(attr)s bidang EAV %(err)s"
#: .\eav\validators.py:26
msgid "Must be str or unicode"
msgstr "Harus berupa str atau unicode"
#: .\eav\validators.py:36
msgid "Must be a float"
msgstr "Harus berupa float"
#: .\eav\validators.py:46
msgid "Must be an integer"
msgstr "Harus berupa integer"
#: .\eav\validators.py:57
msgid "Must be a date or datetime"
msgstr "Harus berupa date atau datetime"
#: .\eav\validators.py:65
msgid "Must be a boolean"
msgstr "Harus berupa boolean"
#: .\eav\validators.py:74
msgid "Must be a django model object instance"
msgstr "Harus berupa instance objek model django"
#: .\eav\validators.py:77
msgid "Model has not been saved yet"
msgstr "Model belum disimpan"
#: .\eav\validators.py:88
msgid "EnumValue has not been saved yet"
msgstr "EnumValue belum disimpan"
#: .\eav\validators.py:99 .\eav\validators.py:101
msgid "Must be a JSON Serializable object"
msgstr "Harus berupa objek JSON yang dapat diserialisasikan"
#: .\eav\validators.py:111
msgid "Must be Comma-Separated-Value."
msgstr "Harus berupa Nilai-ang-Dipisahkan-Koma."

Binary file not shown.

View file

@ -0,0 +1,194 @@
# Russian translation for django-eav2
# Copyright (C) 2019
# This file is distributed under the same license as the django-eav2 package.
# Evgeny Pisemsky <evgeny@pisemsky.com>, 2019.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-02-15 01:10+0300\n"
"PO-Revision-Date: 2019-02-15 02:13+0300\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"Last-Translator: Evgeny Pisemsky <evgeny@pisemsky.com>\n"
"Language-Team: \n"
"X-Generator: Poedit 1.8.11\n"
#: fields.py:25
msgid ""
"Must be all lower case, start with a letter, and contain only letters, "
"numbers, or underscores."
msgstr ""
"Должно быть в нижнем регистре, начинаться с буквы и содержать только буквы, "
"числа или подчёркивания."
#: fields.py:62
msgid "You cannot change the datatype of an attribute that is already in use."
msgstr "Вы не можете изменить тип данных атрибута, который уже используется."
#: forms.py:91
#, python-format
msgid "The %s could not be saved because the datadidn't validate."
msgstr "%s не может быть сохранено, потому что данные не корректны."
#: models.py:54
msgid "Value"
msgstr "Значение"
#: models.py:68 models.py:153
msgid "Name"
msgstr "Название"
#: models.py:69
msgid "Enum group"
msgstr "Группа выбора"
#: models.py:135
msgid "Text"
msgstr "Текст"
#: models.py:136
msgid "Date"
msgstr "Дата"
#: models.py:137
msgid "Float"
msgstr "Число с плавающей запятой"
#: models.py:138
msgid "Integer"
msgstr "Целое число"
#: models.py:139
msgid "True / False"
msgstr "Правда / Ложь"
#: models.py:140
msgid "Django Object"
msgstr "Объект Django"
#: models.py:141
msgid "Multiple Choice"
msgstr "Множественный выбор"
#: models.py:147
msgid "Data Type"
msgstr "Тип данных"
#: models.py:155
msgid "User-friendly attribute name"
msgstr "Понятное пользователю название атрибута"
#: models.py:164
msgid "Slug"
msgstr "Псевдоним"
#: models.py:168
msgid "Short unique attribute label"
msgstr "Короткая уникальная метка атрибута"
#: models.py:177
msgid "Required"
msgstr "Обязательно"
#: models.py:181
msgid "Choice Group"
msgstr "Группа выбора"
#: models.py:188
msgid "Description"
msgstr "Описание"
#: models.py:192
msgid "Short description"
msgstr "Краткое описание"
#: models.py:198
msgid "Display order"
msgstr "Порядок отображения"
#: models.py:203 models.py:392
msgid "Modified"
msgstr "Изменено"
#: models.py:208 models.py:391
msgid "Created"
msgstr "Создано"
#: models.py:250
#, python-format
msgid "%(val)s is not a valid choice for %(attr)s"
msgstr "%(val)s не является корректным выбором для %(attr)s"
#: models.py:273
msgid "You must set the choice group for multiple choice attributes"
msgstr "Вы должны назначить группу выбора для атрибутов множественного выбора"
#: models.py:278
msgid "You can only assign a choice group to multiple choice attributes"
msgstr ""
"Вы можете назначить группу выбора только для атрибутов множественного выбора"
#: models.py:398
msgid "Attribute"
msgstr "Атрибут"
#: models.py:416
#, python-format
msgid "%(enum)s is not a valid choice for %(attr)s"
msgstr "%(enum)s не является корректным выбором для %(attr)s"
#: models.py:492
#, python-format
msgid "%(obj)s has no EAV attribute named %(attr)s"
msgstr "%(obj)s не имеет атрибута EAV с названием %(attr)s"
#: models.py:557
msgid "{} EAV field cannot be blank"
msgstr "Поле EAV {} не может быть пустым"
#: models.py:564
#, python-format
msgid "%(attr)s EAV field %(err)s"
msgstr "Поле EAV %(attr)s %(err)s"
#: validators.py:25
msgid "Must be str or unicode"
msgstr "Должно быть строкой или юникодом"
#: validators.py:35
msgid "Must be a float"
msgstr "Должно быть числом с плавающей запятой"
#: validators.py:45
msgid "Must be an integer"
msgstr "Должно быть целым числом"
#: validators.py:54
msgid "Must be a date or datetime"
msgstr "Должно быть датой или датой со временем"
#: validators.py:62
msgid "Must be a boolean"
msgstr "Должно быть булевым значением"
#: validators.py:71
msgid "Must be a django model object instance"
msgstr "Должно быть экземпляром объекта модели Django"
#: validators.py:74
msgid "Model has not been saved yet"
msgstr "Модель ещё не была сохранена"
#: validators.py:85
msgid "Must be an EnumValue model object instance"
msgstr "Должно быть экземпляром объекта модели EnumValue"
#: validators.py:88
msgid "EnumValue has not been saved yet"
msgstr "EnumValue ещё не было сохранено"

Binary file not shown.

View file

@ -0,0 +1,279 @@
# Simplified Chinese translation for django-eav2
# Copyright (C) 2023
# This file is distributed under the same license as the django-eav2 package.
# FIRST 954-Ivory <954ivory@gmail.com>, 2023.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-02-07 02:17+0800\n"
"PO-Revision-Date: 2023-02-27 16:36+0800\n"
"Last-Translator: 954-Ivory <954ivory@gmail.com>\n"
"Language-Team: \n"
"Language: zh-Hans\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: .\fields.py:30
msgid "You cannot change the datatype of an attribute that is already in use."
msgstr "您不能更改已使用属性的数据类型。"
#: .\fields.py:36
msgid "A Comma-Separated-Value field."
msgstr "字符分隔值(CSV)字段。"
#: .\forms.py:28
msgid "Enter comma-separated-values. eg: one;two;three."
msgstr "输入字符分隔值(CSV)字段例如one;two;three。"
#: .\forms.py:137
#, python-format
msgid "The %s could not be saved because the datadidn't validate."
msgstr "由于数据未验证,无法保存 %s 。"
#: .\models.py:81
msgid "EnumValue"
msgstr "枚举值"
#: .\models.py:82
msgid "EnumValues"
msgstr "枚举值"
#: .\models.py:85 .\models.py:443
msgid "Value"
msgstr "值"
#: .\models.py:110
msgid "EnumGroup"
msgstr "枚举组"
#: .\models.py:111
msgid "EnumGroups"
msgstr "枚举组"
#: .\models.py:116 .\models.py:222
msgid "Name"
msgstr "名称"
#: .\models.py:120
msgid "Enum group"
msgstr "枚举组"
#: .\models.py:186 .\models.py:451
msgid "Attribute"
msgstr "属性"
#: .\models.py:187
msgid "Attributes"
msgstr "属性"
#: .\models.py:200
msgid "Text"
msgstr "文本"
#: .\models.py:201
msgid "Date"
msgstr "日期"
#: .\models.py:202
msgid "Float"
msgstr "浮点数"
#: .\models.py:203
msgid "Integer"
msgstr "整数"
#: .\models.py:204
msgid "True / False"
msgstr "布尔值"
#: .\models.py:205
msgid "Django Object"
msgstr "Django 对象"
#: .\models.py:206
msgid "Multiple Choice"
msgstr "多项选择"
#: .\models.py:207
msgid "JSON Object"
msgstr "JSON 对象"
#: .\models.py:208
msgid "Comma-Separated-Value"
msgstr "字符分隔值(CSV)"
#: .\models.py:216
msgid "Data Type"
msgstr "数据类型"
#: .\models.py:221
msgid "User-friendly attribute name"
msgstr "面向用户的名称"
#: .\models.py:234
msgid "Short unique attribute label"
msgstr "唯一的属性短标识符"
#: .\models.py:235
msgid "Slug"
msgstr "短标识符(Slug)"
#: .\models.py:246
msgid "Required"
msgstr "必填项"
#: .\models.py:252
msgid "Entity content type"
msgstr "实体内容类型"
#: .\models.py:266
msgid "Choice Group"
msgstr "选项组"
#: .\models.py:273
msgid "Short description"
msgstr "简短描述"
#: .\models.py:274
msgid "Description"
msgstr "描述"
#: .\models.py:281
msgid "Display order"
msgstr "显示顺序"
#: .\models.py:286 .\models.py:494
msgid "Modified"
msgstr "修改"
#: .\models.py:292 .\models.py:489
msgid "Created"
msgstr "创建"
#: .\models.py:336
#, python-format
msgid "%(val)s is not a valid choice for %(attr)s"
msgstr "%(val)s 不是有效的 %(attr)s 选项"
#: .\models.py:359
msgid "You must set the choice group for multiple choice attributes"
msgstr "您必须为多项选择属性设置选项组"
#: .\models.py:364
msgid "You can only assign a choice group to multiple choice attributes"
msgstr "您只能将选项组分配给多项选择属性"
#: .\models.py:444
msgid "Values"
msgstr "值"
#: .\models.py:460
msgid "Entity id"
msgstr "实体 ID"
#: .\models.py:466
msgid "Entity uuid"
msgstr "实体 UUID"
#: .\models.py:473
msgid "Entity ct"
msgstr "实体内容类型"
#: .\models.py:501
msgid "Value bool"
msgstr "布尔值"
#: .\models.py:506
msgid "Value CSV"
msgstr "字符分隔值(CSV)"
#: .\models.py:511
msgid "Value date"
msgstr "日期值"
#: .\models.py:516
msgid "Value float"
msgstr "浮点值"
#: .\models.py:521
msgid "Value int"
msgstr "整型值"
#: .\models.py:526
msgid "Value text"
msgstr "文本值"
#: .\models.py:534
msgid "Value JSON"
msgstr "JSON 值"
#: .\models.py:543
msgid "Value enum"
msgstr "枚举值"
#: .\models.py:550
msgid "Generic value id"
msgstr "通用值 ID"
#: .\models.py:559
msgid "Generic value content type"
msgstr "通用值内容类型"
#: .\models.py:657
#, python-format
msgid "%(obj)s has no EAV attribute named %(attr)s"
msgstr "%(obj)s 中不存在为 %(attr)s 的属性"
#: .\models.py:729
msgid "{} EAV field cannot be blank"
msgstr "{} 字段不能为空白(blank)"
#: .\models.py:736
#, python-format
msgid "%(attr)s EAV field %(err)s"
msgstr "%(attr)s 字段错误:%(err)s"
#: .\validators.py:26
msgid "Must be str or unicode"
msgstr "必须是一个 str 或 unicode"
#: .\validators.py:36
msgid "Must be a float"
msgstr "必须是一个浮点数"
#: .\validators.py:46
msgid "Must be an integer"
msgstr "必须是一个整数"
#: .\validators.py:57
msgid "Must be a date or datetime"
msgstr "必须是一个日期(date)或者日期时间(datetime)"
#: .\validators.py:65
msgid "Must be a boolean"
msgstr "必须是一个布尔值"
#: .\validators.py:74
msgid "Must be a django model object instance"
msgstr "必须是一个 Django Model 对象的实例"
#: .\validators.py:77
msgid "Model has not been saved yet"
msgstr "Model 尚未保存"
#: .\validators.py:88
msgid "EnumValue has not been saved yet"
msgstr "枚举值尚未保存"
#: .\validators.py:99 .\validators.py:101
msgid "Must be a JSON Serializable object"
msgstr "必须是一个 JSON 序列化对象"
#: .\validators.py:111
msgid "Must be Comma-Separated-Value."
msgstr "必须是一个字符分隔值(CSV)"

12
eav/logic/entity_pk.py Normal file
View file

@ -0,0 +1,12 @@
from django.db.models.fields import UUIDField
def get_entity_pk_type(entity_cls) -> str:
"""Returns the entity PK type to use.
These values map to `models.Value` as potential fields to use to relate
to the proper entity via the correct PK type.
"""
if isinstance(entity_cls._meta.pk, UUIDField): # noqa: SLF001
return "entity_uuid"
return "entity_id"

97
eav/logic/managers.py Normal file
View file

@ -0,0 +1,97 @@
from django.db import models
class EnumValueManager(models.Manager):
"""
Custom manager for `EnumValue` model.
This manager adds utility methods specific to the `EnumValue` model.
"""
def get_by_natural_key(self, value):
"""
Retrieves an EnumValue instance using its `value` as a natural key.
Args:
value (str): The value of the EnumValue instance.
Returns:
EnumValue: The instance matching the provided value.
"""
return self.get(value=value)
class EnumGroupManager(models.Manager):
"""
Custom manager for `EnumGroup` model.
This manager adds utility methods specific to the `EnumGroup` model.
"""
def get_by_natural_key(self, name):
"""
Retrieves an EnumGroup instance using its `name` as a natural key.
Args:
name (str): The name of the EnumGroup instance.
Returns:
EnumGroup: The instance matching the provided name.
"""
return self.get(name=name)
class AttributeManager(models.Manager):
"""
Custom manager for `Attribute` model.
This manager adds utility methods specific to the `Attribute` model.
"""
def get_by_natural_key(self, name, slug):
"""
Retrieves an Attribute instance using its `name` and `slug` as natural keys.
Args:
name (str): The name of the Attribute instance.
slug (str): The slug of the Attribute instance.
Returns:
Attribute: The instance matching the provided name and slug.
"""
return self.get(name=name, slug=slug)
class ValueManager(models.Manager):
"""
Custom manager for `Value` model.
This manager adds utility methods specific to the `Value` model.
"""
def get_by_natural_key(self, attribute, entity_id, entity_uuid):
"""
Retrieve a Value instance using multiple natural keys.
This method utilizes a combination of an `attribute` (defined by its
name and slug), `entity_id`, and `entity_uuid` to retrieve a unique
Value instance.
Args:
attribute (tuple): A tuple containing the name and slug of the
Attribute instance.
entity_id (int): The ID of the associated entity.
entity_uuid (str): The UUID of the associated entity.
Returns:
Value: The instance matching the provided keys.
"""
from eav.models import Attribute
attribute = Attribute.objects.get(name=attribute[0], slug=attribute[1])
return self.get(
attribute=attribute,
entity_id=entity_id,
entity_uuid=entity_uuid,
)

44
eav/logic/object_pk.py Normal file
View file

@ -0,0 +1,44 @@
import uuid
from functools import partial
from django.conf import settings
from django.db import models
#: Constants
_DEFAULT_CHARFIELD_LEN: int = 40
_FIELD_MAPPING = {
"django.db.models.UUIDField": partial(
models.UUIDField,
primary_key=True,
editable=False,
default=uuid.uuid4,
),
"django.db.models.CharField": partial(
models.CharField,
primary_key=True,
editable=False,
max_length=_DEFAULT_CHARFIELD_LEN,
),
}
def get_pk_format() -> models.Field:
"""
Get the primary key field format based on the Django settings.
This function returns a field factory function that corresponds to the
primary key format specified in Django settings. If the primary key
format is not recognized, it defaults to using BigAutoField.
Returns:
Type[models.Field]: A field factory function that can be used to
create the primary key field instance.
"""
field_factory = _FIELD_MAPPING.get(
settings.EAV2_PRIMARY_KEY_FIELD,
partial(models.BigAutoField, primary_key=True, editable=False),
)
# Create and return the field instance
return field_factory()

61
eav/logic/slug.py Normal file
View file

@ -0,0 +1,61 @@
from __future__ import annotations
import secrets
import string
from typing import Final
from django.utils.text import slugify
SLUGFIELD_MAX_LENGTH: Final = 50
def non_identifier_chars() -> dict[str, str]:
"""Generate a mapping of non-identifier characters to their Unicode representations.
Returns:
dict[str, str]: A dictionary where keys are special characters and values
are their Unicode representations.
"""
# Start with all printable characters
all_chars = string.printable
# Filter out characters that are valid in Python identifiers
special_chars = [
char for char in all_chars if not char.isalnum() and char not in ["_", " "]
]
return {char: f"u{ord(char):04x}" for char in special_chars}
def generate_slug(value: str) -> str:
"""Generate a valid slug based on the given value.
This function converts the input value into a Python-identifier-friendly slug.
It handles special characters, ensures a valid Python identifier, and truncates
the result to fit within the maximum allowed length.
Args:
value (str): The input string to generate a slug from.
Returns:
str: A valid Python identifier slug, with a maximum
length of SLUGFIELD_MAX_LENGTH.
"""
for char, replacement in non_identifier_chars().items():
value = value.replace(char, replacement)
# Use slugify to create a URL-friendly base slug.
slug = slugify(value, allow_unicode=False).replace("-", "_")
# If slugify returns an empty string, generate a fallback
# slug to ensure it's never empty.
if not slug:
chars = string.ascii_lowercase + string.digits
randstr = "".join(secrets.choice(chars) for _ in range(8))
slug = f"rand_{randstr}"
# Ensure the slug doesn't start with a digit to make it a valid Python identifier.
if slug[0].isdigit():
slug = "_" + slug
return slug[:SLUGFIELD_MAX_LENGTH]

View file

@ -1,52 +1,55 @@
'''
Managers.
"""
This module contains the custom manager used by entities registered with eav.
'''
"""
from django.db import models
from .queryset import EavQuerySet
from eav.queryset import EavQuerySet
class EntityManager(models.Manager):
'''
"""
Our custom manager, overrides ``models.Manager``.
'''
"""
_queryset_class = EavQuerySet
def create(self, **kwargs):
'''
"""
Parse eav attributes out of *kwargs*, then try to create and save
the object, then assign and save it's eav attributes.
'''
config_cls = getattr(self.model, '_eav_config_cls', None)
"""
config_cls = getattr(self.model, "_eav_config_cls", None)
if not config_cls or config_cls.manager_only:
return super(EntityManager, self).create(**kwargs)
#attributes = config_cls.get_attributes()
prefix = '%s__' % config_cls.eav_attr
return super().create(**kwargs)
prefix = f"{config_cls.eav_attr}__"
new_kwargs = {}
eav_kwargs = {}
for key, value in kwargs.items():
if key.startswith(prefix):
eav_kwargs.update({key[len(prefix):]: value})
eav_kwargs.update({key[len(prefix) :]: value})
else:
new_kwargs.update({key: value})
obj = self.model(**new_kwargs)
obj_eav = getattr(obj, config_cls.eav_attr)
for key, value in eav_kwargs.items():
setattr(obj_eav, key, value)
obj.save()
return obj
def get_or_create(self, **kwargs):
'''
def get_or_create(self, defaults=None, **kwargs):
"""
Reproduces the behavior of get_or_create, eav friendly.
'''
"""
try:
return self.get(**kwargs), False
except self.model.DoesNotExist:
if defaults:
kwargs = {**kwargs, **defaults}
return self.create(**kwargs), True

View file

@ -1,78 +1,227 @@
# Generated by Django 2.0.4 on 2018-06-01 09:36
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
from django.db import migrations, models
import eav.fields
class Migration(migrations.Migration):
"""Initial migration for the Attribute, EnumGroup, EnumValue, and Value models."""
initial = True
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
("contenttypes", "0002_remove_content_type_name"),
]
operations = [
migrations.CreateModel(
name='Attribute',
name="Attribute",
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='User-friendly attribute name', max_length=100, verbose_name='name')),
('slug', eav.fields.EavSlugField(help_text='Short unique attribute label', unique=True, verbose_name='slug')),
('description', models.CharField(blank=True, help_text='Short description', max_length=256, null=True, verbose_name='description')),
('datatype', eav.fields.EavDatatypeField(choices=[('text', 'Text'), ('float', 'Float'), ('int', 'Integer'), ('date', 'Date'), ('bool', 'True / False'), ('object', 'Django Object'), ('enum', 'Multiple Choice')], max_length=6, verbose_name='data type')),
('created', models.DateTimeField(default=django.utils.timezone.now, editable=False, verbose_name='created')),
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
('required', models.BooleanField(default=False, verbose_name='required')),
('display_order', models.PositiveIntegerField(default=1, verbose_name='display order')),
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"name",
models.CharField(
help_text="User-friendly attribute name",
max_length=100,
verbose_name="Name",
),
),
(
"slug",
models.SlugField(
help_text="Short unique attribute label",
unique=True,
verbose_name="Slug",
),
),
(
"description",
models.CharField(
blank=True,
help_text="Short description",
max_length=256,
null=True,
verbose_name="Description",
),
),
(
"datatype",
eav.fields.EavDatatypeField(
choices=[
("text", "Text"),
("date", "Date"),
("float", "Float"),
("int", "Integer"),
("bool", "True / False"),
("object", "Django Object"),
("enum", "Multiple Choice"),
],
max_length=6,
verbose_name="Data Type",
),
),
(
"created",
models.DateTimeField(
default=django.utils.timezone.now,
editable=False,
verbose_name="Created",
),
),
(
"modified",
models.DateTimeField(auto_now=True, verbose_name="Modified"),
),
(
"required",
models.BooleanField(default=False, verbose_name="Required"),
),
(
"display_order",
models.PositiveIntegerField(
default=1,
verbose_name="Display order",
),
),
],
options={
'ordering': ['name'],
"ordering": ["name"],
},
),
migrations.CreateModel(
name='EnumGroup',
name="EnumGroup",
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100, unique=True, verbose_name='name')),
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"name",
models.CharField(max_length=100, unique=True, verbose_name="Name"),
),
],
),
migrations.CreateModel(
name='EnumValue',
name="EnumValue",
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('value', models.CharField(db_index=True, max_length=50, unique=True, verbose_name='value')),
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"value",
models.CharField(
db_index=True,
max_length=50,
unique=True,
verbose_name="Value",
),
),
],
),
migrations.CreateModel(
name='Value',
name="Value",
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('entity_id', models.IntegerField()),
('value_text', models.TextField(blank=True, null=True)),
('value_float', models.FloatField(blank=True, null=True)),
('value_int', models.IntegerField(blank=True, null=True)),
('value_date', models.DateTimeField(blank=True, null=True)),
('value_bool', models.NullBooleanField()),
('generic_value_id', models.IntegerField(blank=True, null=True)),
('created', models.DateTimeField(default=django.utils.timezone.now, verbose_name='created')),
('modified', models.DateTimeField(auto_now=True, verbose_name='modified')),
('attribute', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='eav.Attribute', verbose_name='attribute')),
('entity_ct', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='value_entities', to='contenttypes.ContentType')),
('generic_value_ct', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='value_values', to='contenttypes.ContentType')),
('value_enum', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='eav_values', to='eav.EnumValue')),
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("entity_id", models.IntegerField()),
("value_text", models.TextField(blank=True, null=True)),
("value_float", models.FloatField(blank=True, null=True)),
("value_int", models.IntegerField(blank=True, null=True)),
("value_date", models.DateTimeField(blank=True, null=True)),
("value_bool", models.NullBooleanField()),
("generic_value_id", models.IntegerField(blank=True, null=True)),
(
"created",
models.DateTimeField(
default=django.utils.timezone.now,
verbose_name="Created",
),
),
(
"modified",
models.DateTimeField(auto_now=True, verbose_name="Modified"),
),
(
"attribute",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
to="eav.Attribute",
verbose_name="Attribute",
),
),
(
"entity_ct",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
related_name="value_entities",
to="contenttypes.ContentType",
),
),
(
"generic_value_ct",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.PROTECT,
related_name="value_values",
to="contenttypes.ContentType",
),
),
(
"value_enum",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.PROTECT,
related_name="eav_values",
to="eav.EnumValue",
),
),
],
),
migrations.AddField(
model_name='enumgroup',
name='enums',
field=models.ManyToManyField(to='eav.EnumValue', verbose_name='enum group'),
model_name="enumgroup",
name="values",
field=models.ManyToManyField(to="eav.EnumValue", verbose_name="Enum group"),
),
migrations.AddField(
model_name='attribute',
name='enum_group',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='eav.EnumGroup', verbose_name='choice group'),
model_name="attribute",
name="enum_group",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.PROTECT,
to="eav.EnumGroup",
verbose_name="Choice Group",
),
),
]

View file

@ -0,0 +1,18 @@
from django.db import migrations, models
class Migration(migrations.Migration):
"""Add entity_ct field to Attribute model."""
dependencies = [
("contenttypes", "0002_remove_content_type_name"),
("eav", "0001_initial"),
]
operations = [
migrations.AddField(
model_name="attribute",
name="entity_ct",
field=models.ManyToManyField(blank=True, to="contenttypes.ContentType"),
),
]

View file

@ -0,0 +1,44 @@
# Generated by Django 3.1.6 on 2021-04-04 22:09
import django.core.serializers.json
from django.db import migrations
from django.db.models import JSONField
import eav.fields
class Migration(migrations.Migration):
dependencies = [
("eav", "0002_add_entity_ct_field"),
]
operations = [
migrations.AddField(
model_name="value",
name="value_json",
field=JSONField(
blank=True,
default=dict,
encoder=django.core.serializers.json.DjangoJSONEncoder,
null=True,
),
),
migrations.AlterField(
model_name="attribute",
name="datatype",
field=eav.fields.EavDatatypeField(
choices=[
("text", "Text"),
("date", "Date"),
("float", "Float"),
("int", "Integer"),
("bool", "True / False"),
("object", "Django Object"),
("enum", "Multiple Choice"),
("json", "JSON Object"),
],
max_length=6,
verbose_name="Data Type",
),
),
]

View file

@ -0,0 +1,17 @@
# Generated by Django 3.2 on 2021-04-23 19:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("eav", "0003_auto_20210404_2209"),
]
operations = [
migrations.AlterField(
model_name="value",
name="value_bool",
field=models.BooleanField(blank=True, null=True),
),
]

View file

@ -0,0 +1,38 @@
# Generated by Django 3.2 on 2021-05-10 13:05
from django.db import migrations
import eav.fields
class Migration(migrations.Migration):
dependencies = [
("eav", "0004_alter_value_value_bool"),
]
operations = [
migrations.AddField(
model_name="value",
name="value_csv",
field=eav.fields.CSVField(blank=True, default="", null=True),
),
migrations.AlterField(
model_name="attribute",
name="datatype",
field=eav.fields.EavDatatypeField(
choices=[
("text", "Text"),
("date", "Date"),
("float", "Float"),
("int", "Integer"),
("bool", "True / False"),
("object", "Django Object"),
("enum", "Multiple Choice"),
("json", "JSON Object"),
("csv", "Comma-Separated-Value"),
],
max_length=6,
verbose_name="Data Type",
),
),
]

View file

@ -0,0 +1,22 @@
from django.db import migrations, models
class Migration(migrations.Migration):
"""Creates UUID field to map to Entity FK."""
dependencies = [
("eav", "0005_auto_20210510_1305"),
]
operations = [
migrations.AddField(
model_name="value",
name="entity_uuid",
field=models.UUIDField(blank=True, null=True),
),
migrations.AlterField(
model_name="value",
name="entity_id",
field=models.IntegerField(blank=True, null=True),
),
]

View file

@ -0,0 +1,17 @@
from django.db import migrations, models
class Migration(migrations.Migration):
"""Convert Value.value_int to BigInteger."""
dependencies = [
("eav", "0006_add_entity_uuid"),
]
operations = [
migrations.AlterField(
model_name="value",
name="value_int",
field=models.BigIntegerField(blank=True, null=True),
),
]

View file

@ -0,0 +1,21 @@
from django.db import migrations, models
class Migration(migrations.Migration):
"""Use Django SlugField() for Attribute.slug."""
dependencies = [
("eav", "0007_alter_value_value_int"),
]
operations = [
migrations.AlterField(
model_name="attribute",
name="slug",
field=models.SlugField(
help_text="Short unique attribute label",
unique=True,
verbose_name="Slug",
),
),
]

View file

@ -0,0 +1,178 @@
from django.core.serializers.json import DjangoJSONEncoder
from django.db import migrations, models
from eav.fields import CSVField
class Migration(migrations.Migration):
"""Define verbose naming for models and fields."""
dependencies = [
("contenttypes", "0002_remove_content_type_name"),
("eav", "0008_use_native_slugfield"),
]
operations = [
migrations.AlterModelOptions(
name="attribute",
options={
"ordering": ["name"],
"verbose_name": "Attribute",
"verbose_name_plural": "Attributes",
},
),
migrations.AlterModelOptions(
name="enumgroup",
options={
"verbose_name": "EnumGroup",
"verbose_name_plural": "EnumGroups",
},
),
migrations.AlterModelOptions(
name="enumvalue",
options={
"verbose_name": "EnumValue",
"verbose_name_plural": "EnumValues",
},
),
migrations.AlterModelOptions(
name="value",
options={"verbose_name": "Value", "verbose_name_plural": "Values"},
),
migrations.AlterField(
model_name="attribute",
name="entity_ct",
field=models.ManyToManyField(
blank=True,
to="contenttypes.contenttype",
verbose_name="Entity content type",
),
),
migrations.AlterField(
model_name="value",
name="entity_ct",
field=models.ForeignKey(
on_delete=models.deletion.PROTECT,
related_name="value_entities",
to="contenttypes.contenttype",
verbose_name="Entity ct",
),
),
migrations.AlterField(
model_name="value",
name="entity_id",
field=models.IntegerField(
blank=True,
null=True,
verbose_name="Entity id",
),
),
migrations.AlterField(
model_name="value",
name="entity_uuid",
field=models.UUIDField(
blank=True,
null=True,
verbose_name="Entity uuid",
),
),
migrations.AlterField(
model_name="value",
name="generic_value_ct",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=models.deletion.PROTECT,
related_name="value_values",
to="contenttypes.contenttype",
verbose_name="Generic value content type",
),
),
migrations.AlterField(
model_name="value",
name="generic_value_id",
field=models.IntegerField(
blank=True,
null=True,
verbose_name="Generic value id",
),
),
migrations.AlterField(
model_name="value",
name="value_bool",
field=models.BooleanField(
blank=True,
null=True,
verbose_name="Value bool",
),
),
migrations.AlterField(
model_name="value",
name="value_csv",
field=CSVField(
blank=True,
default="",
null=True,
verbose_name="Value CSV",
),
),
migrations.AlterField(
model_name="value",
name="value_date",
field=models.DateTimeField(
blank=True,
null=True,
verbose_name="Value date",
),
),
migrations.AlterField(
model_name="value",
name="value_enum",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=models.deletion.PROTECT,
related_name="eav_values",
to="eav.enumvalue",
verbose_name="Value enum",
),
),
migrations.AlterField(
model_name="value",
name="value_float",
field=models.FloatField(
blank=True,
null=True,
verbose_name="Value float",
),
),
migrations.AlterField(
model_name="value",
name="value_int",
field=models.BigIntegerField(
blank=True,
null=True,
verbose_name="Value int",
),
),
migrations.AlterField(
model_name="value",
name="value_json",
field=models.JSONField(
blank=True,
default=dict,
encoder=DjangoJSONEncoder,
null=True,
verbose_name="Value JSON",
),
),
migrations.AlterField(
model_name="value",
name="value_text",
field=models.TextField(
blank=True,
null=True,
verbose_name="Value text",
),
),
]

View file

@ -0,0 +1,48 @@
from django.db import migrations, models
class Migration(migrations.Migration):
"""Migration to use BigAutoField as default for all models."""
dependencies = [
("eav", "0009_enchance_naming"),
]
operations = [
migrations.AlterField(
model_name="attribute",
name="id",
field=models.BigAutoField(
editable=False,
primary_key=True,
serialize=False,
),
),
migrations.AlterField(
model_name="enumgroup",
name="id",
field=models.BigAutoField(
editable=False,
primary_key=True,
serialize=False,
),
),
migrations.AlterField(
model_name="enumvalue",
name="id",
field=models.BigAutoField(
editable=False,
primary_key=True,
serialize=False,
),
),
migrations.AlterField(
model_name="value",
name="id",
field=models.BigAutoField(
editable=False,
primary_key=True,
serialize=False,
),
),
]

View file

@ -0,0 +1,36 @@
from django.db import migrations, models
class Migration(migrations.Migration):
"""Update default values and meta options for Attribute and Value models."""
dependencies = [
("eav", "0010_dynamic_pk_type_for_models"),
]
operations = [
migrations.AlterModelOptions(
name="attribute",
options={
"ordering": ("name",),
"verbose_name": "Attribute",
"verbose_name_plural": "Attributes",
},
),
migrations.AlterField(
model_name="attribute",
name="description",
field=models.CharField(
blank=True,
default="",
help_text="Short description",
max_length=256,
verbose_name="Description",
),
),
migrations.AlterField(
model_name="value",
name="value_text",
field=models.TextField(blank=True, default="", verbose_name="Value text"),
),
]

View file

@ -0,0 +1,54 @@
from django.db import migrations, models
class Migration(migrations.Migration):
"""
Add uniqueness and integrity constraints to the Value model.
This migration adds database-level constraints to ensure:
1. Each entity (identified by UUID) can have only one value per attribute
2. Each entity (identified by integer ID) can have only one value per attribute
3. Each value must use either entity_id OR entity_uuid, never both or neither
These constraints ensure data integrity by preventing duplicate attribute values
for the same entity and enforcing the XOR relationship between the two types of
entity identification (integer ID vs UUID).
"""
dependencies = [
("eav", "0011_update_defaults_and_meta"),
]
operations = [
migrations.AddConstraint(
model_name="value",
constraint=models.UniqueConstraint(
fields=("entity_ct", "attribute", "entity_uuid"),
name="unique_entity_uuid_per_attribute",
),
),
migrations.AddConstraint(
model_name="value",
constraint=models.UniqueConstraint(
fields=("entity_ct", "attribute", "entity_id"),
name="unique_entity_id_per_attribute",
),
),
migrations.AddConstraint(
model_name="value",
constraint=models.CheckConstraint(
check=models.Q(
models.Q(
("entity_id__isnull", False),
("entity_uuid__isnull", True),
),
models.Q(
("entity_id__isnull", True),
("entity_uuid__isnull", False),
),
_connector="OR",
),
name="ensure_entity_id_xor_entity_uuid",
),
),
]

View file

@ -1,618 +0,0 @@
'''
Models.
This module defines the four concrete, non-abstract models:
* :class:`Value`
* :class:`Attribute`
* :class:`EnumValue`
* :class:`EnumGroup`
Along with the :class:`Entity` helper class.
'''
from copy import copy
from django.contrib.contenttypes import fields as generic
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from .exceptions import IllegalAssignmentException
from .fields import EavDatatypeField, EavSlugField
from .validators import *
class EnumValue(models.Model):
'''
*EnumValue* objects are the value 'choices' to multiple choice
*TYPE_ENUM* :class:`Attribute` objects.
They have only one field, *value*, a ``CharField`` that must be unique.
For example::
yes = EnumValue.objects.create(value='Yes') # doctest: SKIP
no = EnumValue.objects.create(value='No')
unknown = EnumValue.objects.create(value='Unknown')
ynu = EnumGroup.objects.create(name='Yes / No / Unknown')
ynu.enums.add(yes, no, unknown)
Attribute.objects.create(name='has fever?', datatype=Attribute.TYPE_ENUM, enum_group=ynu)
# = <Attribute: has fever? (Multiple Choice)>
.. note::
The same *EnumValue* objects should be reused within multiple
*EnumGroups*. For example, if you have one *EnumGroup*
called: *Yes / No / Unknown* and another called *Yes / No /
Not applicable*, you should only have a total of four *EnumValues*
objects, as you should have used the same *Yes* and *No* *EnumValues*
for both *EnumGroups*.
'''
value = models.CharField(_('value'), db_index=True, unique=True, max_length=50)
def __str__(self):
return '<EnumValue {}>'.format(self.value)
class EnumGroup(models.Model):
'''
*EnumGroup* objects have two fields - a *name* ``CharField`` and *enums*,
a ``ManyToManyField`` to :class:`EnumValue`. :class:`Attribute` classes
with datatype *TYPE_ENUM* have a ``ForeignKey`` field to *EnumGroup*.
See :class:`EnumValue` for an example.
'''
name = models.CharField(_('name'), unique = True, max_length = 100)
enums = models.ManyToManyField(EnumValue, verbose_name = _('enum group'))
def __str__(self):
return '<EnumGroup {}>'.format(self.name)
class Attribute(models.Model):
'''
Putting the **A** in *EAV*. This holds the attributes, or concepts.
Examples of possible *Attributes*: color, height, weight,
number of children, number of patients, has fever?, etc...
Each attribute has a name, and a description, along with a slug that must
be unique. If you don't provide a slug, a default slug (derived from
name), will be created.
The *required* field is a boolean that indicates whether this EAV attribute
is required for entities to which it applies. It defaults to *False*.
.. warning::
Just like a normal model field that is required, you will not be able
to save or create any entity object for which this attribute applies,
without first setting this EAV attribute.
There are 7 possible values for datatype:
* int (TYPE_INT)
* float (TYPE_FLOAT)
* text (TYPE_TEXT)
* date (TYPE_DATE)
* bool (TYPE_BOOLEAN)
* object (TYPE_OBJECT)
* enum (TYPE_ENUM)
Examples::
Attribute.objects.create(name='Height', datatype=Attribute.TYPE_INT)
# = <Attribute: Height (Integer)>
Attribute.objects.create(name='Color', datatype=Attribute.TYPE_TEXT)
# = <Attribute: Color (Text)>
yes = EnumValue.objects.create(value='yes')
no = EnumValue.objects.create(value='no')
unknown = EnumValue.objects.create(value='unknown')
ynu = EnumGroup.objects.create(name='Yes / No / Unknown')
ynu.enums.add(yes, no, unknown)
Attribute.objects.create(name='has fever?', datatype=Attribute.TYPE_ENUM, enum_group=ynu)
# = <Attribute: has fever? (Multiple Choice)>
.. warning:: Once an Attribute has been used by an entity, you can not
change it's datatype.
'''
class Meta:
ordering = ['name']
TYPE_TEXT = 'text'
TYPE_FLOAT = 'float'
TYPE_INT = 'int'
TYPE_DATE = 'date'
TYPE_BOOLEAN = 'bool'
TYPE_OBJECT = 'object'
TYPE_ENUM = 'enum'
DATATYPE_CHOICES = (
(TYPE_TEXT, _('Text')),
(TYPE_DATE, _('Date')),
(TYPE_FLOAT, _('Float')),
(TYPE_INT, _('Integer')),
(TYPE_BOOLEAN, _('True / False')),
(TYPE_OBJECT, _('Django Object')),
(TYPE_ENUM, _('Multiple Choice')),
)
# Core attributes
datatype = EavDatatypeField(
verbose_name = _('Data Type'),
choices = DATATYPE_CHOICES,
max_length = 6
)
name = models.CharField(
verbose_name = _('Name'),
max_length = 100,
help_text = _('User-friendly attribute name')
)
'''
Main identifer for the attribute.
Upon creation, slug is autogenerated from the name.
(see :meth:`~eav.fields.EavSlugField.create_slug_from_name`).
'''
slug = EavSlugField(
verbose_name = _('Slug'),
max_length = 50,
db_index = True,
unique = True,
help_text = _('Short unique attribute label')
)
'''
.. warning::
This attribute should be used with caution. Setting this to *True*
means that *all* entities that *can* have this attribute will
be required to have a value for it.
'''
required = models.BooleanField(verbose_name = _('Required'), default = False)
enum_group = models.ForeignKey(
EnumGroup,
verbose_name = _('Choice Group'),
on_delete = models.PROTECT,
blank = True,
null = True
)
description = models.CharField(
verbose_name = _('Description'),
max_length = 256,
blank = True,
null = True,
help_text = _('Short description')
)
# Useful meta-information
display_order = models.PositiveIntegerField(
verbose_name = _('Display order'),
default = 1
)
modified = models.DateTimeField(
verbose_name = _('Modified'),
auto_now = True
)
created = models.DateTimeField(
verbose_name = _('Created'),
default = timezone.now,
editable = False
)
@property
def help_text(self):
return self.description
def get_validators(self):
'''
Returns the appropriate validator function from :mod:`~eav.validators`
as a list (of length one) for the datatype.
.. note::
The reason it returns it as a list, is eventually we may want this
method to look elsewhere for additional attribute specific
validators to return as well as the default, built-in one.
'''
DATATYPE_VALIDATORS = {
'text': validate_text,
'float': validate_float,
'int': validate_int,
'date': validate_date,
'bool': validate_bool,
'object': validate_object,
'enum': validate_enum,
}
return [DATATYPE_VALIDATORS[self.datatype]]
def validate_value(self, value):
'''
Check *value* against the validators returned by
:meth:`get_validators` for this attribute.
'''
for validator in self.get_validators():
validator(value)
if self.datatype == self.TYPE_ENUM:
if value not in self.enum_group.enums.all():
raise ValidationError(
_('%(val)s is not a valid choice for %(attr)s')
% dict(val = value, attr = self)
)
def save(self, *args, **kwargs):
'''
Saves the Attribute and auto-generates a slug field
if one wasn't provided.
'''
if not self.slug:
self.slug = EavSlugField.create_slug_from_name(self.name)
self.full_clean()
super(Attribute, self).save(*args, **kwargs)
def clean(self):
'''
Validates the attribute. Will raise ``ValidationError`` if
the attribute's datatype is *TYPE_ENUM* and enum_group is not set,
or if the attribute is not *TYPE_ENUM* and the enum group is set.
'''
if self.datatype == self.TYPE_ENUM and not self.enum_group:
raise ValidationError(
_('You must set the choice group for multiple choice attributes')
)
if self.datatype != self.TYPE_ENUM and self.enum_group:
raise ValidationError(
_('You can only assign a choice group to multiple choice attributes')
)
def get_choices(self):
'''
Returns a query set of :class:`EnumValue` objects for this attribute.
Returns None if the datatype of this attribute is not *TYPE_ENUM*.
'''
return self.enum_group.enums.all() if self.datatype == Attribute.TYPE_ENUM else None
def save_value(self, entity, value):
'''
Called with *entity*, any Django object registered with eav, and
*value*, the :class:`Value` this attribute for *entity* should
be set to.
If a :class:`Value` object for this *entity* and attribute doesn't
exist, one will be created.
.. note::
If *value* is None and a :class:`Value` object exists for this
Attribute and *entity*, it will delete that :class:`Value` object.
'''
ct = ContentType.objects.get_for_model(entity)
try:
value_obj = self.value_set.get(
entity_ct = ct,
entity_id = entity.pk,
attribute = self
)
except Value.DoesNotExist:
if value == None or value == '':
return
value_obj = Value.objects.create(
entity_ct = ct,
entity_id = entity.pk,
attribute = self
)
if value == None or value == '':
value_obj.delete()
return
if value != value_obj.value:
value_obj.value = value
value_obj.save()
def __str__(self):
return '{} ({})'.format(self.name, self.get_datatype_display())
class Value(models.Model):
'''
Putting the **V** in *EAV*. This model stores the value for one particular
:class:`Attribute` for some entity.
As with most EAV implementations, most of the columns of this model will
be blank, as onle one *value_* field will be used.
Example::
import eav
from django.contrib.auth.models import User
eav.register(User)
u = User.objects.create(username='crazy_dev_user')
a = Attribute.objects.create(name='Fav Drink', datatype='text')
Value.objects.create(entity = u, attribute = a, value_text = 'red bull')
# = <Value: crazy_dev_user - Fav Drink: "red bull">
'''
entity_ct = models.ForeignKey(
ContentType,
on_delete = models.PROTECT,
related_name = 'value_entities'
)
entity_id = models.IntegerField()
entity = generic.GenericForeignKey(ct_field = 'entity_ct', fk_field = 'entity_id')
value_text = models.TextField(blank = True, null = True)
value_float = models.FloatField(blank = True, null = True)
value_int = models.IntegerField(blank = True, null = True)
value_date = models.DateTimeField(blank = True, null = True)
value_bool = models.NullBooleanField(blank = True, null = True)
value_enum = models.ForeignKey(
EnumValue,
blank = True,
null = True,
on_delete = models.PROTECT,
related_name = 'eav_values'
)
generic_value_id = models.IntegerField(blank=True, null=True)
generic_value_ct = models.ForeignKey(
ContentType,
blank = True,
null = True,
on_delete = models.PROTECT,
related_name ='value_values'
)
value_object = generic.GenericForeignKey(
ct_field = 'generic_value_ct',
fk_field = 'generic_value_id'
)
created = models.DateTimeField(_('Created'), default = timezone.now)
modified = models.DateTimeField(_('Modified'), auto_now = True)
attribute = models.ForeignKey(
Attribute,
db_index = True,
on_delete = models.PROTECT,
verbose_name = _('attribute')
)
def save(self, *args, **kwargs):
'''
Validate and save this value.
'''
self.full_clean()
super(Value, self).save(*args, **kwargs)
def clean(self):
'''
Raises ``ValidationError`` if this value's attribute is *TYPE_ENUM*
and value_enum is not a valid choice for this value's attribute.
'''
if self.attribute.datatype == Attribute.TYPE_ENUM and self.value_enum:
if self.value_enum not in self.attribute.enum_group.enums.all():
raise ValidationError(
_('%(enum)s is not a valid choice for %(attr)s')
% dict(enum = self.value_enum, attr = self.attribute)
)
def _get_value(self):
'''
Return the python object this value is holding
'''
return getattr(self, 'value_%s' % self.attribute.datatype)
def _set_value(self, new_value):
'''
Set the object this value is holding
'''
setattr(self, 'value_%s' % self.attribute.datatype, new_value)
value = property(_get_value, _set_value)
def __str__(self):
return '{}: "{}" ({})'.format(self.attribute.name, self.value, self.entity)
def __repr__(self):
return '{}: "{}" ({})'.format(self.attribute.name, self.value, self.entity.pk)
class Entity(object):
'''
The helper class that will be attached to any entity
registered with eav.
'''
@staticmethod
def pre_save_handler(sender, *args, **kwargs):
'''
Pre save handler attached to self.instance. Called before the
model instance we are attached to is saved. This allows us to call
:meth:`validate_attributes` before the entity is saved.
'''
instance = kwargs['instance']
entity = getattr(kwargs['instance'], instance._eav_config_cls.eav_attr)
entity.validate_attributes()
@staticmethod
def post_save_handler(sender, *args, **kwargs):
'''
Post save handler attached to self.instance. Calls :meth:`save` when
the model instance we are attached to is saved.
'''
instance = kwargs['instance']
entity = getattr(instance, instance._eav_config_cls.eav_attr)
entity.save()
def __init__(self, instance):
'''
Set self.instance equal to the instance of the model that we're attached
to. Also, store the content type of that instance.
'''
self.instance = instance
self.ct = ContentType.objects.get_for_model(instance)
def __getattr__(self, name):
'''
Tha magic getattr helper. This is called whenever user invokes::
instance.<attribute>
Checks if *name* is a valid slug for attributes available to this
instances. If it is, tries to lookup the :class:`Value` with that
attribute slug. If there is one, it returns the value of the
class:`Value` object, otherwise it hasn't been set, so it returns
None.
'''
if not name.startswith('_'):
try:
attribute = self.get_attribute_by_slug(name)
except Attribute.DoesNotExist:
raise AttributeError(
_('%(obj)s has no EAV attribute named %(attr)s')
% dict(obj = self.instance, attr = name)
)
try:
return self.get_value_by_attribute(attribute).value
except Value.DoesNotExist:
return None
return getattr(super(Entity, self), name)
def get_all_attributes(self):
'''
Return a query set of all :class:`Attribute` objects that can be set
for this entity.
'''
return self.instance._eav_config_cls.get_attributes().order_by('display_order')
def _hasattr(self, attribute_slug):
'''
Since we override __getattr__ with a backdown to the database, this
exists as a way of checking whether a user has set a real attribute on
ourselves, without going to the db if not.
'''
return attribute_slug in self.__dict__
def _getattr(self, attribute_slug):
'''
Since we override __getattr__ with a backdown to the database, this
exists as a way of getting the value a user set for one of our
attributes, without going to the db to check.
'''
return self.__dict__[attribute_slug]
def save(self):
'''
Saves all the EAV values that have been set on this entity.
'''
for attribute in self.get_all_attributes():
if self._hasattr(attribute.slug):
attribute_value = self._getattr(attribute.slug)
attribute.save_value(self.instance, attribute_value)
def validate_attributes(self):
'''
Called before :meth:`save`, first validate all the entity values to
make sure they can be created / saved cleanly.
Raises ``ValidationError`` if they can't be.
'''
values_dict = self.get_values_dict()
for attribute in self.get_all_attributes():
value = None
# Value was assigned to this instance.
if self._hasattr(attribute.slug):
value = self._getattr(attribute.slug)
values_dict.pop(attribute.slug, None)
# Otherwise try pre-loaded from DB.
else:
value = values_dict.pop(attribute.slug, None)
if value is None:
if attribute.required:
raise ValidationError(
_('{} EAV field cannot be blank'.format(attribute.slug))
)
else:
try:
attribute.validate_value(value)
except ValidationError as e:
raise ValidationError(
_('%(attr)s EAV field %(err)s')
% dict(attr = attribute.slug, err = e)
)
illegal = values_dict or (
self.get_object_attributes() - self.get_all_attribute_slugs())
if illegal:
raise IllegalAssignmentException(
'Instance of the class {} cannot have values for attributes: {}.'
.format(self.instance.__class__, ', '.join(illegal))
)
def get_values_dict(self):
return {v.attribute.slug: v.value for v in self.get_values()}
def get_values(self):
'''
Get all set :class:`Value` objects for self.instance
'''
return Value.objects.filter(
entity_ct = self.ct,
entity_id = self.instance.pk
).select_related()
def get_all_attribute_slugs(self):
'''
Returns a list of slugs for all attributes available to this entity.
'''
return set(self.get_all_attributes().values_list('slug', flat=True))
def get_attribute_by_slug(self, slug):
'''
Returns a single :class:`Attribute` with *slug*.
'''
return self.get_all_attributes().get(slug=slug)
def get_value_by_attribute(self, attribute):
'''
Returns a single :class:`Value` for *attribute*.
'''
return self.get_values().get(attribute=attribute)
def get_object_attributes(self):
'''
Returns entity instance attributes, except for
``instance`` and ``ct`` which are used internally.
'''
return set(copy(self.__dict__).keys()) - set(['instance', 'ct'])
def __iter__(self):
'''
Iterate over set eav values. This would allow you to do::
for i in m.eav: print(i)
'''
return iter(self.get_values())

25
eav/models/__init__.py Normal file
View file

@ -0,0 +1,25 @@
"""
This module defines the four concrete, non-abstract models:
* :class:`Value`
* :class:`Attribute`
* :class:`EnumValue`
* :class:`EnumGroup`.
Along with the :class:`Entity` helper class and :class:`EAVModelMeta`
optional metaclass for each eav model class.
"""
from .attribute import Attribute
from .entity import EAVModelMeta, Entity
from .enum_group import EnumGroup
from .enum_value import EnumValue
from .value import Value
__all__ = [
"Attribute",
"EAVModelMeta",
"Entity",
"EnumGroup",
"EnumValue",
"Value",
]

367
eav/models/attribute.py Normal file
View file

@ -0,0 +1,367 @@
# ruff: noqa: UP007
from __future__ import annotations
import warnings
from typing import TYPE_CHECKING, Optional
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db import models
from django.db.models import ForeignKey
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from eav.fields import EavDatatypeField
from eav.logic.entity_pk import get_entity_pk_type
from eav.logic.managers import AttributeManager
from eav.logic.object_pk import get_pk_format
from eav.logic.slug import SLUGFIELD_MAX_LENGTH, generate_slug
from eav.settings import CHARFIELD_LENGTH
from eav.validators import (
validate_bool,
validate_csv,
validate_date,
validate_enum,
validate_float,
validate_int,
validate_json,
validate_object,
validate_text,
)
from .enum_value import EnumValue
from .value import Value
if TYPE_CHECKING:
from .enum_group import EnumGroup
class Attribute(models.Model):
"""
Putting the **A** in *EAV*. This holds the attributes, or concepts.
Examples of possible *Attributes*: color, height, weight, number of
children, number of patients, has fever?, etc...
Each attribute has a name, and a description, along with a slug that must
be unique. If you don't provide a slug, a default slug (derived from
name), will be created.
The *required* field is a boolean that indicates whether this EAV attribute
is required for entities to which it applies. It defaults to *False*.
.. warning::
Just like a normal model field that is required, you will not be able
to save or create any entity object for which this attribute applies,
without first setting this EAV attribute.
There are 7 possible values for datatype:
* int (TYPE_INT)
* float (TYPE_FLOAT)
* text (TYPE_TEXT)
* date (TYPE_DATE)
* bool (TYPE_BOOLEAN)
* object (TYPE_OBJECT)
* enum (TYPE_ENUM)
* json (TYPE_JSON)
* csv (TYPE_CSV)
Examples::
Attribute.objects.create(name='Height', datatype=Attribute.TYPE_INT)
# = <Attribute: Height (Integer)>
Attribute.objects.create(name='Color', datatype=Attribute.TYPE_TEXT)
# = <Attribute: Color (Text)>
yes = EnumValue.objects.create(value='yes')
no = EnumValue.objects.create(value='no')
unknown = EnumValue.objects.create(value='unknown')
ynu = EnumGroup.objects.create(name='Yes / No / Unknown')
ynu.values.add(yes, no, unknown)
Attribute.objects.create(name='has fever?',
datatype=Attribute.TYPE_ENUM,
enum_group=ynu
)
# = <Attribute: has fever? (Multiple Choice)>
.. warning:: Once an Attribute has been used by an entity, you can not
change it's datatype.
"""
TYPE_TEXT = "text"
TYPE_FLOAT = "float"
TYPE_INT = "int"
TYPE_DATE = "date"
TYPE_BOOLEAN = "bool"
TYPE_OBJECT = "object"
TYPE_ENUM = "enum"
TYPE_JSON = "json"
TYPE_CSV = "csv"
DATATYPE_CHOICES = (
(TYPE_TEXT, _("Text")),
(TYPE_DATE, _("Date")),
(TYPE_FLOAT, _("Float")),
(TYPE_INT, _("Integer")),
(TYPE_BOOLEAN, _("True / False")),
(TYPE_OBJECT, _("Django Object")),
(TYPE_ENUM, _("Multiple Choice")),
(TYPE_JSON, _("JSON Object")),
(TYPE_CSV, _("Comma-Separated-Value")),
)
# Core attributes
id = get_pk_format()
datatype = EavDatatypeField(
choices=DATATYPE_CHOICES,
max_length=6,
verbose_name=_("Data Type"),
)
name = models.CharField(
max_length=CHARFIELD_LENGTH,
help_text=_("User-friendly attribute name"),
verbose_name=_("Name"),
)
"""
Main identifier for the attribute.
Upon creation, slug is autogenerated from the name.
(see :meth:`~eav.fields.EavSlugField.create_slug_from_name`).
"""
slug = models.SlugField(
max_length=SLUGFIELD_MAX_LENGTH,
db_index=True,
unique=True,
help_text=_("Short unique attribute label"),
verbose_name=_("Slug"),
)
"""
.. warning::
This attribute should be used with caution. Setting this to *True*
means that *all* entities that *can* have this attribute will
be required to have a value for it.
"""
required = models.BooleanField(
default=False,
verbose_name=_("Required"),
)
entity_ct = models.ManyToManyField(
ContentType,
blank=True,
verbose_name=_("Entity content type"),
)
"""
This field allows you to specify a relationship with any number of content types.
This would be useful, for example, if you wanted an attribute to apply only to
a subset of entities. In that case, you could filter by content type in the
:meth:`~eav.registry.EavConfig.get_attributes` method of that entity's config.
"""
enum_group: ForeignKey[Optional[EnumGroup]] = ForeignKey(
"eav.EnumGroup",
on_delete=models.PROTECT,
blank=True,
null=True,
verbose_name=_("Choice Group"),
)
description = models.CharField(
max_length=256,
blank=True,
default="",
help_text=_("Short description"),
verbose_name=_("Description"),
)
# Useful meta-information
display_order = models.PositiveIntegerField(
default=1,
verbose_name=_("Display order"),
)
modified = models.DateTimeField(
auto_now=True,
verbose_name=_("Modified"),
)
created = models.DateTimeField(
default=timezone.now,
editable=False,
verbose_name=_("Created"),
)
objects = AttributeManager()
class Meta:
ordering = ("name",)
verbose_name = _("Attribute")
verbose_name_plural = _("Attributes")
def __str__(self) -> str:
return f"{self.name} ({self.get_datatype_display()})"
def save(self, *args, **kwargs):
"""
Saves the Attribute and auto-generates a slug field
if one wasn't provided.
"""
if not self.slug:
self.slug = generate_slug(self.name)
self.full_clean()
super().save(*args, **kwargs)
def natural_key(self) -> tuple[str, str]:
"""
Retrieve the natural key for the Attribute instance.
The natural key for an Attribute is defined by its `name` and `slug`. This
method returns a tuple containing these two attributes of the instance.
Returns
-------
tuple: A tuple containing the name and slug of the Attribute instance.
"""
return (
self.name,
self.slug,
)
@property
def help_text(self):
return self.description
def get_validators(self):
"""
Returns the appropriate validator function from :mod:`~eav.validators`
as a list (of length one) for the datatype.
.. note::
The reason it returns it as a list, is eventually we may want this
method to look elsewhere for additional attribute specific
validators to return as well as the default, built-in one.
"""
datatype_validators = {
"text": validate_text,
"float": validate_float,
"int": validate_int,
"date": validate_date,
"bool": validate_bool,
"object": validate_object,
"enum": validate_enum,
"json": validate_json,
"csv": validate_csv,
}
return [datatype_validators[self.datatype]]
def validate_value(self, value):
"""
Check *value* against the validators returned by
:meth:`get_validators` for this attribute.
"""
for validator in self.get_validators():
validator(value)
if self.datatype == self.TYPE_ENUM:
if isinstance(value, EnumValue):
value = value.value
if not self.enum_group.values.filter(value=value).exists():
raise ValidationError(
_("%(val)s is not a valid choice for %(attr)s")
% {"val": value, "attr": self},
)
def clean(self):
"""
Validates the attribute. Will raise ``ValidationError`` if the
attribute's datatype is *TYPE_ENUM* and enum_group is not set, or if
the attribute is not *TYPE_ENUM* and the enum group is set.
"""
if self.datatype == self.TYPE_ENUM and not self.enum_group:
raise ValidationError(
_("You must set the choice group for multiple choice attributes"),
)
if self.datatype != self.TYPE_ENUM and self.enum_group:
raise ValidationError(
_("You can only assign a choice group to multiple choice attributes"),
)
def clean_fields(self, exclude=None):
"""Perform field-specific validation on the model's fields.
This method extends the default field cleaning process to include
custom validation for the slug field.
Args:
exclude (list): Fields to exclude from cleaning.
Raises:
ValidationError: If the slug is not a valid Python identifier.
"""
super().clean_fields(exclude=exclude)
if not self.slug.isidentifier():
warnings.warn(
f"Slug '{self.slug}' is not a valid Python identifier. "
+ "Consider updating it.",
stacklevel=3,
)
def get_choices(self):
"""
Returns a query set of :class:`EnumValue` objects for this attribute.
Returns None if the datatype of this attribute is not *TYPE_ENUM*.
"""
return (
self.enum_group.values.all()
if self.datatype == Attribute.TYPE_ENUM
else None
)
def save_value(self, entity, value):
"""
Called with *entity*, any Django object registered with eav, and
*value*, the :class:`Value` this attribute for *entity* should
be set to.
If a :class:`Value` object for this *entity* and attribute doesn't
exist, one will be created.
.. note::
If *value* is None and a :class:`Value` object exists for this
Attribute and *entity*, it will delete that :class:`Value` object.
"""
ct = ContentType.objects.get_for_model(entity)
entity_filter = {
"entity_ct": ct,
"attribute": self,
f"{get_entity_pk_type(entity)}": entity.pk,
}
try:
value_obj = self.value_set.get(**entity_filter)
except Value.DoesNotExist:
if value is None or value == "":
return
value_obj = Value.objects.create(**entity_filter)
if value is None or value == "":
value_obj.delete()
return
if value != value_obj.value:
value_obj.value = value
value_obj.save()

208
eav/models/entity.py Normal file
View file

@ -0,0 +1,208 @@
from copy import copy
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db.models.base import ModelBase
from django.utils.translation import gettext_lazy as _
from eav import register
from eav.exceptions import IllegalAssignmentException
from eav.logic.entity_pk import get_entity_pk_type
from .attribute import Attribute
from .enum_value import EnumValue
from .value import Value
class Entity:
"""Helper class that will be attached to entities registered with eav."""
@staticmethod
def pre_save_handler(sender, *args, **kwargs):
"""
Pre save handler attached to self.instance. Called before the
model instance we are attached to is saved. This allows us to call
:meth:`validate_attributes` before the entity is saved.
"""
instance = kwargs["instance"]
entity = getattr(kwargs["instance"], instance._eav_config_cls.eav_attr) # noqa: SLF001
entity.validate_attributes()
@staticmethod
def post_save_handler(sender, *args, **kwargs):
"""
Post save handler attached to self.instance. Calls :meth:`save` when
the model instance we are attached to is saved.
"""
instance = kwargs["instance"]
entity = getattr(instance, instance._eav_config_cls.eav_attr) # noqa: SLF001
entity.save()
def __init__(self, instance) -> None:
"""
Set self.instance equal to the instance of the model that we're attached
to. Also, store the content type of that instance.
"""
self.instance = instance
self.ct = ContentType.objects.get_for_model(instance)
def __getattr__(self, name):
"""
The magic getattr helper. This is called whenever user invokes::
instance.<attribute>
Checks if *name* is a valid slug for attributes available to this
instances. If it is, tries to lookup the :class:`Value` with that
attribute slug. If there is one, it returns the value of the
class:`Value` object, otherwise it hasn't been set, so it returns
None.
"""
if not name.startswith("_"):
try:
attribute = self.get_attribute_by_slug(name)
except Attribute.DoesNotExist as err:
raise AttributeError(
_("%(obj)s has no EAV attribute named %(attr)s")
% {"obj": self.instance, "attr": name},
) from err
try:
return self.get_value_by_attribute(attribute).value
except Value.DoesNotExist:
return None
return getattr(super(), name)
def get_all_attributes(self):
"""
Return a query set of all :class:`Attribute` objects that can be set
for this entity.
"""
return self.instance._eav_config_cls.get_attributes( # noqa: SLF001
instance=self.instance,
).order_by("display_order")
def _hasattr(self, attribute_slug):
"""
Since we override __getattr__ with a backdown to the database, this
exists as a way of checking whether a user has set a real attribute on
ourselves, without going to the db if not.
"""
return attribute_slug in self.__dict__
def _getattr(self, attribute_slug):
"""
Since we override __getattr__ with a backdown to the database, this
exists as a way of getting the value a user set for one of our
attributes, without going to the db to check.
"""
return self.__dict__[attribute_slug]
def save(self):
"""Saves all the EAV values that have been set on this entity."""
for attribute in self.get_all_attributes():
if self._hasattr(attribute.slug):
attribute_value = self._getattr(attribute.slug)
if (
attribute.datatype == Attribute.TYPE_ENUM
and not isinstance(
attribute_value,
EnumValue,
)
and attribute_value is not None
):
attribute_value = EnumValue.objects.get(value=attribute_value)
attribute.save_value(self.instance, attribute_value)
def validate_attributes(self):
"""
Called before :meth:`save`, first validate all the entity values to
make sure they can be created / saved cleanly.
Raises ``ValidationError`` if they can't be.
"""
values_dict = self.get_values_dict()
for attribute in self.get_all_attributes():
value = None
# Value was assigned to this instance.
if self._hasattr(attribute.slug):
value = self._getattr(attribute.slug)
values_dict.pop(attribute.slug, None)
# Otherwise try pre-loaded from DB.
else:
value = values_dict.pop(attribute.slug, None)
if value is None:
if attribute.required:
raise ValidationError(
_("%s EAV field cannot be blank") % attribute.slug,
)
else:
try:
attribute.validate_value(value)
except ValidationError as err:
raise ValidationError(
_("%(attr)s EAV field %(err)s")
% {"attr": attribute.slug, "err": err},
) from err
illegal = values_dict or (
self.get_object_attributes() - self.get_all_attribute_slugs()
)
if illegal:
message = (
"Instance of the class {} cannot have values for attributes: {}."
).format(
self.instance.__class__,
", ".join(illegal),
)
raise IllegalAssignmentException(message)
def get_values_dict(self):
return {v.attribute.slug: v.value for v in self.get_values()}
def get_values(self):
"""Get all set :class:`Value` objects for self.instance."""
entity_filter = {
"entity_ct": self.ct,
f"{get_entity_pk_type(self.instance)}": self.instance.pk,
}
return Value.objects.filter(**entity_filter).select_related()
def get_all_attribute_slugs(self):
"""Returns a list of slugs for all attributes available to this entity."""
return set(self.get_all_attributes().values_list("slug", flat=True))
def get_attribute_by_slug(self, slug):
"""Returns a single :class:`Attribute` with *slug*."""
return self.get_all_attributes().get(slug=slug)
def get_value_by_attribute(self, attribute):
"""Returns a single :class:`Value` for *attribute*."""
return self.get_values().get(attribute=attribute)
def get_object_attributes(self):
"""
Returns entity instance attributes, except for
``instance`` and ``ct`` which are used internally.
"""
return set(copy(self.__dict__).keys()) - {"instance", "ct"}
def __iter__(self):
"""
Iterate over set eav values. This would allow you to do::
for i in m.eav: print(i)
"""
return iter(self.get_values())
class EAVModelMeta(ModelBase):
def __new__(cls, name, bases, namespace, **kwds):
result = super().__new__(cls, name, bases, dict(namespace))
register(result)
return result

63
eav/models/enum_group.py Normal file
View file

@ -0,0 +1,63 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Any
from django.db import models
from django.db.models import ManyToManyField
from django.utils.translation import gettext_lazy as _
from eav.logic.managers import EnumGroupManager
from eav.logic.object_pk import get_pk_format
from eav.settings import CHARFIELD_LENGTH
if TYPE_CHECKING:
from .enum_value import EnumValue
class EnumGroup(models.Model):
"""
*EnumGroup* objects have two fields - a *name* ``CharField`` and *values*,
a ``ManyToManyField`` to :class:`EnumValue`. :class:`Attribute` classes
with datatype *TYPE_ENUM* have a ``ForeignKey`` field to *EnumGroup*.
See :class:`EnumValue` for an example.
"""
id = get_pk_format()
name = models.CharField(
unique=True,
max_length=CHARFIELD_LENGTH,
verbose_name=_("Name"),
)
values: ManyToManyField[EnumValue, Any] = ManyToManyField(
"eav.EnumValue",
verbose_name=_("Enum group"),
)
objects = EnumGroupManager()
class Meta:
verbose_name = _("EnumGroup")
verbose_name_plural = _("EnumGroups")
def __str__(self) -> str:
"""String representation of `EnumGroup` instance."""
return str(self.name)
def __repr__(self) -> str:
"""String representation of `EnumGroup` object."""
return f"<EnumGroup {self.name}>"
def natural_key(self) -> tuple[str]:
"""
Retrieve the natural key for the EnumGroup instance.
The natural key for an EnumGroup is defined by its `name`. This method
returns the name of the instance as a single-element tuple.
Returns
-------
tuple: A tuple containing the name of the EnumGroup instance.
"""
return (self.name,)

74
eav/models/enum_value.py Normal file
View file

@ -0,0 +1,74 @@
from __future__ import annotations
from django.db import models
from django.utils.translation import gettext_lazy as _
from eav.logic.managers import EnumValueManager
from eav.logic.object_pk import get_pk_format
from eav.logic.slug import SLUGFIELD_MAX_LENGTH
class EnumValue(models.Model):
"""
*EnumValue* objects are the value 'choices' to multiple choice *TYPE_ENUM*
:class:`Attribute` objects. They have only one field, *value*, a
``CharField`` that must be unique.
For example::
yes = EnumValue.objects.create(value='Yes') # doctest: SKIP
no = EnumValue.objects.create(value='No')
unknown = EnumValue.objects.create(value='Unknown')
ynu = EnumGroup.objects.create(name='Yes / No / Unknown')
ynu.values.add(yes, no, unknown)
Attribute.objects.create(name='has fever?',
datatype=Attribute.TYPE_ENUM, enum_group=ynu)
# = <Attribute: has fever? (Multiple Choice)>
.. note::
The same *EnumValue* objects should be reused within multiple
*EnumGroups*. For example, if you have one *EnumGroup* called: *Yes /
No / Unknown* and another called *Yes / No / Not applicable*, you should
only have a total of four *EnumValues* objects, as you should have used
the same *Yes* and *No* *EnumValues* for both *EnumGroups*.
"""
id = get_pk_format()
value = models.CharField(
_("Value"),
db_index=True,
unique=True,
max_length=SLUGFIELD_MAX_LENGTH,
)
objects = EnumValueManager()
class Meta:
verbose_name = _("EnumValue")
verbose_name_plural = _("EnumValues")
def __str__(self) -> str:
"""String representation of `EnumValue` instance."""
return str(
self.value,
)
def __repr__(self) -> str:
"""String representation of `EnumValue` object."""
return f"<EnumValue {self.value}>"
def natural_key(self) -> tuple[str]:
"""
Retrieve the natural key for the EnumValue instance.
The natural key for an EnumValue is defined by its `value`. This method returns
the value of the instance as a single-element tuple.
Returns
-------
tuple: A tuple containing the value of the EnumValue instance.
"""
return (self.value,)

232
eav/models/value.py Normal file
View file

@ -0,0 +1,232 @@
# ruff: noqa: UP007
from __future__ import annotations
from typing import TYPE_CHECKING, ClassVar, Optional
from django.contrib.contenttypes import fields as generic
from django.contrib.contenttypes.models import ContentType
from django.core.serializers.json import DjangoJSONEncoder
from django.db import models
from django.db.models import ForeignKey
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from eav.fields import CSVField
from eav.logic.managers import ValueManager
from eav.logic.object_pk import get_pk_format
if TYPE_CHECKING:
from .attribute import Attribute
from .enum_value import EnumValue
class Value(models.Model):
"""
Putting the **V** in *EAV*.
This model stores the value for one particular :class:`Attribute` for
some entity.
As with most EAV implementations, most of the columns of this model will
be blank, as onle one *value_* field will be used.
Example::
import eav
from django.contrib.auth.models import User
eav.register(User)
u = User.objects.create(username='crazy_dev_user')
a = Attribute.objects.create(name='Fav Drink', datatype='text')
Value.objects.create(entity = u, attribute = a, value_text = 'red bull')
# = <Value: crazy_dev_user - Fav Drink: "red bull">
"""
id = get_pk_format()
# Direct foreign keys
attribute: ForeignKey[Attribute] = ForeignKey(
"eav.Attribute",
db_index=True,
on_delete=models.PROTECT,
verbose_name=_("Attribute"),
)
# Entity generic relationships. Rather than rely on database casting,
# this will instead use a separate ForeignKey field attribute that matches
# the FK type of the entity.
entity_id = models.IntegerField(
blank=True,
null=True,
verbose_name=_("Entity id"),
)
entity_uuid = models.UUIDField(
blank=True,
null=True,
verbose_name=_("Entity uuid"),
)
entity_ct = ForeignKey(
ContentType,
on_delete=models.PROTECT,
related_name="value_entities",
verbose_name=_("Entity ct"),
)
entity_pk_int = generic.GenericForeignKey(
ct_field="entity_ct",
fk_field="entity_id",
)
entity_pk_uuid = generic.GenericForeignKey(
ct_field="entity_ct",
fk_field="entity_uuid",
)
# Model attributes
created = models.DateTimeField(
default=timezone.now,
verbose_name=_("Created"),
)
modified = models.DateTimeField(
auto_now=True,
verbose_name=_("Modified"),
)
# Value attributes
value_bool = models.BooleanField(
blank=True,
null=True,
verbose_name=_("Value bool"),
)
value_csv = CSVField(
blank=True,
null=True,
verbose_name=_("Value CSV"),
)
value_date = models.DateTimeField(
blank=True,
null=True,
verbose_name=_("Value date"),
)
value_float = models.FloatField(
blank=True,
null=True,
verbose_name=_("Value float"),
)
value_int = models.BigIntegerField(
blank=True,
null=True,
verbose_name=_("Value int"),
)
value_text = models.TextField(
blank=True,
default="",
verbose_name=_("Value text"),
)
value_json = models.JSONField(
default=dict,
encoder=DjangoJSONEncoder,
blank=True,
null=True,
verbose_name=_("Value JSON"),
)
value_enum: ForeignKey[Optional[EnumValue]] = ForeignKey(
"eav.EnumValue",
blank=True,
null=True,
on_delete=models.PROTECT,
related_name="eav_values",
verbose_name=_("Value enum"),
)
# Value object relationship
generic_value_id = models.IntegerField(
blank=True,
null=True,
verbose_name=_("Generic value id"),
)
generic_value_ct = ForeignKey(
ContentType,
blank=True,
null=True,
on_delete=models.PROTECT,
related_name="value_values",
verbose_name=_("Generic value content type"),
)
value_object = generic.GenericForeignKey(
ct_field="generic_value_ct",
fk_field="generic_value_id",
)
objects = ValueManager()
class Meta:
verbose_name = _("Value")
verbose_name_plural = _("Values")
constraints: ClassVar[list[models.Constraint]] = [
models.UniqueConstraint(
fields=["entity_ct", "attribute", "entity_uuid"],
name="unique_entity_uuid_per_attribute",
),
models.UniqueConstraint(
fields=["entity_ct", "attribute", "entity_id"],
name="unique_entity_id_per_attribute",
),
models.CheckConstraint(
check=(
models.Q(entity_id__isnull=False, entity_uuid__isnull=True)
| models.Q(entity_id__isnull=True, entity_uuid__isnull=False)
),
name="ensure_entity_id_xor_entity_uuid",
),
]
def __str__(self) -> str:
"""String representation of a Value."""
entity = self.entity_pk_uuid if self.entity_uuid else self.entity_pk_int
return f'{self.attribute.name}: "{self.value}" ({entity})'
def __repr__(self) -> str:
"""Representation of Value object."""
entity = self.entity_pk_uuid if self.entity_uuid else self.entity_pk_int
return f'{self.attribute.name}: "{self.value}" ({entity})'
def save(self, *args, **kwargs):
"""Validate and save this value."""
self.full_clean()
super().save(*args, **kwargs)
def natural_key(self) -> tuple[tuple[str, str], int, str]:
"""
Retrieve the natural key for the Value instance.
The natural key for a Value is a combination of its `attribute` natural key,
`entity_id`, and `entity_uuid`. This method returns a tuple containing these
three elements.
Returns
-------
tuple: A tuple containing the natural key of the attribute, entity ID,
and entity UUID of the Value instance.
"""
return (self.attribute.natural_key(), self.entity_id, self.entity_uuid)
def _get_value(self):
"""Return the python object this value is holding."""
return getattr(self, f"value_{self.attribute.datatype}")
def _set_value(self, new_value):
"""Set the object this value is holding."""
setattr(self, f"value_{self.attribute.datatype}", new_value)
value = property(_get_value, _set_value)

View file

@ -1,102 +1,106 @@
# -*- coding: utf-8 -*-
'''
Queryset.
This module contains custom EavQuerySet class used for overriding
"""
This module contains custom :class:`EavQuerySet` class used for overriding
relational operators and pure functions for rewriting Q-expressions.
Q-expressions need to be rewritten for two reasons:
1. In order to hide implementation from the user and provide easy to use
syntax sugar, i.e.::
1. In order to hide implementation from the user and provide easy to use
syntax sugar, i.e.::
Supplier.objects.filter(eav__city__startswith='New')
Supplier.objects.filter(eav__city__startswith='New')
instead of::
instead of::
city_values = Value.objects.filter(value__text__startswith='New')
Supplier.objects.filter(eav_values__in=city_values)
city_values = Value.objects.filter(value__text__startswith='New')
Supplier.objects.filter(eav_values__in=city_values)
For details see: ``eav_filter``.
For details see: :func:`eav_filter`.
2. To ensure that Q-expression tree is compiled to valid SQL.
For details see: ``rewrite_q_expr``.
'''
2. To ensure that Q-expression tree is compiled to valid SQL.
For details see: :func:`rewrite_q_expr`.
"""
from functools import wraps
from itertools import count
from django.db import models
from django.db.models import Q
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Case, IntegerField, Q, When
from django.db.models.query import QuerySet
from django.db.utils import NotSupportedError
from .models import Attribute, Value
from eav.models import Attribute, EnumValue, Value
def is_eav_and_leaf(expr, gr_name):
'''
"""
Checks whether Q-expression is an EAV AND leaf.
Args:
expr (Q | tuple): Q-expression to be checked.
expr (Union[Q, tuple]): Q-expression to be checked.
gr_name (str): Generic relation attribute name, by default 'eav_values'
Returns:
bool
'''
return (getattr(expr, 'connector', None) == 'AND' and
len(expr.children) == 1 and
expr.children[0][0] in ['pk__in', '{}__in'.format(gr_name)])
"""
return (
getattr(expr, "connector", None) == "AND"
and len(expr.children) == 1
and expr.children[0][0] in ["pk__in", f"{gr_name}__in"]
)
def rewrite_q_expr(model_cls, expr):
'''
Rewrites Q-expression to safe form, in order to ensure that
generated SQL is valid.
"""
Rewrites Q-expression to safe form, in order to ensure that
generated SQL is valid.
Suppose we have the following Q-expression:
IGNORE:
Suppose we have the following Q-expression:
OR
AND
eav_values__in [1, 2, 3]
AND (1)
AND
eav_values__in [4, 5]
AND
eav_values__in [6, 7, 8]
OR
AND
eav_values__in [1, 2, 3]
AND (1)
AND
eav_values__in [4, 5]
AND
eav_values__in [6, 7, 8]
IGNORE
All EAV values are stored in a single table. Therefore, INNER JOIN
generated for the AND-expression (1) will always fail, i.e.
single row in a eav_values table cannot be both in two disjoint sets at
the same time (and the whole point of using AND, usually, is two have
two different sets). Therefore, we must paritially rewrite the
expression so that the generated SQL is valid::
All EAV values are stored in a single table. Therefore, INNER JOIN
generated for the AND-expression (1) will always fail, i.e.
single row in a eav_values table cannot be both in two disjoint sets at
the same time (and the whole point of using AND, usually, is two have
two different sets). Therefore, we must paritially rewrite the
expression so that the generated SQL is valid.
OR
AND
eav_values__in [1, 2, 3]
AND
pk__in [1, 2]
IGNORE:
OR
AND
eav_values__in [1, 2, 3]
AND
pk__in [1, 2]
IGNORE
This is done by merging dangerous AND's and substituting them with
explicit ``pk__in`` filter, where pks are taken from evaluted
Q-expr branch.
This is done by merging dangerous AND's and substituting them with
explicit ``pk__in`` filter, where pks are taken from evaluated
Q-expr branch.
Args:
model_cls (Model class): model class used to construct QuerySet
from leaf attribute-value expression.
expr: (Q | tuple): Q-expression (or attr-val leaf) to be rewritten.
Args:
model_cls (TypeVar): model class used to construct :meth:`QuerySet`
from leaf attribute-value expression.
expr: (Q | tuple): Q-expression (or attr-val leaf) to be rewritten.
Returns:
Q | tuple
'''
Returns:
Union[Q, tuple]
"""
# Node in a Q-expr can be a Q or an attribute-value tuple (leaf).
# We are only interested in Qs.
if isinstance(expr, Q):
config_cls = getattr(model_cls, '_eav_config_cls', None)
config_cls = getattr(model_cls, "_eav_config_cls", None)
gr_name = config_cls.generic_relation_attr
# Recurively check child nodes.
# Recursively check child nodes.
expr.children = [rewrite_q_expr(model_cls, c) for c in expr.children]
# Check which ones need a rewrite.
rewritable = [c for c in expr.children if is_eav_and_leaf(c, gr_name)]
@ -107,18 +111,18 @@ def rewrite_q_expr(model_cls, expr):
if len(rewritable) > 1:
q = None
# Save nodes which shouldn't be merged (non-EAV).
other = [c for c in expr.children if not c in rewritable]
other = [c for c in expr.children if c not in rewritable]
for child in rewritable:
if not (child.children and len(child.children) == 1):
raise AssertionError('Child must have exactly one descendant')
raise AssertionError("Child must have exactly one descendant")
# Child to be merged is always a terminal Q node,
# i.e. it's an AND expression with attribute-value tuple child.
attrval = child.children[0]
if not isinstance(attrval, tuple):
raise AssertionError('Attribute-value must be a tuple')
raise TypeError("Attribute-value must be a tuple")
fname = '{}__in'.format(gr_name)
fname = f"{gr_name}__in"
# Child can be either a 'eav_values__in' or 'pk__in' query.
# If it's the former then transform it into the latter.
@ -126,7 +130,7 @@ def rewrite_q_expr(model_cls, expr):
# If so, reverse it back to QuerySet so that set operators
# can be applied.
if attrval[0] == fname or hasattr(attrval[1], '__contains__'):
if attrval[0] == fname or hasattr(attrval[1], "__contains__"):
# Create model queryset.
_q = model_cls.objects.filter(**{fname: attrval[1]})
else:
@ -135,27 +139,28 @@ def rewrite_q_expr(model_cls, expr):
# Explicitly check for None. 'or' doesn't work here
# as empty QuerySet, which is valid, is falsy.
q = q if q != None else _q
q = q if q is not None else _q
if expr.connector == 'AND':
if expr.connector == "AND":
q &= _q
else:
q |= _q
# If any two children were merged,
# update parent expression.
if q != None:
expr.children = other + [('pk__in', q)]
if q is not None:
expr.children = [*other, ("pk__in", q)]
return expr
def eav_filter(func):
'''
"""
Decorator used to wrap filter and exclude methods. Passes args through
expand_q_filters and kwargs through expand_eav_filter. Returns the
:func:`expand_q_filters` and kwargs through :func:`expand_eav_filter`. Returns the
called function (filter or exclude).
'''
"""
@wraps(func)
def wrapper(self, *args, **kwargs):
nargs = []
@ -164,9 +169,9 @@ def eav_filter(func):
for arg in args:
if isinstance(arg, Q):
# Modify Q objects (warning: recursion ahead).
arg = expand_q_filters(arg, self.model)
arg = expand_q_filters(arg, self.model) # noqa: PLW2901
# Rewrite Q-expression to safeform.
arg = rewrite_q_expr(self.model, arg)
arg = rewrite_q_expr(self.model, arg) # noqa: PLW2901
nargs.append(arg)
for key, value in kwargs.items():
@ -174,8 +179,11 @@ def eav_filter(func):
nkey, nval = expand_eav_filter(self.model, key, value)
if nkey in nkwargs:
# Apply AND to both querysets.
nkwargs[nkey] = (nkwargs[nkey] & nval).distinct()
# Add filter to check if matching entity_id is
# in the previous queryset with same nkey
nkwargs[nkey] = nval.filter(
entity_id__in=nkwargs[nkey].values_list("entity_id", flat=True),
).distinct()
else:
nkwargs.update({nkey: nval})
@ -185,11 +193,11 @@ def eav_filter(func):
def expand_q_filters(q, root_cls):
'''
"""
Takes a Q object and a model class.
Recursively passes each filter / value in the Q object tree leaf nodes
through expand_eav_filter
'''
through :func:`expand_eav_filter`.
"""
new_children = []
for qi in q.children:
@ -207,7 +215,7 @@ def expand_q_filters(q, root_cls):
def expand_eav_filter(model_cls, key, value):
'''
"""
Accepts a model class and a key, value.
Recurisively replaces any eav filter with a subquery.
@ -220,62 +228,143 @@ def expand_eav_filter(model_cls, key, value):
key = 'eav_values__in'
value = Values.objects.filter(value_int=5, attribute__slug='height')
'''
fields = key.split('__')
config_cls = getattr(model_cls, '_eav_config_cls', None)
"""
fields = key.split("__")
config_cls = getattr(model_cls, "_eav_config_cls", None)
if len(fields) > 1 and config_cls and fields[0] == config_cls.eav_attr:
slug = fields[1]
gr_name = config_cls.generic_relation_attr
datatype = Attribute.objects.get(slug=slug).datatype
lookup = '__%s' % fields[2] if len(fields) > 2 else ''
kwargs = {
'value_{}{}'.format(datatype, lookup): value,
'attribute__slug': slug
}
value_key = ""
if datatype == Attribute.TYPE_ENUM and not isinstance(value, EnumValue):
lookup = f"__value__{fields[2]}" if len(fields) > 2 else "__value" # noqa: PLR2004
value_key = f"value_{datatype}{lookup}"
elif datatype == Attribute.TYPE_OBJECT:
value_key = "generic_value_id"
else:
lookup = f"__{fields[2]}" if len(fields) > 2 else "" # noqa: PLR2004
value_key = f"value_{datatype}{lookup}"
kwargs = {value_key: value, "attribute__slug": slug}
value = Value.objects.filter(**kwargs)
return '%s__in' % gr_name, value
return f"{gr_name}__in", value
try:
field = model_cls._meta.get_field(fields[0])
except models.FieldDoesNotExist:
return key, value
if not field.auto_created or field.concrete:
return key, value
else:
sub_key = '__'.join(fields[1:])
key, value = expand_eav_filter(field.model, sub_key, value)
return '{}__{}'.format(ields[0], key), value
# Not an eav field, so keep as is
return key, value
class EavQuerySet(QuerySet):
'''
"""
Overrides relational operators for EAV models.
'''
"""
@eav_filter
def filter(self, *args, **kwargs):
'''
Pass *args* and *kwargs* through ``eav_filter``, then pass to
the ``models.Manager`` filter method.
'''
"""
Pass *args* and *kwargs* through :func:`eav_filter`, then pass to
the ``Manager`` filter method.
"""
return super().filter(*args, **kwargs)
@eav_filter
def exclude(self, *args, **kwargs):
'''
Pass *args* and *kwargs* through ``eav_filter``, then pass to
the ``models.Manager`` exclude method.
'''
"""
Pass *args* and *kwargs* through :func:`eav_filter`, then pass to
the ``Manager`` exclude method.
"""
return super().exclude(*args, **kwargs)
@eav_filter
def get(self, *args, **kwargs):
'''
Pass *args* and *kwargs* through ``eav_filter``, then pass to
the ``models.Manager`` get method.
'''
"""
Pass *args* and *kwargs* through :func:`eav_filter`, then pass to
the ``Manager`` get method.
"""
return super().get(*args, **kwargs)
def order_by(self, *fields):
# Django only allows to order querysets by direct fields and
# foreign-key chains. In order to bypass this behaviour and order
# by EAV attributes, it is required to construct custom order-by
# clause manually using Django's conditional expressions.
# This will be slow, of course.
order_clauses = []
query_clause = self
config_cls = self.model._eav_config_cls # noqa: SLF001
for term in [t.split("__") for t in fields]:
# Continue only for EAV attributes.
if len(term) == 2 and term[0] == config_cls.eav_attr: # noqa: PLR2004
# Retrieve Attribute over which the ordering is performed.
try:
attr = Attribute.objects.get(slug=term[1])
except ObjectDoesNotExist as err:
raise ObjectDoesNotExist(
f'Cannot find EAV attribute "{term[1]}"',
) from err
field_name = f"value_{attr.datatype}"
pks_values = (
Value.objects.filter(
# Retrieve pk-values pairs of the related values
# (i.e. values for the specified attribute and
# belonging to entities in the queryset).
attribute__slug=attr.slug,
entity_id__in=self,
)
.order_by(
# Order values by their value-field of
# appropriate attribute data-type.
field_name,
)
.values_list(
# Retrieve only primary-keys of the entities
# in the current queryset.
"entity_id",
field_name,
)
)
# Retrieve ordered values from pk-value list.
_, ordered_values = zip(*pks_values)
# Add explicit ordering and turn
# list of pairs into look-up table.
val2ind = dict(zip(ordered_values, count()))
# Finally, zip ordered pks with their grouped orderings.
entities_pk = [(pk, val2ind[val]) for pk, val in pks_values]
# Using ordered primary-keys, construct
# CASE clause of the form:
#
# CASE
# WHEN id = 2 THEN 1
# WHEN id = 5 THEN 2
# WHEN id = 9 THEN 2
# WHEN id = 4 THEN 3
# END
#
when_clauses = [When(id=pk, then=i) for pk, i in entities_pk]
order_clause = Case(*when_clauses, output_field=IntegerField())
clause_name = "__".join(term)
# Use when-clause to construct
# custom order-by clause.
query_clause = query_clause.annotate(**{clause_name: order_clause})
order_clauses.append(clause_name)
elif len(term) >= 2 and term[0] == config_cls.eav_attr: # noqa: PLR2004
raise NotSupportedError(
"EAV does not support ordering through foreign-key chains",
)
else:
order_clauses.append(term[0])
return QuerySet.order_by(query_clause, *order_clauses)

View file

@ -1,171 +1,195 @@
'''Registry. This modules contains the registry classes.'''
"""This modules contains the registry classes."""
from django.contrib.contenttypes import fields as generic
from django.db.models.signals import post_init, post_save, pre_save
from .managers import EntityManager
from .models import Attribute, Entity, Value
from eav.logic.entity_pk import get_entity_pk_type
from eav.managers import EntityManager
from eav.models import Attribute, Entity, Value
class EavConfig(object):
'''
The default EavConfig class used if it is not overriden on registration.
class EavConfig:
"""
The default ``EavConfig`` class used if it is not overridden on registration.
This is where all the default eav attribute names are defined.
Available options are as follows:
1. manager_attr - Specifies manager name. Used to refer to the
manager from Entity class, "objects" by default.
2. manager_only - Specifies whether signals and generic relation should
be setup for the registered model.
3. eav_attr - Named of the Entity toolkit instance on the registered
model instance. "eav" by default. See attach_eav_attr.
4. generic_relation_attr - Name of the GenericRelation to Value
objects. "eav_values" by default.
5. generic_relation_related_name - Name of the related name for
GenericRelation from Entity to Value. None by default. Therefore,
if not overridden, it is not possible to query Values by Entities.
'''
manager_attr = 'objects'
1. manager_attr - Specifies manager name. Used to refer to the
manager from Entity class, "objects" by default.
2. manager_only - Specifies whether signals and generic relation should
be setup for the registered model.
3. eav_attr - Named of the Entity toolkit instance on the registered
model instance. "eav" by default. See attach_eav_attr.
4. generic_relation_attr - Name of the GenericRelation to Value
objects. "eav_values" by default.
5. generic_relation_related_name - Name of the related name for
GenericRelation from Entity to Value. None by default. Therefore,
if not overridden, it is not possible to query Values by Entities.
"""
manager_attr = "objects"
manager_only = False
eav_attr = 'eav'
generic_relation_attr = 'eav_values'
eav_attr = "eav"
generic_relation_attr = "eav_values"
generic_relation_related_name = None
@classmethod
def get_attributes(cls):
'''
def get_attributes(cls, instance=None):
"""
By default, all :class:`~eav.models.Attribute` object apply to an
entity, unless you provide a custom EavConfig class overriding this.
'''
"""
return Attribute.objects.all()
class Registry(object):
'''
class Registry:
"""
Handles registration through the
:meth:`register` and :meth:`unregister` methods.
'''
"""
@staticmethod
def register(model_cls, config_cls=None):
'''
"""
Registers *model_cls* with eav. You can pass an optional *config_cls*
to override the EavConfig defaults.
.. note::
Multiple registrations for the same entity are harmlessly ignored.
'''
if hasattr(model_cls, '_eav_config_cls'):
"""
if hasattr(model_cls, "_eav_config_cls"):
return
if config_cls is EavConfig or config_cls is None:
config_cls = type("%sConfig" % model_cls.__name__,
(EavConfig,), {})
config_cls = type(f"{model_cls.__name__}Config", (EavConfig,), {})
# set _eav_config_cls on the model so we can access it there
setattr(model_cls, '_eav_config_cls', config_cls)
model_cls._eav_config_cls = config_cls
reg = Registry(model_cls)
reg._register_self()
@staticmethod
def unregister(model_cls):
'''
"""
Unregisters *model_cls* with eav.
.. note::
Unregistering a class not already registered is harmlessly ignored.
'''
if not getattr(model_cls, '_eav_config_cls', None):
"""
if not getattr(model_cls, "_eav_config_cls", None):
return
reg = Registry(model_cls)
reg._unregister_self()
delattr(model_cls, '_eav_config_cls')
delattr(model_cls, "_eav_config_cls")
@staticmethod
def attach_eav_attr(sender, *args, **kwargs):
'''
"""
Attach EAV Entity toolkit to an instance after init.
'''
instance = kwargs['instance']
"""
instance = kwargs["instance"]
config_cls = instance.__class__._eav_config_cls
setattr(instance, config_cls.eav_attr, Entity(instance))
def __init__(self, model_cls):
'''
"""
Set the *model_cls* and its *config_cls*
'''
"""
self.model_cls = model_cls
self.config_cls = model_cls._eav_config_cls
def _attach_manager(self):
'''
Attach the manager to *manager_attr* specified in *config_cls*
'''
# Save the old manager if the attribute name conflicts with the new one.
if hasattr(self.model_cls, self.config_cls.manager_attr):
mgr = getattr(self.model_cls, self.config_cls.manager_attr)
self.config_cls.old_mgr = mgr
self.model_cls._meta.local_managers.remove(mgr)
self.model_cls._meta._expire_cache()
def _attach_manager(self) -> None:
"""
Attach the EntityManager to the model class.
# Attach the new manager to the model.
mgr = EntityManager()
mgr.contribute_to_class(self.model_cls, self.config_cls.manager_attr)
This method replaces the existing manager specified in the `config_cls`
with a new instance of `EntityManager`. If the specified manager is the
default manager, the `EntityManager` is set as the new default manager.
Otherwise, it is appended to the list of managers.
If the model class already has a manager with the same name as the one
specified in `config_cls`, it is saved as `old_mgr` in the `config_cls`
for use during detachment.
"""
manager_attr = self.config_cls.manager_attr
model_meta = self.model_cls._meta
current_manager = getattr(self.model_cls, manager_attr, None)
if isinstance(current_manager, EntityManager):
# EntityManager is already attached, no need to proceed
return
# Create a new EntityManager
new_manager = EntityManager()
# Save and remove the old manager if it exists
if current_manager and current_manager in model_meta.local_managers:
self.config_cls.old_mgr = current_manager
model_meta.local_managers.remove(current_manager)
# Set the creation_counter to maintain the order
# This ensures that the new manager has the same priority as the old one
new_manager.creation_counter = current_manager.creation_counter
# Attach the new EntityManager instance to the model.
new_manager.contribute_to_class(self.model_cls, manager_attr)
def _detach_manager(self):
'''
"""
Detach the manager and restore the previous one (if there was one).
'''
"""
mgr = getattr(self.model_cls, self.config_cls.manager_attr)
self.model_cls._meta.local_managers.remove(mgr)
self.model_cls._meta._expire_cache()
delattr(self.model_cls, self.config_cls.manager_attr)
if hasattr(self.config_cls, 'old_mgr'):
self.config_cls.old_mgr \
.contribute_to_class(self.model_cls,
self.config_cls.manager_attr)
if hasattr(self.config_cls, "old_mgr"):
self.config_cls.old_mgr.contribute_to_class(
self.model_cls,
self.config_cls.manager_attr,
)
def _attach_signals(self):
'''
"""
Attach pre- and post- save signals from model class
to Entity helper. This way, Entity instance will be
able to prepare and clean-up before and after creation /
update of the user's model class instance.
'''
post_init.connect(Registry.attach_eav_attr, sender = self.model_cls)
pre_save.connect(Entity.pre_save_handler, sender = self.model_cls)
post_save.connect(Entity.post_save_handler, sender = self.model_cls)
"""
post_init.connect(Registry.attach_eav_attr, sender=self.model_cls)
pre_save.connect(Entity.pre_save_handler, sender=self.model_cls)
post_save.connect(Entity.post_save_handler, sender=self.model_cls)
def _detach_signals(self):
'''
"""
Detach all signals for eav.
'''
post_init.disconnect(Registry.attach_eav_attr, sender = self.model_cls)
pre_save.disconnect(Entity.pre_save_handler, sender = self.model_cls)
post_save.disconnect(Entity.post_save_handler, sender = self.model_cls)
"""
post_init.disconnect(Registry.attach_eav_attr, sender=self.model_cls)
pre_save.disconnect(Entity.pre_save_handler, sender=self.model_cls)
post_save.disconnect(Entity.post_save_handler, sender=self.model_cls)
def _attach_generic_relation(self):
'''
Set up the generic relation for the entity
'''
rel_name = self.config_cls.generic_relation_related_name or \
self.model_cls.__name__
"""Set up the generic relation for the entity."""
rel_name = (
self.config_cls.generic_relation_related_name or self.model_cls.__name__
)
gr_name = self.config_cls.generic_relation_attr.lower()
generic_relation = \
generic.GenericRelation(Value,
object_id_field='entity_id',
content_type_field='entity_ct',
related_query_name=rel_name)
generic_relation = generic.GenericRelation(
Value,
object_id_field=get_entity_pk_type(self.model_cls),
content_type_field="entity_ct",
related_query_name=rel_name,
)
generic_relation.contribute_to_class(self.model_cls, gr_name)
def _detach_generic_relation(self):
'''
"""
Remove the generic relation from the entity
'''
"""
gen_rel_field = self.config_cls.generic_relation_attr.lower()
for field in self.model_cls._meta.local_many_to_many:
if field.name == gen_rel_field:
@ -175,9 +199,9 @@ class Registry(object):
delattr(self.model_cls, gen_rel_field)
def _register_self(self):
'''
"""
Call the necessary registration methods
'''
"""
self._attach_manager()
if not self.config_cls.manager_only:
@ -185,9 +209,9 @@ class Registry(object):
self._attach_generic_relation()
def _unregister_self(self):
'''
"""
Call the necessary unregistration methods
'''
"""
self._detach_manager()
if not self.config_cls.manager_only:

3
eav/settings.py Normal file
View file

@ -0,0 +1,3 @@
from typing import Final
CHARFIELD_LENGTH: Final = 100

View file

@ -1,24 +0,0 @@
'''Utilities. This module contains non-essential helper methods.'''
import sys
from django.db.models import Q
def print_q_expr(expr, indent="", is_tail=True):
'''
Simple print method for debugging Q-expressions' trees.
'''
sys.stdout.write(indent)
sa, sb = (' └── ', ' ') if is_tail else (' ├── ', '')
if isinstance(expr, Q):
sys.stdout.write('{}{}\n'.format(sa, expr.connector))
for child in expr.children:
print_q_expr(child, indent + sb, expr.children[-1] == child)
else:
try:
queryset = ', '.join(repr(v) for v in expr[1])
except TypeError:
queryset = repr(expr[1])
sys.stdout.write(' └── {} {}\n'.format(expr[0], queryset))

View file

@ -1,89 +1,112 @@
# -*- coding: utf-8 -*-
'''
Validtors.
This module contains a validator for each Attribute datatype.
"""
This module contains a validator for each :class:`~eav.models.Attribute` datatype.
A validator is a callable that takes a value and raises a ``ValidationError``
if it doesnt meet some criteria. (see
`django validators <http://docs.djangoproject.com/en/dev/ref/validators/>`_)
if it doesn't meet some criteria (see `Django validators
<https://docs.djangoproject.com/en/dev/ref/validators/>`_).
These validators are called by the
:meth:`~eav.models.Attribute.validate_value` method in the
:class:`~eav.models.Attribute` model.
'''
"""
import datetime
import json
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import gettext_lazy as _
def validate_text(value):
'''
"""
Raises ``ValidationError`` unless *value* type is ``str`` or ``unicode``
'''
"""
if not isinstance(value, str):
raise ValidationError(_(u"Must be str or unicode"))
raise ValidationError(_("Must be str or unicode"))
def validate_float(value):
'''
"""
Raises ``ValidationError`` unless *value* can be cast as a ``float``
'''
"""
try:
float(value)
except ValueError:
raise ValidationError(_(u"Must be a float"))
except ValueError as err:
raise ValidationError(_("Must be a float")) from err
def validate_int(value):
'''
"""
Raises ``ValidationError`` unless *value* can be cast as an ``int``
'''
"""
try:
int(value)
except ValueError:
raise ValidationError(_(u"Must be an integer"))
except ValueError as err:
raise ValidationError(_("Must be an integer")) from err
def validate_date(value):
'''
"""
Raises ``ValidationError`` unless *value* is an instance of ``datetime``
or ``date``
'''
if not isinstance(value, datetime.datetime) and not isinstance(value, datetime.date):
raise ValidationError(_(u"Must be a date or datetime"))
"""
if not isinstance(value, datetime.datetime) and not isinstance(
value,
datetime.date,
):
raise ValidationError(_("Must be a date or datetime"))
def validate_bool(value):
'''
"""
Raises ``ValidationError`` unless *value* type is ``bool``
'''
"""
if not isinstance(value, bool):
raise ValidationError(_(u"Must be a boolean"))
raise ValidationError(_("Must be a boolean"))
def validate_object(value):
'''
"""
Raises ``ValidationError`` unless *value* is a saved
django model instance.
'''
"""
if not isinstance(value, models.Model):
raise ValidationError(_(u"Must be a django model object instance"))
raise ValidationError(_("Must be a django model object instance"))
if not value.pk:
raise ValidationError(_(u"Model has not been saved yet"))
raise ValidationError(_("Model has not been saved yet"))
def validate_enum(value):
'''
"""
Raises ``ValidationError`` unless *value* is a saved
:class:`~eav.models.EnumValue` model instance.
'''
from .models import EnumValue
if not isinstance(value, EnumValue):
raise ValidationError(_(u"Must be an EnumValue model object instance"))
if not value.pk:
raise ValidationError(_(u"EnumValue has not been saved yet"))
"""
from eav.models import EnumValue
if isinstance(value, EnumValue) and not value.pk:
raise ValidationError(_("EnumValue has not been saved yet"))
def validate_json(value):
"""
Raises ``ValidationError`` unless *value* can be cast as an ``json object`` (a dict)
"""
try:
if isinstance(value, str):
value = json.loads(value)
if not isinstance(value, dict):
raise ValidationError(_("Must be a JSON Serializable object"))
except ValueError as err:
raise ValidationError(_("Must be a JSON Serializable object")) from err
def validate_csv(value):
"""
Raises ``ValidationError`` unless *value* is a c-s-v value.
"""
if isinstance(value, str):
value = value.split(";")
if not isinstance(value, list):
raise ValidationError(_("Must be Comma-Separated-Value."))

39
eav/widgets.py Normal file
View file

@ -0,0 +1,39 @@
from django.core import validators
from django.core.exceptions import ValidationError
from django.forms.widgets import Textarea
EMPTY_VALUES = (*validators.EMPTY_VALUES, "[]")
class CSVWidget(Textarea):
is_hidden = False
def prep_value(self, value):
"""Prepare value before effectively render widget"""
if value in EMPTY_VALUES:
return ""
if isinstance(value, str):
return value
if isinstance(value, list):
return ";".join(value)
raise ValidationError("Invalid format.")
def render(self, name, value, **kwargs):
value = self.prep_value(value)
return super().render(name, value, **kwargs)
def value_from_datadict(self, data, files, name):
"""
Return the value of this widget or None.
Since we're only given the value of the entity name and the data dict
contains the '_eav_config_cls' (which we don't have access to) as the
key, we need to loop through each field checking if the eav attribute
exists with the given 'name'.
"""
for data_value in data.values():
widget_value = getattr(data_value, name, None)
if widget_value is not None:
return widget_value
return None

31
manage.py Executable file
View file

@ -0,0 +1,31 @@
#!/usr/bin/env python
import os
import sys
def main() -> None:
"""
Main function.
It does several things:
1. Sets default settings module, if it is not set
2. Warns if Django is not installed
3. Executes any given command
"""
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project.settings")
try:
from django.core import management
except ImportError as err:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
+ "available on your PYTHONPATH environment variable? Did you "
+ "forget to activate a virtual environment?",
) from err
management.execute_from_command_line(sys.argv)
if __name__ == "__main__":
main()

2254
poetry.lock generated Normal file

File diff suppressed because it is too large Load diff

134
pyproject.toml Normal file
View file

@ -0,0 +1,134 @@
[build-system]
requires = ["poetry-core>=1.9"]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "django-eav2"
description = "Entity-Attribute-Value storage for Django"
version = "1.8.1"
license = "GNU Lesser General Public License (LGPL), Version 3"
packages = [
{ include = "eav" }
]
authors = [
"Mauro Lizaur <mauro@sdf.org>",
]
readme = "README.md"
repository = "https://github.com/jazzband/django-eav2"
keywords = [
"django",
"django-eav2",
"database",
"eav",
"sql",
]
classifiers = [
"Development Status :: 3 - Alpha",
"Environment :: Web Environment",
"Framework :: Django",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
"Programming Language :: Python",
"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 :: Database",
"Topic :: Software Development :: Libraries :: Python Modules",
"Framework :: Django",
"Framework :: Django :: 4.2",
"Framework :: Django :: 5.1",
"Framework :: Django :: 5.2",
]
[tool.semantic_release]
version_variable = [
"pyproject.toml:version"
]
branch = "master"
upload_to_pypi = false
upload_to_release = false
build_command = "pip install poetry && poetry build"
[tool.poetry.dependencies]
python = "^3.9"
django = ">=4.2,<5.3"
[tool.poetry.group.test.dependencies]
mypy = "^1.6"
ruff = ">=0.6.3,<0.13.0"
safety = ">=2.3,<4.0"
pytest = ">=7.4.3,<9.0.0"
pytest-cov = ">=4.1,<7.0"
pytest-randomly = "^3.15"
pytest-django = "^4.5.2"
hypothesis = "^6.87.1"
doc8 = ">=0.11.2,<1.2.0"
[tool.poetry.group.docs]
optional = true
[tool.poetry.group.docs.dependencies]
sphinx = ">=5.0,<8.0"
sphinx-rtd-theme = ">=1.3,<4.0"
sphinx-autodoc-typehints = ">=1.19.5,<3.0.0"
m2r2 = "^0.3"
tomlkit = ">=0.13.0,<0.14"
[tool.ruff]
line-length = 88
target-version = "py38"
[tool.ruff.lint]
select = ["ALL"]
ignore = [
"ANN", # Type hints related, let mypy handle these.
"ARG", # Unused arguments
"D", # Docstrings related
"EM101", # "Exception must not use a string literal, assign to variable first"
"EM102", # "Exception must not use an f-string literal, assign to variable first"
"PD", # Pandas related
"Q000", # For now
"SIM105", # "Use contextlib.suppress({exception}) instead of try-except-pass"
"TRY003", # "Avoid specifying long messages outside the exception class"
]
[tool.ruff.lint.flake8-implicit-str-concat]
allow-multiline = false
[tool.ruff.lint.per-file-ignores]
# Allow private member access for Registry
"eav/registry.py" = ["SLF001"]
# Migrations are special
"**/migrations/*" = ["RUF012"]
# Sphinx specific
"docs/source/conf.py" = ["INP001"]
# pytest is even more special
"tests/*" = [
"INP001", # "Add an __init__.py"
"PLR2004", # "Magic value used in comparison"
"PT009", # "Use a regular assert instead of unittest-style"
"PT027", # "Use pytest.raises instead of unittest-style"
"S101", # "Use of assert detected"
"SLF001" # "Private member accessed"
]
[tool.ruff.lint.pydocstyle]
# Use Google-style docstrings.
convention = "google"

View file

@ -1 +0,0 @@
Django>=1.11

View file

@ -1,29 +0,0 @@
#!/usr/bin/env python
import os
import sys
import django
from django.conf import settings
from django.test.utils import get_runner
if __name__ == "__main__":
os.environ['DJANGO_SETTINGS_MODULE'] = 'tests.test_settings'
django.setup()
TestRunner = get_runner(settings)
test_runner = TestRunner()
if len(sys.argv) == 1 or sys.argv[1] in ['-a', '--all']:
tests = [
'tests.queries',
'tests.registry',
'tests.data_validation',
'tests.attributes',
'tests.misc_models',
'tests.set_and_get',
'tests.forms'
]
else:
tests = ['tests.{}'.format(arg) for arg in sys.argv[1:]]
result = test_runner.run_tests(tests)
sys.exit(bool(result))

75
setup.cfg Normal file
View file

@ -0,0 +1,75 @@
# All configuration for plugins and other utils is defined here.
# Read more about `setup.cfg`:
# https://docs.python.org/3/distutils/configfile.html
[tool:pytest]
# Django options:
# https://pytest-django.readthedocs.io/en/latest/
DJANGO_SETTINGS_MODULE = test_project.settings
# PYTHONPATH configuration:
# https://docs.pytest.org/en/7.0.x/reference/reference.html#confval-pythonpath
pythonpath = ./eav
# py.test options:
norecursedirs =
*.egg
.eggs
dist
build
docs
.tox
.git
__pycache__
# You will need to measure your tests speed with `-n auto` and without it,
# so you can see whether it gives you any performance gain, or just gives
# you an overhead. See `docs/template/development-process.rst`.
addopts =
-p no:randomly
--strict-markers
--strict-config
--doctest-modules
--cov=eav
--cov-report=term-missing:skip-covered
--cov-report=html
--cov-report=xml
--cov-branch
--cov-fail-under=90
[coverage:run]
# Exclude tox output from coverage calculation
omit = */.tox/*
[coverage:report]
skip_covered = True
show_missing = True
sort = Cover
exclude_lines =
pragma: no cover
# type hinting related code
if TYPE_CHECKING:
[mypy]
# mypy configurations: https://bit.ly/2zEl9WI
allow_redefinition = False
check_untyped_defs = True
disallow_any_explicit = True
disallow_any_generics = True
disallow_untyped_calls = True
ignore_errors = False
ignore_missing_imports = True
implicit_reexport = False
strict_optional = True
strict_equality = True
local_partial_types = True
no_implicit_optional = True
warn_no_return = True
warn_unused_ignores = True
warn_redundant_casts = True
warn_unused_configs = True
warn_unreachable = True

View file

@ -1,25 +0,0 @@
from setuptools import setup
setup(
name = 'django-eav2',
version = __import__('eav').__version__,
license = 'GNU Lesser General Public License (LGPL), Version 3',
requires = ['python (>= 3.5)', 'django (>= 1.11.14)'],
provides = ['eav'],
description = 'Entity-Attribute-Value storage for Django',
url = 'http://github.com/makimo/django-eav2',
packages = ['eav', 'tests'],
maintainer = 'Iwo Herka',
maintainer_email = 'hi@iwoherka.eu',
classifiers = [
'Development Status :: 3 - Alpha',
'Environment :: Web Environment',
'Framework :: Django',
'Intended Audience :: Developers',
'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
'Programming Language :: Python',
'Topic :: Database',
'Topic :: Software Development :: Libraries :: Python Modules',
],
)

5
test_project/apps.py Normal file
View file

@ -0,0 +1,5 @@
from django.apps import AppConfig
class TestAppConfig(AppConfig):
name = "test_project"

View file

@ -0,0 +1,160 @@
import uuid
from django.db import migrations, models
from test_project.models import MAX_CHARFIELD_LEN
class Migration(migrations.Migration):
"""Initial migration for test_project."""
initial = True
dependencies = []
operations = [
migrations.CreateModel(
name="ExampleMetaclassModel",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=MAX_CHARFIELD_LEN)),
],
options={
"abstract": False,
},
),
migrations.CreateModel(
name="ExampleModel",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=MAX_CHARFIELD_LEN)),
],
options={
"abstract": False,
},
),
migrations.CreateModel(
name="RegisterTestModel",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=MAX_CHARFIELD_LEN)),
],
options={
"abstract": False,
},
),
migrations.CreateModel(
name="Patient",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=MAX_CHARFIELD_LEN)),
("email", models.EmailField(blank=True, max_length=MAX_CHARFIELD_LEN)),
(
"example",
models.ForeignKey(
blank=True,
null=True,
on_delete=models.deletion.PROTECT,
to="test_project.examplemodel",
),
),
],
options={
"abstract": False,
},
),
migrations.CreateModel(
name="M2MModel",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("name", models.CharField(max_length=MAX_CHARFIELD_LEN)),
("models", models.ManyToManyField(to="test_project.ExampleModel")),
],
options={
"abstract": False,
},
),
migrations.CreateModel(
name="Encounter",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("num", models.PositiveSmallIntegerField()),
(
"patient",
models.ForeignKey(
on_delete=models.deletion.PROTECT,
to="test_project.patient",
),
),
],
options={
"abstract": False,
},
),
migrations.CreateModel(
name="Doctor",
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
("name", models.CharField(max_length=MAX_CHARFIELD_LEN)),
],
options={
"abstract": False,
},
),
]

142
test_project/models.py Normal file
View file

@ -0,0 +1,142 @@
import uuid
from typing import Final, final
from django.db import models
from eav.decorators import register_eav
from eav.managers import EntityManager
from eav.models import EAVModelMeta
#: Constants
MAX_CHARFIELD_LEN: Final = 254
class TestBase(models.Model):
"""Base class for test models."""
class Meta:
"""Define common options."""
app_label = "test_project"
abstract = True
class DoctorManager(EntityManager):
"""
Custom manager for the Doctor model.
This manager extends the EntityManager and provides additional
methods specific to the Doctor model, and is expected to be the
default manager on the model.
"""
def get_by_name(self, name: str) -> models.QuerySet:
"""Returns a QuerySet of doctors with the given name.
Args:
name (str): The name of the doctor to search for.
Returns:
models.QuerySet: A QuerySet of doctors with the specified name.
"""
return self.filter(name=name)
class DoctorSubstringManager(models.Manager):
"""
Custom manager for the Doctor model.
This is a second manager used to ensure during testing that it's not replaced
as the default manager after eav.register().
"""
def get_by_name_contains(self, substring: str) -> models.QuerySet:
"""Returns a QuerySet of doctors whose names contain the given substring.
Args:
substring (str): The substring to search for in the doctor's name.
Returns:
models.QuerySet: A QuerySet of doctors whose names contain the
specified substring.
"""
return self.filter(name__icontains=substring)
@final
@register_eav()
class Doctor(TestBase):
"""Test model using UUID as primary key."""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=MAX_CHARFIELD_LEN)
objects = DoctorManager()
substrings = DoctorSubstringManager()
def __str__(self):
return self.name
@final
class Patient(TestBase):
name = models.CharField(max_length=MAX_CHARFIELD_LEN)
email = models.EmailField(max_length=MAX_CHARFIELD_LEN, blank=True)
example = models.ForeignKey(
"ExampleModel",
null=True,
blank=True,
on_delete=models.PROTECT,
)
def __str__(self):
return self.name
def __repr__(self):
return self.name
class Encounter(TestBase):
num = models.PositiveSmallIntegerField()
patient = models.ForeignKey(Patient, on_delete=models.PROTECT)
def __str__(self):
return f"{self.patient}: encounter num {self.num}"
def __repr__(self):
return self.name
@register_eav()
@final
class ExampleModel(TestBase):
name = models.CharField(max_length=MAX_CHARFIELD_LEN)
def __str__(self):
return self.name
@register_eav()
@final
class M2MModel(TestBase):
name = models.CharField(max_length=MAX_CHARFIELD_LEN)
models = models.ManyToManyField(ExampleModel)
def __str__(self):
return self.name
@final
class ExampleMetaclassModel(TestBase, metaclass=EAVModelMeta):
name = models.CharField(max_length=MAX_CHARFIELD_LEN)
def __str__(self):
return self.name
@final
class RegisterTestModel(TestBase, metaclass=EAVModelMeta):
name = models.CharField(max_length=MAX_CHARFIELD_LEN)
def __str__(self):
return self.name

102
test_project/settings.py Normal file
View file

@ -0,0 +1,102 @@
from __future__ import annotations
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "secret!" # noqa: S105
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS: list[str] = []
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
# Test Project:
"test_project.apps.TestAppConfig",
# Our app:
"eav",
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
# Database
# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": ":memory:",
},
}
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
EAV2_PRIMARY_KEY_FIELD = "django.db.models.AutoField"
# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = []
# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_L10N = True
USE_TZ = False
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.1/howto/static-files/
STATIC_URL = "/static/"

View file

@ -1,76 +0,0 @@
from django.core.exceptions import ValidationError
from django.test import TestCase
import eav
from eav.exceptions import IllegalAssignmentException
from eav.models import Attribute, Value
from eav.registry import EavConfig
from .models import Encounter, Patient
class Attributes(TestCase):
def setUp(self):
class EncounterEavConfig(EavConfig):
manager_attr = 'eav_objects'
eav_attr = 'eav_field'
generic_relation_attr = 'encounter_eav_values'
generic_relation_related_name = 'encounters'
@classmethod
def get_attributes(cls):
return Attribute.objects.filter(slug__contains='a')
eav.register(Encounter, EncounterEavConfig)
eav.register(Patient)
Attribute.objects.create(name='age', datatype=Attribute.TYPE_INT)
Attribute.objects.create(name='height', datatype=Attribute.TYPE_FLOAT)
Attribute.objects.create(name='weight', datatype=Attribute.TYPE_FLOAT)
Attribute.objects.create(name='color', datatype=Attribute.TYPE_TEXT)
def tearDown(self):
eav.unregister(Encounter)
eav.unregister(Patient)
def test_get_attribute_querysets(self):
self.assertEqual(Patient._eav_config_cls.get_attributes().count(), 4)
self.assertEqual(Encounter._eav_config_cls.get_attributes().count(), 1)
def test_duplicate_attributs(self):
'''
Ensure that no two Attributes with the same slug can exist.
'''
with self.assertRaises(ValidationError):
Attribute.objects.create(name='height', datatype=Attribute.TYPE_FLOAT)
def test_setting_attributes(self):
p = Patient.objects.create(name='Jon')
e = Encounter.objects.create(patient=p, num=1)
p.eav.age = 3
p.eav.height = 2.3
p.save()
e.eav_field.age = 4
e.save()
self.assertEqual(Value.objects.count(), 3)
p = Patient.objects.get(name='Jon')
self.assertEqual(p.eav.age, 3)
self.assertEqual(p.eav.height, 2.3)
e = Encounter.objects.get(num=1)
self.assertEqual(e.eav_field.age, 4)
def test_illegal_assignemnt(self):
class EncounterEavConfig(EavConfig):
@classmethod
def get_attributes(cls):
return Attribute.objects.filter(datatype=Attribute.TYPE_INT)
eav.unregister(Encounter)
eav.register(Encounter, EncounterEavConfig)
p = Patient.objects.create(name='Jon')
e = Encounter.objects.create(patient=p, num=1)
with self.assertRaises(IllegalAssignmentException):
e.eav.color = 'red'
e.save()

View file

@ -1,190 +0,0 @@
from django.utils import timezone
from django.test import TestCase
from django.core.exceptions import ValidationError
from django.contrib.auth.models import User
import eav
from eav.models import Attribute, Value, EnumValue, EnumGroup
from .models import Patient
class DataValidation(TestCase):
def setUp(self):
eav.register(Patient)
Attribute.objects.create(name='Age', datatype=Attribute.TYPE_INT)
Attribute.objects.create(name='DoB', datatype=Attribute.TYPE_DATE)
Attribute.objects.create(name='Height', datatype=Attribute.TYPE_FLOAT)
Attribute.objects.create(name='City', datatype=Attribute.TYPE_TEXT)
Attribute.objects.create(name='Pregnant?', datatype=Attribute.TYPE_BOOLEAN)
Attribute.objects.create(name='User', datatype=Attribute.TYPE_OBJECT)
def tearDown(self):
eav.unregister(Patient)
def test_required_field(self):
p = Patient(name='Bob')
p.eav.age = 5
p.save()
Attribute.objects.create(name='Weight', datatype=Attribute.TYPE_INT, required=True)
p.eav.age = 6
self.assertRaises(ValidationError, p.save)
p = Patient.objects.get(name='Bob')
self.assertEqual(p.eav.age, 5)
p.eav.weight = 23
p.save()
p = Patient.objects.get(name='Bob')
self.assertEqual(p.eav.weight, 23)
def test_create_required_field(self):
Attribute.objects.create(name='Weight', datatype=Attribute.TYPE_INT, required=True)
self.assertRaises(ValidationError,
Patient.objects.create,
name='Joe', eav__age=5)
self.assertEqual(Patient.objects.count(), 0)
self.assertEqual(Value.objects.count(), 0)
Patient.objects.create(name='Joe', eav__weight=2, eav__age=5)
self.assertEqual(Patient.objects.count(), 1)
self.assertEqual(Value.objects.count(), 2)
def test_validation_error_create(self):
self.assertRaises(ValidationError,
Patient.objects.create,
name='Joe', eav__age='df')
self.assertEqual(Patient.objects.count(), 0)
self.assertEqual(Value.objects.count(), 0)
def test_bad_slug(self):
a = Attribute.objects.create(name='color', datatype=Attribute.TYPE_TEXT)
a.slug = 'Color'
self.assertRaises(ValidationError, a.save)
a.slug = '1st'
self.assertRaises(ValidationError, a.save)
a.slug = '_st'
self.assertRaises(ValidationError, a.save)
def test_changing_datatypes(self):
a = Attribute.objects.create(name='Color', datatype=Attribute.TYPE_INT)
a.datatype = Attribute.TYPE_TEXT
a.save()
Patient.objects.create(name='Bob', eav__color='brown')
a.datatype = Attribute.TYPE_INT
self.assertRaises(ValidationError, a.save)
def test_int_validation(self):
p = Patient.objects.create(name='Joe')
p.eav.age = 'bad'
self.assertRaises(ValidationError, p.save)
p.eav.age = 15
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.age, 15)
def test_date_validation(self):
p = Patient.objects.create(name='Joe')
p.eav.dob = '12'
self.assertRaises(ValidationError, lambda: p.save())
p.eav.dob = 15
self.assertRaises(ValidationError, lambda: p.save())
now = timezone.now()
p.eav.dob = now
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.dob, now)
today = timezone.now().date()
p.eav.dob = today
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.dob.date(), today)
def test_float_validation(self):
p = Patient.objects.create(name='Joe')
p.eav.height = 'bad'
self.assertRaises(ValidationError, p.save)
p.eav.height = 15
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.height, 15)
p.eav.height='2.3'
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.height, 2.3)
def test_text_validation(self):
p = Patient.objects.create(name='Joe')
p.eav.city = 5
self.assertRaises(ValidationError, p.save)
p.eav.city = 'El Dorado'
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.city, 'El Dorado')
def test_bool_validation(self):
p = Patient.objects.create(name='Joe')
p.eav.pregnant = 5
self.assertRaises(ValidationError, p.save)
p.eav.pregnant = True
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.pregnant, True)
def test_object_validation(self):
p = Patient.objects.create(name='Joe')
p.eav.user = 5
self.assertRaises(ValidationError, p.save)
p.eav.user = object
self.assertRaises(ValidationError, p.save)
p.eav.user = User(username='joe')
self.assertRaises(ValidationError, p.save)
u = User.objects.create(username='joe')
p.eav.user = u
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.user, u)
def test_enum_validation(self):
yes = EnumValue.objects.create(value='yes')
no = EnumValue.objects.create(value='no')
unkown = EnumValue.objects.create(value='unkown')
green = EnumValue.objects.create(value='green')
ynu = EnumGroup.objects.create(name='Yes / No / Unknown')
ynu.enums.add(yes)
ynu.enums.add(no)
ynu.enums.add(unkown)
Attribute.objects.create(name='Fever?', datatype=Attribute.TYPE_ENUM, enum_group=ynu)
p = Patient.objects.create(name='Joe')
p.eav.fever = 5
self.assertRaises(ValidationError, p.save)
p.eav.fever = object
self.assertRaises(ValidationError, p.save)
p.eav.fever = 'yes'
self.assertRaises(ValidationError, p.save)
p.eav.fever = green
self.assertRaises(ValidationError, p.save)
p.eav.fever = EnumValue(value='yes')
self.assertRaises(ValidationError, p.save)
p.eav.fever = no
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.fever, no)
def test_enum_datatype_without_enum_group(self):
a = Attribute(name='Age Bracket', datatype=Attribute.TYPE_ENUM)
self.assertRaises(ValidationError, a.save)
yes = EnumValue.objects.create(value='yes')
no = EnumValue.objects.create(value='no')
unkown = EnumValue.objects.create(value='unkown')
ynu = EnumGroup.objects.create(name='Yes / No / Unknown')
ynu.enums.add(yes)
ynu.enums.add(no)
ynu.enums.add(unkown)
a = Attribute(name='Age Bracket', datatype=Attribute.TYPE_ENUM, enum_group=ynu)
a.save()
def test_enum_group_on_other_datatype(self):
yes = EnumValue.objects.create(value='yes')
no = EnumValue.objects.create(value='no')
unkown = EnumValue.objects.create(value='unkown')
ynu = EnumGroup.objects.create(name='Yes / No / Unknown')
ynu.enums.add(yes)
ynu.enums.add(no)
ynu.enums.add(unkown)
a = Attribute(name='color', datatype=Attribute.TYPE_TEXT, enum_group=ynu)
self.assertRaises(ValidationError, a.save)

View file

@ -1,92 +0,0 @@
from django.test import TestCase
from django.contrib.admin.sites import AdminSite
import eav
from eav.admin import *
from .models import Patient, M2MModel, ExampleModel
from eav.models import Attribute
from eav.forms import BaseDynamicEntityForm
from django.contrib import admin
from django.core.handlers.base import BaseHandler
from django.test.client import RequestFactory
from django.forms import ModelForm
class MockRequest(RequestFactory):
def request(self, **request):
"Construct a generic request object."
request = RequestFactory.request(self, **request)
handler = BaseHandler()
handler.load_middleware()
for middleware_method in handler._request_middleware:
if middleware_method(request):
raise Exception("Couldn't create request mock object - "
"request middleware returned a response")
return request
class MockSuperUser:
def __init__(self):
self.is_active = True
self.is_staff = True
def has_perm(self, perm):
return True
request = MockRequest().request()
request.user = MockSuperUser()
class PatientForm(ModelForm):
class Meta:
model = Patient
fields = '__all__'
class M2MModelForm(ModelForm):
class Meta:
model = M2MModel
fields = '__all__'
class Forms(TestCase):
def setUp(self):
eav.register(Patient)
Attribute.objects.create(name='weight', datatype=Attribute.TYPE_FLOAT)
Attribute.objects.create(name='color', datatype=Attribute.TYPE_TEXT)
self.instance = Patient.objects.create(name='Jim Morrison')
self.site = AdminSite()
def test_fields(self):
admin = BaseEntityAdmin(Patient, self.site)
admin.form = BaseDynamicEntityForm
view = admin.change_view(request, str(self.instance.pk))
own_fields = 1
adminform = view.context_data['adminform']
self.assertEqual(
len(adminform.form.fields), Attribute.objects.count() + own_fields
)
def test_valid_submit(self):
self.instance.eav.color = 'Blue'
form = PatientForm(self.instance.__dict__, instance=self.instance)
jim = form.save()
self.assertEqual(jim.eav.color, 'Blue')
def test_invalid_submit(self):
form = PatientForm(dict(color='Blue'), instance=self.instance)
with self.assertRaises(ValueError):
jim = form.save()
def test_m2m(self):
m2mmodel = M2MModel.objects.create(name='name')
model = ExampleModel.objects.create(name='name')
form = M2MModelForm(dict(name='Lorem', models=[model.pk]), instance=m2mmodel)
form.save()
self.assertEqual(len(m2mmodel.models.all()), 1)

View file

@ -1,27 +0,0 @@
from django.test import TestCase
from eav.models import EnumGroup, Attribute, Value
import eav
from .models import Patient
class MiscModels(TestCase):
def test_enumgroup_str(self):
name = 'Yes / No'
e = EnumGroup.objects.create(name=name)
self.assertEqual('<EnumGroup Yes / No>', str(e))
def test_attribute_help_text(self):
desc = 'Patient Age'
a = Attribute.objects.create(name='age', description=desc, datatype=Attribute.TYPE_INT)
self.assertEqual(a.help_text, desc)
def test_setting_to_none_deletes_value(self):
eav.register(Patient)
Attribute.objects.create(name='age', datatype=Attribute.TYPE_INT)
p = Patient.objects.create(name='Bob', eav__age=5)
self.assertEqual(Value.objects.count(), 1)
p.eav.age = None
p.save()
self.assertEqual(Value.objects.count(), 0)

View file

@ -1,40 +0,0 @@
from django.db import models
from eav.decorators import register_eav
class Patient(models.Model):
name = models.CharField(max_length=12)
def __str__(self):
return self.name
def __repr__(self):
return self.name
class Encounter(models.Model):
num = models.PositiveSmallIntegerField()
patient = models.ForeignKey(Patient, on_delete=models.PROTECT)
def __str__(self):
return '%s: encounter num %d' % (self.patient, self.num)
def __repr__(self):
return self.name
@register_eav()
class ExampleModel(models.Model):
name = models.CharField(max_length=12)
def __unicode__(self):
return self.name
@register_eav()
class M2MModel(models.Model):
name = models.CharField(max_length=12)
models = models.ManyToManyField(ExampleModel)
def __unicode__(self):
return self.name

View file

@ -1,139 +0,0 @@
from django.core.exceptions import MultipleObjectsReturned
from django.db.models import Q
from django.test import TestCase
import eav
from eav.models import Attribute, EnumGroup, EnumValue, Value
from .models import Encounter, Patient
class Queries(TestCase):
def setUp(self):
eav.register(Encounter)
eav.register(Patient)
Attribute.objects.create(name='age', datatype=Attribute.TYPE_INT)
Attribute.objects.create(name='height', datatype=Attribute.TYPE_FLOAT)
Attribute.objects.create(name='weight', datatype=Attribute.TYPE_FLOAT)
Attribute.objects.create(name='city', datatype=Attribute.TYPE_TEXT)
Attribute.objects.create(name='country', datatype=Attribute.TYPE_TEXT)
self.yes = EnumValue.objects.create(value='yes')
self.no = EnumValue.objects.create(value='no')
self.unknown = EnumValue.objects.create(value='unknown')
ynu = EnumGroup.objects.create(name='Yes / No / Unknown')
ynu.enums.add(self.yes)
ynu.enums.add(self.no)
ynu.enums.add(self.unknown)
Attribute.objects.create(name='fever', datatype=Attribute.TYPE_ENUM, enum_group=ynu)
def tearDown(self):
eav.unregister(Encounter)
eav.unregister(Patient)
def test_get_or_create_with_eav(self):
Patient.objects.get_or_create(name='Bob', eav__age=5)
self.assertEqual(Patient.objects.count(), 1)
self.assertEqual(Value.objects.count(), 1)
Patient.objects.get_or_create(name='Bob', eav__age=5)
self.assertEqual(Patient.objects.count(), 1)
self.assertEqual(Value.objects.count(), 1)
Patient.objects.get_or_create(name='Bob', eav__age=6)
self.assertEqual(Patient.objects.count(), 2)
self.assertEqual(Value.objects.count(), 2)
def test_get_with_eav(self):
p1, _ = Patient.objects.get_or_create(name='Bob', eav__age=6)
self.assertEqual(Patient.objects.get(eav__age=6), p1)
Patient.objects.create(name='Fred', eav__age=6)
self.assertRaises(MultipleObjectsReturned, lambda: Patient.objects.get(eav__age=6))
def test_filtering_on_normal_and_eav_fields(self):
yes = self.yes
no = self.no
data = [
# Name, age, fever, city, country.
['Anne', 3, no, 'New York', 'USA'],
['Bob', 15, no, 'Bamako', 'Mali'],
['Cyrill', 15, yes, 'Kisumu', 'Kenya'],
['Daniel', 3, no, 'Nice', 'France'],
['Eugene', 2, yes, 'France', 'Nice']
]
for row in data:
Patient.objects.create(
name=row[0],
eav__age=row[1],
eav__fever=row[2],
eav__city=row[3],
eav__country=row[4]
)
# Check number of objects in DB.
self.assertEqual(Patient.objects.count(), 5)
self.assertEqual(Value.objects.count(), 20)
# Nobody
q1 = Q(eav__fever=yes) & Q(eav__fever=no)
p = Patient.objects.filter(q1)
self.assertEqual(p.count(), 0)
# Anne, Daniel
q1 = Q(eav__age__gte=3) # Everyone except Eugene
q2 = Q(eav__age__lt=15) # Anne, Daniel, Eugene
p = Patient.objects.filter(q2 & q1)
self.assertEqual(p.count(), 2)
# Anne
q1 = Q(eav__city__contains='Y') & Q(eav__fever=no)
q2 = Q(eav__age=3)
p = Patient.objects.filter(q1 & q2)
self.assertEqual(p.count(), 1)
# Anne, Daniel
q1 = Q(eav__city__contains='Y', eav__fever=no)
q2 = Q(eav__city='Nice')
q3 = Q(eav__age=3)
p = Patient.objects.filter((q1 | q2) & q3)
self.assertEqual(p.count(), 2)
# Everyone
q1 = Q(eav__fever=no) | Q(eav__fever=yes)
p = Patient.objects.filter(q1)
self.assertEqual(p.count(), 5)
# Anne, Bob, Daniel
q1 = Q(eav__fever=no) # Anne, Bob, Daniel
q2 = Q(eav__fever=yes) # Cyrill, Eugene
q3 = Q(eav__country__contains='e') # Cyrill, Daniel, Eugene
q4 = q2 & q3 # Cyrill, Daniel, Eugene
q5 = (q1 | q4) & q1 # Anne, Bob, Daniel
p = Patient.objects.filter(q5)
self.assertEqual(p.count(), 3)
# Everyone except Anne
q1 = Q(eav__city__contains='Y')
p = Patient.objects.exclude(q1)
self.assertEqual(p.count(), 4)
# Anne, Bob, Daniel
q1 = Q(eav__city__contains='Y')
q2 = Q(eav__fever=no)
q3 = q1 | q2
p = Patient.objects.filter(q3)
self.assertEqual(p.count(), 3)
# Anne, Daniel
q1 = Q(eav__age=3)
p = Patient.objects.filter(q1)
self.assertEqual(p.count(), 2)
# Eugene
q1 = Q(name__contains='E', eav__fever=yes)
p = Patient.objects.filter(q1)
self.assertEqual(p.count(), 1)

View file

@ -1,83 +0,0 @@
from django.test import TestCase
import eav
from eav.registry import EavConfig
from .models import Encounter, ExampleModel, Patient
class RegistryTests(TestCase):
def setUp(self):
pass
def tearDown(self):
pass
def register_encounter(self):
class EncounterEav(EavConfig):
manager_attr = 'eav_objects'
eav_attr = 'eav_field'
generic_relation_attr = 'encounter_eav_values'
generic_relation_related_name = 'encounters'
@classmethod
def get_attributes(cls):
return 'testing'
eav.register(Encounter, EncounterEav)
def test_registering_with_defaults(self):
eav.register(Patient)
self.assertTrue(hasattr(Patient, '_eav_config_cls'))
self.assertEqual(Patient._eav_config_cls.manager_attr, 'objects')
self.assertFalse(Patient._eav_config_cls.manager_only)
self.assertEqual(Patient._eav_config_cls.eav_attr, 'eav')
self.assertEqual(Patient._eav_config_cls.generic_relation_attr, 'eav_values')
self.assertEqual(Patient._eav_config_cls.generic_relation_related_name, None)
eav.unregister(Patient)
def test_registering_overriding_defaults(self):
eav.register(Patient)
self.register_encounter()
self.assertTrue(hasattr(Patient, '_eav_config_cls'))
self.assertEqual(Patient._eav_config_cls.manager_attr, 'objects')
self.assertEqual(Patient._eav_config_cls.eav_attr, 'eav')
self.assertTrue(hasattr(Encounter, '_eav_config_cls'))
self.assertEqual(Encounter._eav_config_cls.get_attributes(), 'testing')
self.assertEqual(Encounter._eav_config_cls.manager_attr, 'eav_objects')
self.assertEqual(Encounter._eav_config_cls.eav_attr, 'eav_field')
eav.unregister(Patient)
eav.unregister(Encounter)
def test_registering_via_decorator_with_defaults(self):
self.assertTrue(hasattr(ExampleModel, '_eav_config_cls'))
self.assertEqual(ExampleModel._eav_config_cls.manager_attr, 'objects')
self.assertEqual(ExampleModel._eav_config_cls.eav_attr, 'eav')
def test_unregistering(self):
old_mgr = Patient.objects
eav.register(Patient)
self.assertTrue(Patient.objects.__class__.__name__ == 'EntityManager')
eav.unregister(Patient)
self.assertFalse(Patient.objects.__class__.__name__ == 'EntityManager')
self.assertEqual(Patient.objects, old_mgr)
self.assertFalse(hasattr(Patient, '_eav_config_cls'))
def test_unregistering_via_decorator(self):
self.assertTrue(ExampleModel.objects.__class__.__name__ == 'EntityManager')
eav.unregister(ExampleModel)
self.assertFalse(ExampleModel.objects.__class__.__name__ == 'EntityManager')
def test_unregistering_unregistered_model_proceeds_silently(self):
eav.unregister(Patient)
def test_double_registering_model_is_harmless(self):
eav.register(Patient)
eav.register(Patient)
def test_doesnt_register_nonmodel(self):
with self.assertRaises(ValueError):
@eav.decorators.register_eav()
class Foo(object):
pass

183
tests/test_attributes.py Normal file
View file

@ -0,0 +1,183 @@
import string
import uuid
import pytest
from django.conf import settings as django_settings
from django.core.exceptions import ValidationError
from django.test import TestCase
from hypothesis import given, settings
from hypothesis import strategies as st
from hypothesis.extra import django
from hypothesis.strategies import just
import eav
from eav.exceptions import IllegalAssignmentException
from eav.models import Attribute, Value
from eav.registry import EavConfig
from test_project.models import Doctor, Encounter, Patient, RegisterTestModel
if django_settings.EAV2_PRIMARY_KEY_FIELD == "django.db.models.UUIDField":
auto_field_strategy = st.builds(uuid.uuid4, version=4, max_length=32)
elif django_settings.EAV2_PRIMARY_KEY_FIELD == "django.db.models.CharField":
auto_field_strategy = st.text(min_size=1, max_size=255)
else:
auto_field_strategy = st.integers(min_value=1, max_value=32)
class Attributes(TestCase):
def setUp(self):
class EncounterEavConfig(EavConfig):
manager_attr = "eav_objects"
eav_attr = "eav_field"
generic_relation_attr = "encounter_eav_values"
generic_relation_related_name = "encounters"
@classmethod
def get_attributes(cls, instance=None):
return Attribute.objects.filter(slug__contains="a")
eav.register(Encounter, EncounterEavConfig)
eav.register(Patient)
Attribute.objects.create(name="age", datatype=Attribute.TYPE_INT)
Attribute.objects.create(name="height", datatype=Attribute.TYPE_FLOAT)
Attribute.objects.create(name="weight", datatype=Attribute.TYPE_FLOAT)
Attribute.objects.create(name="color", datatype=Attribute.TYPE_TEXT)
def tearDown(self):
eav.unregister(Encounter)
eav.unregister(Patient)
def test_get_attribute_querysets(self):
self.assertEqual(Patient._eav_config_cls.get_attributes().count(), 4)
self.assertEqual(Encounter._eav_config_cls.get_attributes().count(), 1)
def test_duplicate_attributs(self):
"""
Ensure that no two Attributes with the same slug can exist.
"""
with self.assertRaises(ValidationError):
Attribute.objects.create(name="height", datatype=Attribute.TYPE_FLOAT)
def test_setting_attributes(self):
p = Patient.objects.create(name="Jon")
e = Encounter.objects.create(patient=p, num=1)
p.eav.age = 3
p.eav.height = 2.3
p.save()
e.eav_field.age = 4
e.save()
self.assertEqual(Value.objects.count(), 3)
t = RegisterTestModel.objects.create(name="test")
t.eav.age = 6
t.eav.height = 10
t.save()
p = Patient.objects.get(name="Jon")
self.assertEqual(p.eav.age, 3)
self.assertEqual(p.eav.height, 2.3)
e = Encounter.objects.get(num=1)
self.assertEqual(e.eav_field.age, 4)
t = RegisterTestModel.objects.get(name="test")
self.assertEqual(t.eav.age, 6)
self.assertEqual(t.eav.height, 10)
# Validate repr of Value for an entity with an INT PK
v1 = Value.objects.filter(entity_id=p.pk).first()
assert isinstance(repr(v1), str)
assert isinstance(str(v1), str)
def test_illegal_assignemnt(self):
class EncounterEavConfig(EavConfig):
@classmethod
def get_attributes(cls, instance=None):
return Attribute.objects.filter(datatype=Attribute.TYPE_INT)
eav.unregister(Encounter)
eav.register(Encounter, EncounterEavConfig)
p = Patient.objects.create(name="Jon")
e = Encounter.objects.create(patient=p, num=1)
with self.assertRaises(IllegalAssignmentException):
e.eav.color = "red"
e.save()
def test_uuid_pk(self):
"""Tests for when model pk is UUID."""
expected_age = 10
d1 = Doctor.objects.create(name="Lu")
d1.eav.age = expected_age
d1.save()
assert d1.eav.age == expected_age
# Validate repr of Value for an entity with a UUID PK
v1 = Value.objects.filter(entity_uuid=d1.pk).first()
assert isinstance(repr(v1), str)
assert isinstance(str(v1), str)
def test_big_integer(self):
"""Tests an integer larger than 32-bit a value."""
big_num = 3147483647
patient = Patient.objects.create(name="Jon")
patient.eav.age = big_num
patient.save()
assert patient.eav.age == big_num
class TestAttributeModel(django.TestCase):
"""This is a property-based test that ensures model correctness."""
@given(
django.from_model(
Attribute,
id=auto_field_strategy,
datatype=just(Attribute.TYPE_TEXT),
enum_group=just(None),
slug=just(None), # Let Attribute.save() handle
),
)
@settings(deadline=None)
def test_model_properties(self, attribute: Attribute) -> None:
"""Tests that instance can be saved and has correct representation."""
attribute.full_clean()
attribute.save()
assert attribute
@given(
st.text(
alphabet=st.sampled_from(string.ascii_letters + string.digits),
min_size=50,
max_size=100,
),
)
def test_large_name_input(self, name_value) -> None:
"""Ensure proper slug is generated from large name fields."""
instance = Attribute.objects.create(
name=name_value,
datatype=Attribute.TYPE_TEXT,
enum_group=None,
)
assert isinstance(instance, Attribute)
@pytest.mark.django_db
def test_attribute_create_with_invalid_slug() -> None:
"""
Test that creating an Attribute with an invalid slug raises a UserWarning.
This test ensures that when an Attribute is created with a slug that is not
a valid Python identifier, a UserWarning is raised. The warning should
indicate that the slug is invalid and suggest updating it.
"""
with pytest.warns(UserWarning):
Attribute.objects.create(
name="Test Attribute",
slug="123-invalid",
datatype=Attribute.TYPE_TEXT,
)

View file

@ -0,0 +1,216 @@
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.test import TestCase
from django.utils import timezone
import eav
from eav.models import Attribute, EnumGroup, EnumValue, Value
from test_project.models import Patient
class DataValidation(TestCase):
def setUp(self):
eav.register(Patient)
Attribute.objects.create(name="Age", datatype=Attribute.TYPE_INT)
Attribute.objects.create(name="DoB", datatype=Attribute.TYPE_DATE)
Attribute.objects.create(name="Height", datatype=Attribute.TYPE_FLOAT)
Attribute.objects.create(name="City", datatype=Attribute.TYPE_TEXT)
Attribute.objects.create(name="Pregnant", datatype=Attribute.TYPE_BOOLEAN)
Attribute.objects.create(name="User", datatype=Attribute.TYPE_OBJECT)
Attribute.objects.create(name="Extra", datatype=Attribute.TYPE_JSON)
Attribute.objects.create(name="Multi", datatype=Attribute.TYPE_CSV)
def tearDown(self):
eav.unregister(Patient)
def test_required_field(self):
p = Patient(name="Bob")
p.eav.age = 5
p.save()
Attribute.objects.create(
name="Weight",
datatype=Attribute.TYPE_INT,
required=True,
)
p.eav.age = 6
self.assertRaises(ValidationError, p.save)
p = Patient.objects.get(name="Bob")
self.assertEqual(p.eav.age, 5)
p.eav.weight = 23
p.save()
p = Patient.objects.get(name="Bob")
self.assertEqual(p.eav.weight, 23)
def test_create_required_field(self):
Attribute.objects.create(
name="Weight",
datatype=Attribute.TYPE_INT,
required=True,
)
self.assertRaises(
ValidationError,
Patient.objects.create,
name="Joe",
eav__age=5,
)
self.assertEqual(Patient.objects.count(), 0)
self.assertEqual(Value.objects.count(), 0)
Patient.objects.create(name="Joe", eav__weight=2, eav__age=5)
self.assertEqual(Patient.objects.count(), 1)
self.assertEqual(Value.objects.count(), 2)
def test_validation_error_create(self):
self.assertRaises(
ValidationError,
Patient.objects.create,
name="Joe",
eav__age="df",
)
self.assertEqual(Patient.objects.count(), 0)
self.assertEqual(Value.objects.count(), 0)
def test_changing_datatypes(self):
a = Attribute.objects.create(name="Color", datatype=Attribute.TYPE_INT)
a.datatype = Attribute.TYPE_TEXT
a.save()
Patient.objects.create(name="Bob", eav__color="brown")
a.datatype = Attribute.TYPE_INT
self.assertRaises(ValidationError, a.save)
def test_int_validation(self):
p = Patient.objects.create(name="Joe")
p.eav.age = "bad"
self.assertRaises(ValidationError, p.save)
p.eav.age = 15
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.age, 15)
def test_date_validation(self):
p = Patient.objects.create(name="Joe")
p.eav.dob = "12"
self.assertRaises(ValidationError, lambda: p.save())
p.eav.dob = 15
self.assertRaises(ValidationError, lambda: p.save())
now = timezone.now()
p.eav.dob = now
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.dob, now)
today = timezone.now().date()
p.eav.dob = today
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.dob.date(), today)
def test_float_validation(self):
p = Patient.objects.create(name="Joe")
p.eav.height = "bad"
self.assertRaises(ValidationError, p.save)
p.eav.height = 15
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.height, 15)
p.eav.height = "2.3"
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.height, 2.3)
def test_text_validation(self):
p = Patient.objects.create(name="Joe")
p.eav.city = 5
self.assertRaises(ValidationError, p.save)
p.eav.city = "El Dorado"
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.city, "El Dorado")
def test_bool_validation(self):
p = Patient.objects.create(name="Joe")
p.eav.pregnant = 5
self.assertRaises(ValidationError, p.save)
p.eav.pregnant = True
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.pregnant, True)
def test_object_validation(self):
p = Patient.objects.create(name="Joe")
p.eav.user = 5
self.assertRaises(ValidationError, p.save)
p.eav.user = object
self.assertRaises(ValidationError, p.save)
p.eav.user = User(username="joe")
self.assertRaises(ValidationError, p.save)
u = User.objects.create(username="joe")
p.eav.user = u
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.user, u)
def test_enum_validation(self):
yes = EnumValue.objects.create(value="yes")
no = EnumValue.objects.create(value="no")
unkown = EnumValue.objects.create(value="unkown")
green = EnumValue.objects.create(value="green")
ynu = EnumGroup.objects.create(name="Yes / No / Unknown")
ynu.values.add(yes)
ynu.values.add(no)
ynu.values.add(unkown)
Attribute.objects.create(
name="Fever",
datatype=Attribute.TYPE_ENUM,
enum_group=ynu,
)
p = Patient.objects.create(name="Joe")
p.eav.fever = 5
self.assertRaises(ValidationError, p.save)
p.eav.fever = object
self.assertRaises(ValidationError, p.save)
p.eav.fever = green
self.assertRaises(ValidationError, p.save)
p.eav.fever = EnumValue(value="yes")
self.assertRaises(ValidationError, p.save)
p.eav.fever = no
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.fever, no)
def test_enum_datatype_without_enum_group(self):
a = Attribute(name="Age Bracket", datatype=Attribute.TYPE_ENUM)
self.assertRaises(ValidationError, a.save)
yes = EnumValue.objects.create(value="yes")
no = EnumValue.objects.create(value="no")
unkown = EnumValue.objects.create(value="unkown")
ynu = EnumGroup.objects.create(name="Yes / No / Unknown")
ynu.values.add(yes)
ynu.values.add(no)
ynu.values.add(unkown)
a = Attribute(name="Age Bracket", datatype=Attribute.TYPE_ENUM, enum_group=ynu)
a.save()
def test_enum_group_on_other_datatype(self):
yes = EnumValue.objects.create(value="yes")
no = EnumValue.objects.create(value="no")
unkown = EnumValue.objects.create(value="unkown")
ynu = EnumGroup.objects.create(name="Yes / No / Unknown")
ynu.values.add(yes)
ynu.values.add(no)
ynu.values.add(unkown)
a = Attribute(name="color", datatype=Attribute.TYPE_TEXT, enum_group=ynu)
self.assertRaises(ValidationError, a.save)
def test_json_validation(self):
p = Patient.objects.create(name="Joe")
p.eav.extra = 5
self.assertRaises(ValidationError, p.save)
p.eav.extra = {"eyes": "blue", "hair": "brown"}
p.save()
self.assertEqual(Patient.objects.get(pk=p.pk).eav.extra.get("eyes", ""), "blue")
def test_csv_validation(self):
yes = EnumValue.objects.create(value="yes")
p = Patient.objects.create(name="Mike")
p.eav.multi = yes
self.assertRaises(ValidationError, p.save)
p.eav.multi = "one;two;three"
p.save()
self.assertEqual(
Patient.objects.get(pk=p.pk).eav.multi,
["one", "two", "three"],
)

251
tests/test_forms.py Normal file
View file

@ -0,0 +1,251 @@
import pytest
from django.contrib.admin.sites import AdminSite
from django.core.handlers.base import BaseHandler
from django.forms import ModelForm
from django.test import TestCase
from django.test.client import RequestFactory
import eav
from eav.admin import BaseEntityAdmin
from eav.forms import BaseDynamicEntityForm
from eav.models import Attribute, EnumGroup, EnumValue
from test_project.models import ExampleModel, M2MModel, Patient
class MockRequest(RequestFactory):
def request(self, **request):
"Construct a generic request object."
request = RequestFactory.request(self, **request)
handler = BaseHandler()
handler.load_middleware()
return request
class MockSuperUser:
def __init__(self):
self.is_active = True
self.is_staff = True
def has_perm(self, perm):
return True
request = MockRequest().request()
request.user = MockSuperUser()
class PatientForm(ModelForm):
class Meta:
model = Patient
fields = ("name", "email", "example")
class PatientDynamicForm(BaseDynamicEntityForm):
class Meta:
model = Patient
fields = ("name", "email", "example")
class M2MModelForm(ModelForm):
class Meta:
model = M2MModel
fields = ("name", "models")
class Forms(TestCase):
def setUp(self):
eav.register(Patient)
Attribute.objects.create(name="weight", datatype=Attribute.TYPE_FLOAT)
Attribute.objects.create(name="color", datatype=Attribute.TYPE_TEXT)
self.female = EnumValue.objects.create(value="Female")
self.male = EnumValue.objects.create(value="Male")
gender_group = EnumGroup.objects.create(name="Gender")
gender_group.values.add(self.female, self.male)
Attribute.objects.create(
name="gender",
datatype=Attribute.TYPE_ENUM,
enum_group=gender_group,
)
self.instance = Patient.objects.create(name="Jim Morrison")
def test_valid_submit(self):
self.instance.eav.color = "Blue"
form = PatientForm(self.instance.__dict__, instance=self.instance)
jim = form.save()
self.assertEqual(jim.eav.color, "Blue")
def test_invalid_submit(self):
form = PatientForm({"color": "Blue"}, instance=self.instance)
with self.assertRaises(ValueError):
form.save()
def test_valid_enums(self):
self.instance.eav.gender = self.female
form = PatientForm(self.instance.__dict__, instance=self.instance)
rose = form.save()
self.assertEqual(rose.eav.gender, self.female)
def test_m2m(self):
m2mmodel = M2MModel.objects.create(name="name")
model = ExampleModel.objects.create(name="name")
form = M2MModelForm({"name": "Lorem", "models": [model.pk]}, instance=m2mmodel)
form.save()
self.assertEqual(len(m2mmodel.models.all()), 1)
@pytest.fixture
def patient() -> Patient:
"""Return an eav enabled Patient instance."""
eav.register(Patient)
return Patient.objects.create(name="Jim Morrison")
@pytest.fixture
def create_attributes() -> None:
"""Create some Attributes to use for testing."""
Attribute.objects.create(name="weight", datatype=Attribute.TYPE_FLOAT)
Attribute.objects.create(name="color", datatype=Attribute.TYPE_TEXT)
@pytest.mark.django_db
@pytest.mark.parametrize(
("csv_data", "separator"),
[
("", ";"),
("justone", ","),
("one;two;three", ";"),
("alpha,beta,gamma", ","),
(None, ","),
],
)
def test_csvdynamicform(patient, csv_data, separator) -> None:
"""Ensure that a TYPE_CSV field works correctly with forms."""
Attribute.objects.create(name="csv", datatype=Attribute.TYPE_CSV)
patient.eav.csv = csv_data
patient.save()
patient.refresh_from_db()
form = PatientDynamicForm(
patient.__dict__,
instance=patient,
)
form.fields["csv"].separator = separator
assert form.is_valid()
jim = form.save()
expected_result = str(csv_data).split(separator) if csv_data else []
assert jim.eav.csv == expected_result
@pytest.mark.django_db
def test_csvdynamicform_empty(patient) -> None:
"""Test to ensure an instance with no eav values is correct."""
form = PatientDynamicForm(
patient.__dict__,
instance=patient,
)
assert form.is_valid()
assert form.save()
@pytest.mark.django_db
@pytest.mark.usefixtures("create_attributes")
@pytest.mark.parametrize("define_fieldsets", [True, False])
def test_entity_admin_form(patient, define_fieldsets):
"""Test the BaseEntityAdmin form setup and dynamic fieldsets handling."""
admin = BaseEntityAdmin(Patient, AdminSite())
admin.readonly_fields = ("email",)
admin.form = BaseDynamicEntityForm
expected_fieldsets = 2
if define_fieldsets:
# Use all fields in Patient model
admin.fieldsets = (
(None, {"fields": ["name", "example"]}),
("Contact Info", {"fields": ["email"]}),
)
expected_fieldsets = 3
view = admin.change_view(request, str(patient.pk))
adminform = view.context_data["adminform"]
# Count the total fields in fieldsets
total_fields = sum(
len(fields_info["fields"]) for _, fields_info in adminform.fieldsets
)
# 3 for 'name', 'email', 'example'
expected_fields_count = Attribute.objects.count() + 3
assert total_fields == expected_fields_count
# Ensure our fieldset count is correct
assert len(adminform.fieldsets) == expected_fieldsets
@pytest.mark.django_db
def test_entity_admin_form_no_attributes(patient):
"""Test the BaseEntityAdmin form with no Attributes created."""
admin = BaseEntityAdmin(Patient, AdminSite())
admin.readonly_fields = ("email",)
admin.form = BaseDynamicEntityForm
# Only fields defined in Patient model
expected_fields = 3
view = admin.change_view(request, str(patient.pk))
adminform = view.context_data["adminform"]
# Count the total fields in fieldsets
total_fields = sum(
len(fields_info["fields"]) for _, fields_info in adminform.fieldsets
)
# 3 for 'name', 'email', 'example'
assert total_fields == expected_fields
@pytest.mark.django_db
def test_dynamic_form_renders_enum_choices():
"""
Test that enum choices render correctly in BaseDynamicEntityForm.
This test verifies the fix for issue #648 where enum choices weren't
rendering correctly in Django 4.2.17 due to QuerySet unpacking issues.
"""
# Setup
eav.register(Patient)
# Create enum values and group
female = EnumValue.objects.create(value="Female")
male = EnumValue.objects.create(value="Male")
gender_group = EnumGroup.objects.create(name="Gender")
gender_group.values.add(female, male)
Attribute.objects.create(
name="gender",
datatype=Attribute.TYPE_ENUM,
enum_group=gender_group,
)
# Create a patient
patient = Patient.objects.create(name="Test Patient")
# Initialize the dynamic form
form = PatientDynamicForm(instance=patient)
# Test rendering - should not raise any exceptions
rendered_form = form.as_p()
# Verify the form rendered and contains the enum choices
assert 'name="gender"' in rendered_form
assert f'value="{female.pk}">{female.value}' in rendered_form
assert f'value="{male.pk}">{male.value}' in rendered_form

76
tests/test_logic.py Normal file
View file

@ -0,0 +1,76 @@
import pytest
from hypothesis import given
from hypothesis import strategies as st
from eav.logic.slug import SLUGFIELD_MAX_LENGTH, generate_slug
@given(st.text())
def test_generate_slug(name: str) -> None:
"""Ensures slug generation works properly."""
slug = generate_slug(name)
assert slug
@given(st.text(min_size=SLUGFIELD_MAX_LENGTH))
def test_generate_long_slug_text(name: str) -> None:
"""Ensures a slug isn't generated longer than maximum allowed length."""
slug = generate_slug(name)
assert len(slug) <= SLUGFIELD_MAX_LENGTH
def test_generate_slug_uniqueness() -> None:
"""Test that generate_slug() produces unique slugs for different inputs.
This test ensures that even similar inputs result in unique slugs,
and that the number of unique slugs matches the number of inputs.
"""
inputs = ["age #", "age %", "age $", "age @", "age!", "age?", "age 😊"]
generated_slugs: dict[str, str] = {}
for input_str in inputs:
slug = generate_slug(input_str)
assert slug not in generated_slugs.values(), (
f"Duplicate slug '{slug}' generated for input '{input_str}'"
)
generated_slugs[input_str] = slug
assert len(generated_slugs) == len(
inputs,
), "Number of unique slugs doesn't match number of inputs"
@pytest.mark.parametrize(
"input_str",
[
"01 age",
"? age",
"age 😊",
"class",
"def function",
"2nd place",
"@username",
"user-name",
"first.last",
"snake_case",
"CamelCase",
" ", # Empty
],
)
def test_generate_slug_valid_identifier(input_str: str) -> None:
"""Test that generate_slug() produces valid Python identifiers.
This test ensures that the generated slugs are valid Python identifiers
for a variety of input strings, including those with numbers, special
characters, emojis, and different naming conventions.
Args:
input_str (str): The input string to test.
"""
slug = generate_slug(input_str)
assert slug.isidentifier(), (
f"Generated slug '{slug}' for input '{input_str}' "
+ "is not a valid Python identifier"
)

70
tests/test_misc_models.py Normal file
View file

@ -0,0 +1,70 @@
import pytest
from django.test import TestCase
import eav
from eav.models import Attribute, EnumGroup, EnumValue, Value
from test_project.models import Patient
@pytest.fixture
def enumgroup(db):
"""Sample `EnumGroup` object for testing."""
test_group = EnumGroup.objects.create(name="Yes / No")
value_yes = EnumValue.objects.create(value="Yes")
value_no = EnumValue.objects.create(value="No")
test_group.values.add(value_yes)
test_group.values.add(value_no)
return test_group
def test_enumgroup_display(enumgroup):
"""Test repr() and str() of EnumGroup."""
assert f"<EnumGroup {enumgroup.name}>" == repr(enumgroup)
assert str(enumgroup) == str(enumgroup.name)
def test_enumvalue_display(enumgroup):
"""Test repr() and str() of EnumValue."""
test_value = enumgroup.values.first()
assert f"<EnumValue {test_value.value}>" == repr(test_value)
assert str(test_value) == test_value.value
class MiscModels(TestCase):
"""Miscellaneous tests on models."""
def test_attribute_help_text(self):
desc = "Patient Age"
a = Attribute.objects.create(
name="age",
description=desc,
datatype=Attribute.TYPE_INT,
)
self.assertEqual(a.help_text, desc)
def test_setting_to_none_deletes_value(self):
eav.register(Patient)
Attribute.objects.create(name="age", datatype=Attribute.TYPE_INT)
p = Patient.objects.create(name="Bob", eav__age=5)
self.assertEqual(Value.objects.count(), 1)
p.eav.age = None
p.save()
self.assertEqual(Value.objects.count(), 0)
def test_string_enum_value_assignment(self):
yes = EnumValue.objects.create(value="yes")
no = EnumValue.objects.create(value="no")
ynu = EnumGroup.objects.create(name="Yes / No / Unknown")
ynu.values.add(yes)
ynu.values.add(no)
Attribute.objects.create(
name="is_patient",
datatype=Attribute.TYPE_ENUM,
enum_group=ynu,
)
eav.register(Patient)
p = Patient.objects.create(name="Joe")
p.eav.is_patient = "yes"
p.save()
p = Patient.objects.get(name="Joe") # get from DB again
self.assertEqual(p.eav.is_patient, yes)

View file

@ -0,0 +1,52 @@
from django.test import TestCase
import eav
from eav.models import Attribute, EnumGroup, EnumValue, Value
from test_project.models import Patient
class ModelTest(TestCase):
def setUp(self):
eav.register(Patient)
Attribute.objects.create(name="age", datatype=Attribute.TYPE_INT)
Attribute.objects.create(name="height", datatype=Attribute.TYPE_FLOAT)
Attribute.objects.create(name="weight", datatype=Attribute.TYPE_FLOAT)
Attribute.objects.create(name="color", datatype=Attribute.TYPE_TEXT)
EnumGroup.objects.create(name="Yes / No")
EnumValue.objects.create(value="yes")
EnumValue.objects.create(value="no")
EnumValue.objects.create(value="unknown")
def test_attr_natural_keys(self):
attr = Attribute.objects.get(name="age")
attr_natural_key = attr.natural_key()
attr_retrieved_model = Attribute.objects.get_by_natural_key(*attr_natural_key)
self.assertEqual(attr_retrieved_model, attr)
def test_value_natural_keys(self):
p = Patient.objects.create(name="Jon")
p.eav.age = 5
p.save()
val = p.eav_values.first()
value_natural_key = val.natural_key()
value_retrieved_model = Value.objects.get_by_natural_key(*value_natural_key)
self.assertEqual(value_retrieved_model, val)
def test_enum_group_natural_keys(self):
enum_group = EnumGroup.objects.first()
enum_group_natural_key = enum_group.natural_key()
enum_group_retrieved_model = EnumGroup.objects.get_by_natural_key(
*enum_group_natural_key,
)
self.assertEqual(enum_group_retrieved_model, enum_group)
def test_enum_value_natural_keys(self):
enum_value = EnumValue.objects.first()
enum_value_natural_key = enum_value.natural_key()
enum_value_retrieved_model = EnumValue.objects.get_by_natural_key(
*enum_value_natural_key,
)
self.assertEqual(enum_value_retrieved_model, enum_value)

Some files were not shown because too many files have changed in this diff Show more