diff --git a/.editorconfig b/.editorconfig index 8fbb740..ea38bae 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,8 +14,8 @@ charset = utf-8 [*.py] max_line_length = 99 -# Smaller indent for YAML -[*.{yaml,yml}] +# Smaller indent for TOML/YAML +[*.{toml,yaml,yml}] indent_size = 2 # Use 2 spaces for the HTML files diff --git a/.github/matrix.py b/.github/matrix.py index 17a63d3..34883f1 100644 --- a/.github/matrix.py +++ b/.github/matrix.py @@ -1,3 +1,4 @@ +# noqa:INP001 import fileinput import json import re @@ -9,21 +10,22 @@ def main(): actions_matrix = [] - for tox_env in fileinput.input(): - tox_env = tox_env.rstrip() - - if python_match := PY_VERSIONS_RE.match(tox_env): - version_tuple = python_match.groups() - else: - version_tuple = sys.version_info[0:2] - - python_version = "{}.{}".format(*version_tuple) - actions_matrix.append( - { - "python": python_version, - "tox_env": tox_env, - } - ) + with fileinput.input() as f: + for tox_env_line in f: + tox_env = tox_env_line.rstrip() + + if python_match := PY_VERSIONS_RE.match(tox_env): + version_tuple = python_match.groups() + else: + version_tuple = sys.version_info[0:2] + + python_version = "{}.{}".format(*version_tuple) + actions_matrix.append( + { + "python": python_version, + "tox_env": tox_env, + } + ) print(json.dumps(actions_matrix)) # noqa:T201 diff --git a/LICENSE b/LICENSE index d4596aa..8760ff6 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2024, Developer Society Limited +Copyright (c) 2015-2025, Developer Society Limited All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/contentfiles/storage.py b/contentfiles/storage.py index 5800f63..8e072d9 100644 --- a/contentfiles/storage.py +++ b/contentfiles/storage.py @@ -13,7 +13,7 @@ class BaseContentFilesStorage(S3Storage): def __init__(self, *args, **kwargs): # contentfiles specific settings - self.contentfiles_prefix = getattr(settings, "CONTENTFILES_PREFIX") + self.contentfiles_prefix = settings.CONTENTFILES_PREFIX self.contentfiles_ssl = getattr(settings, "CONTENTFILES_SSL", True) self.contentfiles_hostname = getattr(settings, "CONTENTFILES_HOSTNAME", None) self.contentfiles_s3_endpoint_url = getattr(settings, "CONTENTFILES_S3_ENDPOINT_URL", None) diff --git a/pyproject.toml b/pyproject.toml index 3d8288f..0e82aa8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,24 +6,25 @@ readme = 'README.md' maintainers = [{ name = 'The Developer Society', email = 'studio@dev.ngo' }] requires-python = '>= 3.9' classifiers = [ - 'Environment :: Web Environment', - 'Framework :: Django', - 'Framework :: Django :: 3.2', - 'Framework :: Django :: 4.2', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: BSD License', - 'Operating System :: OS Independent', - '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', + 'Environment :: Web Environment', + 'Framework :: Django', + 'Framework :: Django :: 3.2', + 'Framework :: Django :: 4.2', + 'Framework :: Django :: 5.2', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: BSD License', + 'Operating System :: OS Independent', + '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', ] [project.urls] -Homepage = "https://github.com/developersociety/devsoc-contentfiles" +Homepage = 'https://github.com/developersociety/devsoc-contentfiles' [build-system] requires = ['setuptools >= 61.0'] @@ -40,24 +41,82 @@ line-length = 99 target-version = 'py39' [tool.ruff.lint] -select = [ - 'F', # pyflakes - 'E', # pycodestyle - 'W', # pycodestyle - 'I', # isort - 'N', # pep8-naming - 'UP', # pyupgrade - 'S', # flake8-bandit - 'BLE', # flake8-blind-except - 'C4', # flake8-comprehensions - 'EM', # flake8-errmsg - 'T20', # flake8-print - 'RET', # flake8-return - 'RUF', # ruff +extend-select = [ + 'ERA', # eradicate + 'YTT', # flake8-2020 + 'ASYNC', # flake8-async + 'S', # flake8-bandit + 'BLE', # flake8-blind-except + 'B', # flake8-bugbear + 'A', # flake8-builtins + 'COM', # flake8-commas + 'C4', # flake8-comprehensions + 'DTZ', # flake8-datetimez + 'T10', # flake8-debugger + 'DJ', # flake8-django + 'EM', # flake8-errmsg + 'EXE', # flake8-executable + 'FA', # flake8-future-annotations + 'INT', # flake8-gettext + 'ISC', # flake8-implicit-str-concat + 'ICN', # flake8-import-conventions + 'LOG', # flake8-logging + 'G', # flake8-logging-format + 'INP', # flake8-no-pep420 + 'PIE', # flake8-pie + 'T20', # flake8-print + 'PYI', # flake8-pyi + 'Q', # flake8-quotes + 'RSE', # flake8-raise + 'RET', # flake8-return + 'SLOT', # flake8-slots + 'SIM', # flake8-simplify + 'TID', # flake8-tidy-imports + 'TD', # flake8-todos + 'TCH', # flake8-type-checking + 'PTH', # flake8-use-pathlib + 'FLY', # flynt + 'I', # isort + 'NPY', # numpy-specific rules + 'PD', # pandas-vet + 'N', # pep8-naming + 'PERF', # perflint + 'E', # pycodestyle + 'W', # pycodestyle + 'F', # pyflakes + 'PGH', # pygrep-hooks + 'PLC', # pylint + 'PLE', # pylint + 'PLW', # pylint + 'UP', # pyupgrade + 'FURB', # refurb + 'RUF', # ruff-specific rules + 'TRY', # tryceratops ] ignore = [ - 'EM101', # flake8-errmsg: raw-string-in-exception + 'COM812', # flake8-commas: missing-trailing-comma + 'EM101', # flake8-errmsg: raw-string-in-exception + 'ISC001', # flake8-implicit-str-concat: single-line-implicit-string-concatenation + 'RUF012', # ruff-specific rules: mutable-class-default + 'SIM105', # flake8-simplify: suppressible-exception + 'SIM108', # flake8-simplify: if-else-block-instead-of-if-exp + 'TD002', # flake8-todos: missing-todo-author + 'TRY003', # tryceratops: raise-vanilla-args ] [tool.ruff.lint.isort] combine-as-imports = true +section-order = [ + 'future', + 'standard-library', + 'django', + 'third-party', + 'first-party', + 'local-folder', +] + +[tool.ruff.lint.isort.sections] +'django' = ['django'] + +[tool.ruff.lint.pep8-naming] +extend-ignore-names = ['assert*'] diff --git a/requirements/local.txt b/requirements/local.txt index 16336d6..92d703d 100644 --- a/requirements/local.txt +++ b/requirements/local.txt @@ -1,7 +1,7 @@ -r testing.txt -bump-my-version==0.28.1 -Django>=4.2,<5.0 +bump-my-version==1.1.2 +Django>=5.2,<6.0 django-storages[s3]>=1.14 -tox==4.23.2 -tox-uv==1.16.0 +tox==4.25.0 +tox-uv==1.25.0 diff --git a/requirements/testing.txt b/requirements/testing.txt index 9f7e7b8..40ee824 100644 --- a/requirements/testing.txt +++ b/requirements/testing.txt @@ -1,6 +1,6 @@ build==1.2.2.post1 -check-wheel-contents==0.6.0 -coverage==7.6.4 -pipdeptree==2.23.4 -ruff==0.7.3 -twine==5.1.1 +check-wheel-contents==0.6.1 +coverage==7.8.0 +pipdeptree==2.26.0 +ruff==0.11.5 +twine==6.1.0 diff --git a/tests/test_storage.py b/tests/test_storage.py index d761bd9..9247739 100644 --- a/tests/test_storage.py +++ b/tests/test_storage.py @@ -72,7 +72,9 @@ def test_private_storage(self, mock_get_date): ) @mock.patch("botocore.auth.datetime") def test_private_storage_aws4(self, mock_datetime): - mock_datetime.datetime.utcnow.return_value = datetime.datetime(2020, 1, 1, 12, 34, 56, 0) + mock_datetime.datetime.utcnow.return_value = datetime.datetime( + 2020, 1, 1, 12, 34, 56, 0, tzinfo=datetime.timezone.utc + ) storage = PrivateStorage() storage.access_key = "AKIA1234567890ABCDEF" diff --git a/tox.ini b/tox.ini index bdfd899..ccc3186 100644 --- a/tox.ini +++ b/tox.ini @@ -2,18 +2,22 @@ env_list = check lint - {py39,py310}-django3.2 - {py39,py310,py311,py312}-django4.2 + py{39,310}-django3.2 + py{39,310,311,312}-django4.2 + py{310,311,312}-django5.2 coverage no_package = true [testenv] deps = -rrequirements/testing.txt + py39: s3transfer # uv workaround - avoid older version being installed django3.2: Django>=3.2,<4.0 django4.2: Django>=4.2,<5.0 + django5.2: Django>=5.2,<6.0 django3.2: django-storages[s3]>=1.14 django4.2: django-storages[s3]>=1.14 + django5.2: django-storages[s3]>=1.14 allowlist_externals = make commands = make test package = editable