Skip to content

Commit

Permalink
Merge pull request #1421 from tim-schilling/version-updates
Browse files Browse the repository at this point in the history
Drop support for Python 3.8, added support for Django 5.1
  • Loading branch information
tim-schilling authored Nov 24, 2024
2 parents 64cdeb4 + e0d6723 commit 98462de
Show file tree
Hide file tree
Showing 12 changed files with 54 additions and 50 deletions.
16 changes: 7 additions & 9 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,15 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12', '3.13-dev']
django-version: ['4.2', '5.0', 'main']
python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
django-version: ['4.2', '5.0', '5.1', 'main']

exclude:
# Exclude py3.8 and py3.9 for Django main and 5.0
- python-version: '3.8'
django-version: '5.0'
# Exclude py3.9 for Django main and 5+
- python-version: '3.9'
django-version: '5.0'
- python-version: '3.8'
django-version: 'main'
- python-version: '3.9'
django-version: '5.1'
- python-version: '3.9'
django-version: 'main'

Expand Down Expand Up @@ -101,7 +99,7 @@ jobs:
- name: Set up newest stable Python version
uses: actions/setup-python@v5
with:
python-version: 3.11
python-version: 3.13
cache: 'pip'
# Invalidate the cache when this file updates, as the dependencies' versions
# are pinned in the step below
Expand All @@ -113,7 +111,7 @@ jobs:
# Install this project in editable mode, so that its package metadata can be queried
pip install -e .
# Install the latest minor version of Django we support
pip install Django==5.0
pip install Django==5.1
- name: Check translation files are updated
run: python -m simple_history.tests.generated_file_checks.check_translations
14 changes: 7 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
---
repos:
- repo: https://github.com/PyCQA/bandit
rev: 1.7.9
rev: 1.7.10
hooks:
- id: bandit
exclude: /.*tests/

- repo: https://github.com/psf/black-pre-commit-mirror
rev: 24.8.0
rev: 24.10.0
hooks:
- id: black
language_version: python3.9
Expand All @@ -25,7 +25,7 @@ repos:
- id: isort

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
rev: v5.0.0
hooks:
- id: requirements-txt-fixer
files: requirements/.*\.txt$
Expand All @@ -40,11 +40,11 @@ repos:
- id: detect-private-key

- repo: https://github.com/tox-dev/pyproject-fmt
rev: 2.2.3
rev: v2.5.0
hooks:
- id: pyproject-fmt
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.19
rev: v0.23
hooks:
- id: validate-pyproject

Expand All @@ -56,7 +56,7 @@ repos:
- "--strict"

- repo: https://github.com/asottile/pyupgrade
rev: v3.17.0
rev: v3.19.0
hooks:
- id: pyupgrade
args: [--py38-plus]
args: [--py39-plus]
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Unreleased
- Fixed issue with deferred fields causing DoesNotExist error (gh-678)
- Added HistoricOneToOneField (gh-1394)
- Updated all djangoproject.com links to reference the stable version (gh-1420)
- Dropped support for Python 3.8, which reached end-of-life on 2024-10-07 (gh-1421)
- Added support for Django 5.1 (gh-1388)

3.7.0 (2024-05-29)
------------------
Expand Down
7 changes: 4 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ This app supports the following combinations of Django and Python:
========== ========================
Django Python
========== ========================
4.2 3.8, 3.9, 3.10, 3.11, 3.12, 3.13-dev
5.0 3.10, 3.11, 3.12, 3.13-dev
main 3.10, 3.11, 3.12, 3.13-dev
4.2 3.9, 3.10, 3.11, 3.12, 3.13
5.0 3.10, 3.11, 3.12, 3.13
5.1 3.10, 3.11, 3.12, 3.13
main 3.10, 3.11, 3.12, 3.13
========== ========================

Getting Help
Expand Down
7 changes: 4 additions & 3 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ This app supports the following combinations of Django and Python:
========== =======================
Django Python
========== =======================
4.2 3.8, 3.9, 3.10, 3.11, 3.12, 3.13-dev
5.0 3.10, 3.11, 3.12, 3.13-dev
main 3.10, 3.11, 3.12, 3.13-dev
4.2 3.9, 3.10, 3.11, 3.12, 3.13
5.0 3.10, 3.11, 3.12, 3.13
5.1 3.10, 3.11, 3.12, 3.13
main 3.10, 3.11, 3.12, 3.13
========== =======================

