From 73b79b9e0b4406be9f8924f4e87feaa59426cdf4 Mon Sep 17 00:00:00 2001 From: David Paul Graham Date: Sat, 14 Mar 2026 08:08:24 -0400 Subject: [PATCH 1/5] move ruff lint configs to separate section and reduce the target python version to the earliest supported python version --- pyproject.toml | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 8a2f802..8d0b8c5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,12 +3,37 @@ ################## [tool.ruff] fix = true -lint.fixable = ["ALL"] -lint.ignore = ["A003", "COM812", "D", "DJ008", "ERA001", "ISC001", "PLC2401", "PLC2403", "PT011", "RUF001", "S101", "S105", "S608", "SIM103", "TC001", "TC002", "TC003", "UP040"] -lint.select = ["ALL"] -lint.unfixable = ["ERA001", "F401"] -include = ["encrypted_fields/*.py", "package_test/*.py"] -target-version = "py312" +extend-include = ["package_test/**/*.py"] +target-version = "py310" + +[tool.ruff.lint] +fixable = ["ALL"] +extend-ignore = [ + "RUF012", + "A003", + "COM812", + "D", + "DJ008", + "ERA001", + "ISC001", + "PLC2401", + "PLC2403", + "PT011", + "RUF001", + "S101", + "S105", + "S608", + "SIM103", + "TC001", + "TC002", + "TC003", + "UP040" +] +select = ["ALL"] +unfixable = [ + "ERA001", + "F401" +] ################## # mypy From f5033cafefd123f7b59b1565ff5e814f2e5a8f06 Mon Sep 17 00:00:00 2001 From: David Paul Graham Date: Sat, 14 Mar 2026 08:45:17 -0400 Subject: [PATCH 2/5] add ruff format to pre-commit hooks --- .pre-commit-config.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d50ff88..8a1ce87 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -48,3 +48,11 @@ repos: - id: pyupgrade name: pyupgrade args: [--py312-plus] + + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.15.6 + hooks: + # uncomment after linting initially passes + # - id: ruff-check + # args: [ --fix ] + - id: ruff-format From d7fefc11986c015dc9a430f465ac894917eaf917 Mon Sep 17 00:00:00 2001 From: David Paul Graham Date: Sat, 14 Mar 2026 08:46:15 -0400 Subject: [PATCH 3/5] format the codebase with ruff --- .gitignore | 3 +++ encrypted_fields/fields.py | 26 +++++--------------------- package_test/tests.py | 12 ++++-------- pyproject.toml | 1 + 4 files changed, 13 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index f0f01b9..38754f1 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ dist/ .ruff_cache .venv .venv_django_* + +# Node +node_modules/ diff --git a/encrypted_fields/fields.py b/encrypted_fields/fields.py index 33a0622..c60db26 100644 --- a/encrypted_fields/fields.py +++ b/encrypted_fields/fields.py @@ -24,9 +24,7 @@ class EncryptedFieldMixin: def keys(self) -> list[bytes]: keys = [] salt_keys = ( - settings.SALT_KEY - if isinstance(settings.SALT_KEY, list) - else [settings.SALT_KEY] + settings.SALT_KEY if isinstance(settings.SALT_KEY, list) else [settings.SALT_KEY] ) secret_keys = [settings.SECRET_KEY] + getattr(settings, "SECRET_KEY_FALLBACKS", list()) for secret_key in secret_keys: @@ -39,11 +37,7 @@ class EncryptedFieldMixin: iterations=100_000, backend=default_backend(), ) - keys.append( - base64.urlsafe_b64encode( - kdf.derive(secret_key.encode("utf-8")) - ) - ) + keys.append(base64.urlsafe_b64encode(kdf.derive(secret_key.encode("utf-8")))) return keys @cached_property @@ -85,11 +79,7 @@ class EncryptedFieldMixin: return self.to_python(value) def to_python(self, value: _TypeAny) -> _TypeAny: - if ( - value is None - or not isinstance(value, str) - or hasattr(self, "_already_decrypted") - ): + if value is None or not isinstance(value, str) or hasattr(self, "_already_decrypted"): return value try: value = self.f.decrypt(bytes(value, "utf-8")).decode("utf-8") @@ -129,9 +119,7 @@ class EncryptedIntegerField(EncryptedFieldMixin, models.IntegerField): # they're based on values retrieved from `connection`. validators_ = [*self.default_validators, *self._validators] internal_type = models.IntegerField().get_internal_type() - min_value, max_value = BaseDatabaseOperations.integer_field_ranges[ - internal_type - ] + min_value, max_value = BaseDatabaseOperations.integer_field_ranges[internal_type] if min_value is not None and not any( ( isinstance(validator, MinValueValidator) @@ -203,11 +191,7 @@ class EncryptedJSONField(EncryptedFieldMixin, models.JSONField): return "JSONField" def to_python(self, value: _TypeAny) -> _TypeAny: - if ( - value is None - or not isinstance(value, str) - or hasattr(self, "_already_decrypted") - ): + if value is None or not isinstance(value, str) or hasattr(self, "_already_decrypted"): return value try: value = self._decrypt_values(value=json.loads(value)) diff --git a/package_test/tests.py b/package_test/tests.py index abeb65a..94c503f 100644 --- a/package_test/tests.py +++ b/package_test/tests.py @@ -13,9 +13,7 @@ from .models import TestModel class FieldTest(TestCase): def get_db_value(self, field: str, model_id: int) -> None: cursor = connection.cursor() - cursor.execute( - f"select {field} from package_test_testmodel where id = {model_id};" - ) + cursor.execute(f"select {field} from package_test_testmodel where id = {model_id};") return cursor.fetchone()[0] def test_char_field_encrypted(self) -> None: @@ -258,14 +256,13 @@ class RotatedSaltTestCase(TestCase): class RotatedSecretKeyTestCase(TestCase): - @staticmethod def clear_cached_properties(): # we have to clear the cached properties of EncryptedFieldMixin so we have the right encryption keys - text_field = TestModel._meta.get_field('text') - if hasattr(text_field, 'keys'): + text_field = TestModel._meta.get_field("text") + if hasattr(text_field, "keys"): del text_field.keys - if hasattr(text_field, 'f'): + if hasattr(text_field, "f"): del text_field.f @classmethod @@ -308,4 +305,3 @@ class RotatedSecretKeyTestCase(TestCase): assert old_record.text.endswith("=") # assert that old record cannot be decrypted now assert old_record.text != plaintext - diff --git a/pyproject.toml b/pyproject.toml index 8d0b8c5..0b43154 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,7 @@ fix = true extend-include = ["package_test/**/*.py"] target-version = "py310" +line-length = 100 [tool.ruff.lint] fixable = ["ALL"] From 6a4958382e736956e12b1cfe230fb897c3e63885 Mon Sep 17 00:00:00 2001 From: David Paul Graham Date: Sat, 14 Mar 2026 08:57:27 -0400 Subject: [PATCH 4/5] format with ruff in CI --- .github/workflows/lint-and-test.yml | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/.github/workflows/lint-and-test.yml b/.github/workflows/lint-and-test.yml index 5d9966b..9168af0 100644 --- a/.github/workflows/lint-and-test.yml +++ b/.github/workflows/lint-and-test.yml @@ -10,18 +10,20 @@ jobs: runs-on: ubuntu-latest steps: - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install ruff black + - uses: actions/checkout@v3 - - name: Lint with Ruff - run: | - ruff check . + - name: "Set up Python" + uses: actions/setup-python@v6 - - name: Lint with Black - run: | - black --check . + - name: "install Ruff" + uses: astral-sh/ruff-action@v3 + with: + version: ">=0.15,<0.16" + # ToDo: use pyrpoject.toml as version-file + # version-file: "pyproject.toml" + + - name: "Check formatting" + run: ruff format --check --diff test: strategy: From 9c768e7e7c66ea7baf0c8a7557a52498a72c56b4 Mon Sep 17 00:00:00 2001 From: David Paul Graham Date: Sat, 14 Mar 2026 09:02:47 -0400 Subject: [PATCH 5/5] don't run ruff check on installation --- .github/workflows/lint-and-test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/lint-and-test.yml b/.github/workflows/lint-and-test.yml index 9168af0..5693d61 100644 --- a/.github/workflows/lint-and-test.yml +++ b/.github/workflows/lint-and-test.yml @@ -19,6 +19,8 @@ jobs: uses: astral-sh/ruff-action@v3 with: version: ">=0.15,<0.16" + # use args to avoid the default behavior of running ruff check automatically + args: "--version" # ToDo: use pyrpoject.toml as version-file # version-file: "pyproject.toml"