Skip to content

Commit

Permalink
Support Django 5.0 and Python 3.12
Browse files Browse the repository at this point in the history
  • Loading branch information
adamchainz committed Oct 16, 2023
1 parent 50e590a commit de937ce
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 52 deletions.
20 changes: 10 additions & 10 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,27 @@ jobs:
python-version:
- "3.8"
- "3.9"
django-version:
- "3.2"
- "4.0"
- "4.1"
- "4.2"
- "3.10"
- "3.11"
- "3.12"

steps:
- uses: actions/checkout@v3

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies (django ${{ matrix.django-version }})

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pyyaml coveralls pytest-django django==${{ matrix.django-version }}.*
pip install -e .
pip install flake8
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
- name: Test with pytest
run: |
coverage run $(which pytest) --ds=test_settings typedmodels/tests.py
tox run -f py$(echo ${{ matrix.python-version }} | tr -d .)
7 changes: 6 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@

Backward-incompatible changes for released versions are listed here (for 0.5 onwards.)

* Added support for Django 4.2.
* Added support for Django 4.2 and 5.0.

* Added support for Python 3.12.

* Dropped the `VERSION` and `__version__` attributes. To check the version of the package, use `importlib.metadata.version("django-typed-models")` ([docs](https://docs.python.org/3/library/importlib.metadata.html#distribution-versions) /
[backport](https://pypi.org/project/importlib-metadata/)).

## 0.13

Expand Down
4 changes: 4 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def read_relative_file(filename):
"Framework :: Django :: 4.0",
"Framework :: Django :: 4.1",
"Framework :: Django :: 4.2",
"Framework :: Django :: 5.0",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
Expand All @@ -39,6 +40,9 @@ def read_relative_file(filename):
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Utilities",
],
)
3 changes: 2 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ envlist = {py36,py39}-{dj32}
{py38,py310}-{dj40}
{py38,py310}-{dj41}
{py38,py310}-{dj42}
{py310,py311,py312}-{dj50}

[testenv]
changedir = {toxinidir}
commands =
pip --disable-pip-version-check install -e .
coverage run {envbindir}/pytest --ds=test_settings typedmodels/tests.py {posargs}
coverage report --omit=typedmodels/test*

Expand All @@ -25,3 +25,4 @@ deps =
dj40: Django~=4.0.0
dj41: Django~=4.1.0
dj42: Django~=4.2.0
dj50: Django~=5.0a1
6 changes: 0 additions & 6 deletions typedmodels/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +0,0 @@


pkg_resources = __import__('pkg_resources')
distribution = pkg_resources.get_distribution('django-typed-models')

VERSION = __version__ = distribution.version
107 changes: 73 additions & 34 deletions typedmodels/models.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import inspect
from functools import partial
import types

import django
from django.core.exceptions import FieldDoesNotExist, FieldError
from django.core.serializers.python import Serializer as _PythonSerializer
from django.core.serializers.xml_serializer import Serializer as _XmlSerializer
Expand Down Expand Up @@ -245,40 +245,79 @@ def _model_has_field(cls, base_class, field_name):
def _patch_fields_cache(cls, base_class):
orig_get_fields = cls._meta._get_fields

def _get_fields(
self,
forward=True,
reverse=True,
include_parents=True,
include_hidden=False,
seen_models=None,
):
cache_key = (
forward,
reverse,
include_parents,
include_hidden,
seen_models is None,
)
if django.VERSION >= (5, 0):

def _get_fields(
self,
forward=True,
reverse=True,
include_parents=True,
include_hidden=False,
topmost_call=True,
):
cache_key = (
forward,
reverse,
include_parents,
include_hidden,
topmost_call,
)

was_cached = cache_key in self._get_fields_cache
fields = orig_get_fields(
forward=forward,
reverse=reverse,
include_parents=include_parents,
include_hidden=include_hidden,
seen_models=seen_models,
)
# If it was cached already, it's because we've already filtered this, skip it
if not was_cached:
fields = [
f
for f in fields
if TypedModelMetaclass._model_has_field(cls, base_class, f.name)
]
fields = make_immutable_fields_list("get_fields()", fields)
self._get_fields_cache[cache_key] = fields
return fields
was_cached = cache_key in self._get_fields_cache
fields = orig_get_fields(
forward=forward,
reverse=reverse,
include_parents=include_parents,
include_hidden=include_hidden,
topmost_call=topmost_call,
)
# If it was cached already, it's because we've already filtered this, skip it
if not was_cached:
fields = [
f
for f in fields
if TypedModelMetaclass._model_has_field(cls, base_class, f.name)
]
fields = make_immutable_fields_list("get_fields()", fields)
self._get_fields_cache[cache_key] = fields
return fields

else:

def _get_fields(
self,
forward=True,
reverse=True,
include_parents=True,
include_hidden=False,
seen_models=None,
):
cache_key = (
forward,
reverse,
include_parents,
include_hidden,
seen_models is None,
)

was_cached = cache_key in self._get_fields_cache
fields = orig_get_fields(
forward=forward,
reverse=reverse,
include_parents=include_parents,
include_hidden=include_hidden,
seen_models=seen_models,
)
# If it was cached already, it's because we've already filtered this, skip it
if not was_cached:
fields = [
f
for f in fields
if TypedModelMetaclass._model_has_field(cls, base_class, f.name)
]
fields = make_immutable_fields_list("get_fields()", fields)
self._get_fields_cache[cache_key] = fields
return fields

cls._meta._get_fields = partial(_get_fields, cls._meta)

Expand Down

0 comments on commit de937ce

Please sign in to comment.