Contribute
Expand Down
10 changes: 4 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ maintainers = [
authors = [
{ name = "Corey Bertram", email = "[email protected]" },
]
requires-python = ">=3.8"
requires-python = ">=3.9"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Environment :: Web Environment",
Expand All @@ -26,13 +26,11 @@ classifiers = [
"License :: OSI Approved :: BSD License",
"Programming Language :: Python",
"Programming Language :: Python :: 3 :: Only",
"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",
# DEV: uncomment this when the `pyproject-fmt` pre-commit hook stops removing it
#"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.13",
]
dynamic = [
"readme",
Expand Down Expand Up @@ -83,12 +81,12 @@ fragments = [
[tool.black]
line-length = 88
target-version = [
"py38",
"py39",
]

[tool.isort]
profile = "black"
py_version = "38"
py_version = "39"

[tool.coverage.run]
parallel = true
Expand Down
3 changes: 2 additions & 1 deletion simple_history/admin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from typing import Any, Sequence
from collections.abc import Sequence
from typing import Any

from django import http
from django.apps import apps as django_apps
Expand Down
21 changes: 13 additions & 8 deletions simple_history/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
import importlib
import uuid
import warnings
from collections.abc import Iterable, Sequence
from dataclasses import dataclass
from functools import partial
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Sequence, Type, Union
from typing import TYPE_CHECKING, Any, Union

import django
from django.apps import apps
Expand Down Expand Up @@ -899,10 +900,14 @@ def related_manager_cls(self):

class HistoricRelationModelManager(related_model._default_manager.__class__):
def get_queryset(self):
cache_name = (
# DEV: Remove this when support for Django 5.0 has been dropped
self.field.remote_field.get_cache_name()
if django.VERSION < (5, 1)
else self.field.remote_field.cache_name
)
try:
return self.instance._prefetched_objects_cache[
self.field.remote_field.get_cache_name()
]
return self.instance._prefetched_objects_cache[cache_name]
except (AttributeError, KeyError):
history = getattr(
self.instance, SIMPLE_HISTORY_REVERSE_ATTR_NAME, None
Expand Down Expand Up @@ -1088,7 +1093,7 @@ def _get_field_changes_for_diff(
old_history: "HistoricalChanges",
fields: Iterable[str],
foreign_keys_are_objs: bool,
) -> List["ModelChange"]:
) -> list["ModelChange"]:
"""Helper method for ``diff_against()``."""
changes = []

Expand Down Expand Up @@ -1129,7 +1134,7 @@ def _get_m2m_field_changes_for_diff(
old_history: "HistoricalChanges",
m2m_fields: Iterable[str],
foreign_keys_are_objs: bool,
) -> List["ModelChange"]:
) -> list["ModelChange"]:
"""Helper method for ``diff_against()``."""
changes = []

Expand Down Expand Up @@ -1198,7 +1203,7 @@ def get_value(obj, through_field):

@dataclass(frozen=True)
class DeletedObject:
model: Type[models.Model]
model: type[models.Model]
pk: Any

def __str__(self):
Expand All @@ -1223,7 +1228,7 @@ def __str__(self):
# The PK of the through model's related objects.
#
# - Any of the other possible values of a model field.
ModelChangeValue = Union[Any, DeletedObject, List[Dict[str, Union[Any, DeletedObject]]]]
ModelChangeValue = Union[Any, DeletedObject, list[dict[str, Union[Any, DeletedObject]]]]


@dataclass(frozen=True)
Expand Down
10 changes: 5 additions & 5 deletions simple_history/template_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import dataclasses
from os.path import commonprefix
from typing import Any, Dict, Final, List, Tuple, Type, Union
from typing import Any, Final, Union

from django.db.models import ManyToManyField, Model
from django.utils.html import conditional_escape
Expand Down Expand Up @@ -40,7 +40,7 @@ class HistoricalRecordContextHelper:

def __init__(
self,
model: Type[Model],
model: type[Model],
historical_record: HistoricalChanges,
*,
max_displayed_delta_change_chars=DEFAULT_MAX_DISPLAYED_DELTA_CHANGE_CHARS,
Expand All @@ -50,7 +50,7 @@ def __init__(

self.max_displayed_delta_change_chars = max_displayed_delta_change_chars

def context_for_delta_changes(self, delta: ModelDelta) -> List[Dict[str, Any]]:
def context_for_delta_changes(self, delta: ModelDelta) -> list[dict[str, Any]]:
"""
Return the template context for ``delta.changes``.
By default, this is a list of dicts with the keys ``"field"``,
Expand Down Expand Up @@ -119,7 +119,7 @@ def prepare_delta_change_value(

def stringify_delta_change_values(
self, change: ModelChange, old: Any, new: Any
) -> Tuple[SafeString, SafeString]:
) -> tuple[SafeString, SafeString]:
"""
Called by ``format_delta_change()`` after ``old`` and ``new`` have been
prepared by ``prepare_delta_change_value()``.
Expand Down Expand Up @@ -196,7 +196,7 @@ def __init__(
)
assert self.min_diff_len >= 0 # nosec

def common_shorten_repr(self, *args: Any) -> Tuple[str, ...]:
def common_shorten_repr(self, *args: Any) -> tuple[str, ...]:
"""
Returns ``args`` with each element converted into a string representation.
If any of the strings are longer than ``self.max_length``, they're all shortened
Expand Down
3 changes: 1 addition & 2 deletions simple_history/tests/tests/test_template_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from datetime import datetime
from typing import Tuple

from django.test import TestCase
from django.utils.dateparse import parse_datetime
Expand Down Expand Up @@ -225,7 +224,7 @@ def test_context_dict(
)

def test__context_for_delta_changes__preserves_html_safe_strings(self):
def get_context_dict_old_and_new(old_value, new_value) -> Tuple[str, str]:
def get_context_dict_old_and_new(old_value, new_value) -> tuple[str, str]:
# The field doesn't really matter, as long as it exists on the model
# passed to `HistoricalRecordContextHelper`
change = ModelChange("question", old_value, new_value)
Expand Down
3 changes: 1 addition & 2 deletions simple_history/tests/tests/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from enum import Enum
from typing import Type

from django.conf import settings
from django.db.models import Model
Expand All @@ -15,7 +14,7 @@


class HistoricalTestCase(TestCase):
def assertRecordValues(self, record, klass: Type[Model], values_dict: dict):
def assertRecordValues(self, record, klass: type[Model], values_dict: dict):
"""
Fail if ``record`` doesn't contain the field values in ``values_dict``.
``record.history_object`` is also checked.
Expand Down
8 changes: 4 additions & 4 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
[tox]
envlist =
py{38,39,310,311,312,313}-dj42-{sqlite3,postgres,mysql,mariadb},
py{310,311,312,313}-dj50-{sqlite3,postgres,mysql,mariadb},
py{310,311,312,313}-djmain-{sqlite3,postgres,mysql,mariadb},
py{39,310,311,312,313}-dj42-{sqlite3,postgres,mysql,mariadb},
py{310,311,312,313}-dj{50,51,main}-{sqlite3,postgres,mysql,mariadb},
docs,
lint

[gh-actions]
python =
3.8: py38
3.9: py39
3.10: py310
3.11: py311, docs, lint
Expand All @@ -19,6 +17,7 @@ python =
DJANGO =
4.2: dj42
5.0: dj50
5.1: dj51
main: djmain

[flake8]
Expand All @@ -32,6 +31,7 @@ deps =
-rrequirements/test.txt
dj42: Django>=4.2,<4.3
dj50: Django>=5.0,<5.1
dj51: Django>=5.1,<5.2
djmain: https://github.com/django/django/tarball/main
postgres: -rrequirements/postgres.txt
mysql: -rrequirements/mysql.txt
Expand Down

0 comments on commit 98462de

Please sign in to comment.