Drop Python 3.8 support (#678)

This commit is contained in:
Hasan Ramezani 2024-10-17 18:40:21 +02:00 committed by GitHub
parent 4c3ee0b36d
commit a53a6facfe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 38 additions and 51 deletions

View file

@ -18,7 +18,7 @@ jobs:
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: '3.8' python-version: '3.9'
- name: Get pip cache dir - name: Get pip cache dir
id: pip-cache id: pip-cache

View file

@ -9,7 +9,7 @@ jobs:
fail-fast: false fail-fast: false
max-parallel: 5 max-parallel: 5
matrix: matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12'] python-version: ['3.9', '3.10', '3.11', '3.12']
services: services:
postgres: postgres:

View file

@ -4,10 +4,10 @@ repos:
rev: 24.4.2 rev: 24.4.2
hooks: hooks:
- id: black - id: black
language_version: python3.8 language_version: python3.9
args: args:
- "--target-version" - "--target-version"
- "py38" - "py39"
- repo: https://github.com/PyCQA/flake8 - repo: https://github.com/PyCQA/flake8
rev: "7.1.0" rev: "7.1.0"
hooks: hooks:
@ -21,7 +21,7 @@ repos:
rev: v3.16.0 rev: v3.16.0
hooks: hooks:
- id: pyupgrade - id: pyupgrade
args: [--py38-plus] args: [--py39-plus]
- repo: https://github.com/adamchainz/django-upgrade - repo: https://github.com/adamchainz/django-upgrade
rev: 1.20.0 rev: 1.20.0
hooks: hooks:

View file

@ -4,6 +4,7 @@
#### Improvements #### Improvements
- feat: Added `LogEntry.remote_port` field. ([#671](https://github.com/jazzband/django-auditlog/pull/671)) - feat: Added `LogEntry.remote_port` field. ([#671](https://github.com/jazzband/django-auditlog/pull/671))
- Drop Python 3.8 support. ([#678](https://github.com/jazzband/django-auditlog/pull/678))
#### Fixes #### Fixes

View file

@ -1,11 +1,9 @@
# Generated by Django 4.0 on 2022-08-04 15:41 # Generated by Django 4.0 on 2022-08-04 15:41
from typing import List
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
def two_step_migrations() -> List: def two_step_migrations() -> list:
if settings.AUDITLOG_TWO_STEP_MIGRATION: if settings.AUDITLOG_TWO_STEP_MIGRATION:
return [ return [
migrations.RenameField( migrations.RenameField(

View file

@ -3,7 +3,7 @@ import contextlib
import json import json
from copy import deepcopy from copy import deepcopy
from datetime import timezone from datetime import timezone
from typing import Any, Callable, Dict, List, Union from typing import Any, Callable, Union
from dateutil import parser from dateutil import parser
from dateutil.tz import gettz from dateutil.tz import gettz
@ -275,8 +275,8 @@ class LogEntryManager(models.Manager):
return instance_copy return instance_copy
def _get_applicable_model_fields( def _get_applicable_model_fields(
self, instance, model_fields: Dict[str, List[str]] self, instance, model_fields: dict[str, list[str]]
) -> List[str]: ) -> list[str]:
include_fields = model_fields["include_fields"] include_fields = model_fields["include_fields"]
exclude_fields = model_fields["exclude_fields"] exclude_fields = model_fields["exclude_fields"]
all_field_names = [field.name for field in instance._meta.fields] all_field_names = [field.name for field in instance._meta.fields]
@ -287,8 +287,8 @@ class LogEntryManager(models.Manager):
return list(set(include_fields or all_field_names).difference(exclude_fields)) return list(set(include_fields or all_field_names).difference(exclude_fields))
def _mask_serialized_fields( def _mask_serialized_fields(
self, data: Dict[str, Any], mask_fields: List[str] self, data: dict[str, Any], mask_fields: list[str]
) -> Dict[str, Any]: ) -> dict[str, Any]:
all_field_data = data.pop("fields") all_field_data = data.pop("fields")
masked_field_data = {} masked_field_data = {}
@ -595,8 +595,8 @@ class AuditlogHistoryField(GenericRelation):
changes_func = None changes_func = None
def _changes_func() -> Callable[[LogEntry], Dict]: def _changes_func() -> Callable[[LogEntry], dict]:
def json_then_text(instance: LogEntry) -> Dict: def json_then_text(instance: LogEntry) -> dict:
if instance.changes: if instance.changes:
return instance.changes return instance.changes
elif instance.changes_text: elif instance.changes_text:
@ -604,7 +604,7 @@ def _changes_func() -> Callable[[LogEntry], Dict]:
return json.loads(instance.changes_text) return json.loads(instance.changes_text)
return {} return {}
def default(instance: LogEntry) -> Dict: def default(instance: LogEntry) -> dict:
return instance.changes or {} return instance.changes or {}
if settings.AUDITLOG_USE_TEXT_CHANGES_IF_JSON_IS_NOT_PRESENT: if settings.AUDITLOG_USE_TEXT_CHANGES_IF_JSON_IS_NOT_PRESENT:

View file

@ -1,16 +1,7 @@
import copy import copy
from collections import defaultdict from collections import defaultdict
from typing import ( from collections.abc import Collection, Iterable
Any, from typing import Any, Callable, Optional, Union
Callable,
Collection,
Dict,
Iterable,
List,
Optional,
Tuple,
Union,
)
from django.apps import apps from django.apps import apps
from django.db.models import ManyToManyField, Model from django.db.models import ManyToManyField, Model
@ -26,7 +17,7 @@ from django.db.models.signals import (
from auditlog.conf import settings from auditlog.conf import settings
from auditlog.signals import accessed from auditlog.signals import accessed
DispatchUID = Tuple[int, int, int] DispatchUID = tuple[int, int, int]
class AuditLogRegistrationError(Exception): class AuditLogRegistrationError(Exception):
@ -47,7 +38,7 @@ class AuditlogModelRegistry:
delete: bool = True, delete: bool = True,
access: bool = True, access: bool = True,
m2m: bool = True, m2m: bool = True,
custom: Optional[Dict[ModelSignal, Callable]] = None, custom: Optional[dict[ModelSignal, Callable]] = None,
): ):
from auditlog.receivers import log_access, log_create, log_delete, log_update from auditlog.receivers import log_access, log_create, log_delete, log_update
@ -71,13 +62,13 @@ class AuditlogModelRegistry:
def register( def register(
self, self,
model: ModelBase = None, model: ModelBase = None,
include_fields: Optional[List[str]] = None, include_fields: Optional[list[str]] = None,
exclude_fields: Optional[List[str]] = None, exclude_fields: Optional[list[str]] = None,
mapping_fields: Optional[Dict[str, str]] = None, mapping_fields: Optional[dict[str, str]] = None,
mask_fields: Optional[List[str]] = None, mask_fields: Optional[list[str]] = None,
m2m_fields: Optional[Collection[str]] = None, m2m_fields: Optional[Collection[str]] = None,
serialize_data: bool = False, serialize_data: bool = False,
serialize_kwargs: Optional[Dict[str, Any]] = None, serialize_kwargs: Optional[dict[str, Any]] = None,
serialize_auditlog_fields_only: bool = False, serialize_auditlog_fields_only: bool = False,
): ):
""" """
@ -169,7 +160,7 @@ class AuditlogModelRegistry:
else: else:
self._disconnect_signals(model) self._disconnect_signals(model)
def get_models(self) -> List[ModelBase]: def get_models(self) -> list[ModelBase]:
return list(self._registry.keys()) return list(self._registry.keys())
def get_model_fields(self, model: ModelBase): def get_model_fields(self, model: ModelBase):
@ -235,7 +226,7 @@ class AuditlogModelRegistry:
"""Generate a dispatch_uid which is unique for a combination of self, signal, and receiver.""" """Generate a dispatch_uid which is unique for a combination of self, signal, and receiver."""
return id(self), id(signal), id(receiver) return id(self), id(signal), id(receiver)
def _get_model_classes(self, app_model: str) -> List[ModelBase]: def _get_model_classes(self, app_model: str) -> list[ModelBase]:
try: try:
try: try:
app_label, model_name = app_model.split(".") app_label, model_name = app_model.split(".")
@ -247,7 +238,7 @@ class AuditlogModelRegistry:
def _get_exclude_models( def _get_exclude_models(
self, exclude_tracking_models: Iterable[str] self, exclude_tracking_models: Iterable[str]
) -> List[ModelBase]: ) -> list[ModelBase]:
exclude_models = [ exclude_models = [
model model
for app_model in tuple(exclude_tracking_models) for app_model in tuple(exclude_tracking_models)
@ -256,7 +247,7 @@ class AuditlogModelRegistry:
] ]
return exclude_models return exclude_models
def _register_models(self, models: Iterable[Union[str, Dict[str, Any]]]) -> None: def _register_models(self, models: Iterable[Union[str, dict[str, Any]]]) -> None:
models = copy.deepcopy(models) models = copy.deepcopy(models)
for model in models: for model in models:
if isinstance(model, str): if isinstance(model, str):

View file

@ -11,10 +11,10 @@ The repository can be found at https://github.com/jazzband/django-auditlog/.
**Requirements** **Requirements**
- Python 3.8 or higher - Python 3.9 or higher
- Django 3.2, 4.2 and 5.0 - Django 3.2, 4.2 and 5.0
Auditlog is currently tested with Python 3.8+ and Django 3.2, 4.2 and 5.0. The latest test report can be found Auditlog is currently tested with Python 3.9+ and Django 3.2, 4.2 and 5.0. The latest test report can be found
at https://github.com/jazzband/django-auditlog/actions. at https://github.com/jazzband/django-auditlog/actions.
Adding Auditlog to your Django application Adding Auditlog to your Django application

View file

@ -1,5 +1,5 @@
[tool.black] [tool.black]
target-version = ["py38"] target-version = ["py39"]
[tool.isort] [tool.isort]
profile = "black" profile = "black"

View file

@ -27,12 +27,11 @@ setup(
description="Audit log app for Django", description="Audit log app for Django",
long_description=long_description, long_description=long_description,
long_description_content_type="text/markdown", long_description_content_type="text/markdown",
python_requires=">=3.8", python_requires=">=3.9",
install_requires=["Django>=3.2", "python-dateutil>=2.7.0"], install_requires=["Django>=3.2", "python-dateutil>=2.7.0"],
zip_safe=False, zip_safe=False,
classifiers=[ classifiers=[
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.11",

14
tox.ini
View file

@ -1,10 +1,10 @@
[tox] [tox]
envlist = envlist =
{py38,py39,py310}-django32 {py39,py310}-django32
{py38,py39,py310,py311}-django42 {py39,py310,py311}-django42
{py310,py311,py312}-django{50,main} {py310,py311,py312}-django{50,main}
py38-docs py39-docs
py38-lint py39-lint
[testenv] [testenv]
setenv = setenv =
@ -34,21 +34,19 @@ basepython =
py311: python3.11 py311: python3.11
py310: python3.10 py310: python3.10
py39: python3.9 py39: python3.9
py38: python3.8
[testenv:py38-docs] [testenv:py39-docs]
changedir = docs/source changedir = docs/source
deps = -rdocs/requirements.txt deps = -rdocs/requirements.txt
commands = sphinx-build -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html commands = sphinx-build -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html
[testenv:py38-lint] [testenv:py39-lint]
deps = pre-commit deps = pre-commit
commands = commands =
pre-commit run --all-files pre-commit run --all-files
[gh-actions] [gh-actions]
python = python =
3.8: py38
3.9: py39 3.9: py39
3.10: py310 3.10: py310
3.11: py311 3.11: py311