diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 576f4d6..bc1c054 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,10 +4,23 @@ on: branches: - master pull_request: - branches: - - master jobs: + Lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: pre-commit/action@v3.0.1 Build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - run: python -m pip install -U build + - run: python -m build + - uses: actions/upload-artifact@v4 + with: + name: dist + path: dist/* + Test: runs-on: ubuntu-20.04 strategy: matrix: @@ -17,9 +30,9 @@ jobs: - python-version: '3.10' - python-version: '3.11' steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: 'Set up Python ${{ matrix.python-version }}' - uses: actions/setup-python@v4 + uses: actions/setup-python@v5 with: python-version: '${{ matrix.python-version }}' cache: pip diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..b69ec1e --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,22 @@ +repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.3.5 + hooks: + - id: ruff + args: + - --fix + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-merge-conflict + - id: check-yaml + - id: end-of-file-fixer + - id: fix-byte-order-marker + - id: trailing-whitespace + - id: mixed-line-ending + args: + - --fix=lf + - repo: https://github.com/crate-ci/typos + rev: v1.18.2 + hooks: + - id: typos diff --git a/CHANGES.md b/CHANGES.md index 72019f0..85e418c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -45,4 +45,3 @@ * Feature: Warn when some values of an enum won't fit in the backing database field * Packaging: PEP-396 compliant `__version__` attribute * Packaging: Tests are now packaged with the source distribution - diff --git a/LICENSE b/LICENSE index 58f4bb0..8ffe7ca 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -The MIT License +The MIT License Copyright © 2013-2020 Hirshorn Zuckerman Design Group, Inc Copyright © 2022 Aarni Koskela diff --git a/README.rst b/README.rst index 9f15f3e..af208ff 100644 --- a/README.rst +++ b/README.rst @@ -114,12 +114,12 @@ Django Rest Framework integration # models.py from enumfields import EnumField from enum import Enum - + class Color(Enum): RED = 'r' GREEN = 'g' BLUE = 'b' - + class MyModel(models.Model): color = EnumField(Color, max_length=1) diff --git a/enumfields/__init__.py b/enumfields/__init__.py index 56aaa2d..d35e24a 100644 --- a/enumfields/__init__.py +++ b/enumfields/__init__.py @@ -2,3 +2,10 @@ from .fields import EnumField, EnumIntegerField __version__ = "3.0.2" + +__all__ = [ + "Enum", + "EnumField", + "EnumIntegerField", + "IntEnum", +] diff --git a/enumfields/drf/__init__.py b/enumfields/drf/__init__.py index 26eb692..5a18a29 100644 --- a/enumfields/drf/__init__.py +++ b/enumfields/drf/__init__.py @@ -1,2 +1,7 @@ from .fields import EnumField from .serializers import EnumSupportSerializerMixin + +__all__ = [ + "EnumField", + "EnumSupportSerializerMixin", +] diff --git a/enumfields/drf/fields.py b/enumfields/drf/fields.py index bfac3c8..b2f06b0 100644 --- a/enumfields/drf/fields.py +++ b/enumfields/drf/fields.py @@ -1,5 +1,4 @@ from django.utils.encoding import force_str - from rest_framework.fields import ChoiceField diff --git a/enumfields/drf/serializers.py b/enumfields/drf/serializers.py index 746f136..60c57c3 100644 --- a/enumfields/drf/serializers.py +++ b/enumfields/drf/serializers.py @@ -1,6 +1,7 @@ +from rest_framework.fields import CharField, ChoiceField, IntegerField + from enumfields.drf.fields import EnumField as EnumSerializerField from enumfields.fields import EnumFieldMixin -from rest_framework.fields import CharField, ChoiceField, IntegerField class EnumSupportSerializerMixin: diff --git a/enumfields/enums.py b/enumfields/enums.py index 6908fec..2001b28 100644 --- a/enumfields/enums.py +++ b/enumfields/enums.py @@ -1,8 +1,8 @@ -import sys import inspect -from enum import _EnumDict +import sys from enum import Enum as BaseEnum from enum import EnumMeta as BaseEnumMeta +from enum import _EnumDict from django.utils.encoding import force_str diff --git a/pyproject.toml b/pyproject.toml index 7d0e8ac..30988ba 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -46,3 +46,26 @@ path = "enumfields/__init__.py" include = [ "/enumfields", ] + +[tool.hatch.build.targets.wheel] +packages = ["enumfields"] + +[tool.ruff] +line-length = 120 + +[tool.ruff.lint] +extend-select = [ + "C9", + "E", + "F", + "I", + "W", +] + +[tool.ruff.lint.mccabe] +max-complexity = 10 + +[tool.pytest.ini_options] +DJANGO_SETTINGS_MODULE = "tests.settings" +norecursedirs = [".git", ".tox", ".eggs", ".cache", "htmlcov", "venv*"] +doctest_optionflags = ["NORMALIZE_WHITESPACE", "IGNORE_EXCEPTION_DETAIL", "ALLOW_UNICODE"] diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 8cb8e01..0000000 --- a/setup.cfg +++ /dev/null @@ -1,28 +0,0 @@ -[pep8] -max-line-length = 120 -exclude = *migrations* -ignore = E309 - -[flake8] -exclude = migrations -max-line-length = 120 -max-complexity = 10 - -[tool:pytest] -DJANGO_SETTINGS_MODULE = tests.settings -norecursedirs = .git .tox .eggs .cache htmlcov venv* -doctest_optionflags = NORMALIZE_WHITESPACE IGNORE_EXCEPTION_DETAIL ALLOW_UNICODE - -[isort] -atomic=true -combine_as_imports=false -indent=4 -known_standard_library=token,tokenize,enum,importlib -known_third_party=django,six -length_sort=false -line_length=120 -multi_line_output=5 -not_skip=__init__.py -order_by_type=false -skip=migrations -wrap_length=120 diff --git a/tests/migrations/0001_initial.py b/tests/migrations/0001_initial.py new file mode 100644 index 0000000..3d7a0f7 --- /dev/null +++ b/tests/migrations/0001_initial.py @@ -0,0 +1,60 @@ +# Generated by Django 5.0.4 on 2024-04-09 06:18 + +from django.db import migrations, models + +import enumfields.fields +import tests.enums + + +class Migration(migrations.Migration): + initial = True + + dependencies = [] + + operations = [ + migrations.CreateModel( + name="MyModel", + fields=[ + ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")), + ("color", enumfields.fields.EnumField(enum=tests.enums.Color, max_length=1)), + ( + "color_not_editable", + enumfields.fields.EnumField(editable=False, enum=tests.enums.Color, max_length=1, null=True), + ), + ("taste", enumfields.fields.EnumField(default=1, enum=tests.enums.Taste, max_length=10)), + ( + "taste_not_editable", + enumfields.fields.EnumField(default=1, editable=False, enum=tests.enums.Taste, max_length=10), + ), + ( + "taste_null_default", + enumfields.fields.EnumField( + blank=True, default=None, enum=tests.enums.Taste, max_length=10, null=True + ), + ), + ("taste_int", enumfields.fields.EnumIntegerField(default=1, enum=tests.enums.Taste)), + ( + "default_none", + enumfields.fields.EnumIntegerField(blank=True, default=None, enum=tests.enums.Taste, null=True), + ), + ("nullable", enumfields.fields.EnumIntegerField(blank=True, enum=tests.enums.Taste, null=True)), + ("random_code", models.TextField(blank=True, null=True)), + ("zero", enumfields.fields.EnumIntegerField(default=0, enum=tests.enums.ZeroEnum)), + ("zero2", enumfields.fields.EnumIntegerField(blank=True, default=0, enum=tests.enums.ZeroEnum)), + ( + "int_enum", + enumfields.fields.EnumIntegerField( + blank=True, default=None, enum=tests.enums.IntegerEnum, null=True + ), + ), + ( + "int_enum_not_editable", + enumfields.fields.EnumIntegerField(default=0, editable=False, enum=tests.enums.IntegerEnum), + ), + ( + "labeled_enum", + enumfields.fields.EnumField(blank=True, enum=tests.enums.LabeledEnum, max_length=10, null=True), + ), + ], + ), + ] diff --git a/tests/migrations/__init__.py b/tests/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/settings.py b/tests/settings.py index e6222a1..227a52c 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -5,6 +5,7 @@ 'django.contrib.sessions', 'django.contrib.auth', 'django.contrib.admin', + 'django.contrib.messages', 'tests', ) @@ -42,9 +43,12 @@ 'django.template.context_processors.i18n', 'django.template.context_processors.media', 'django.template.context_processors.static', + 'django.template.context_processors.request', 'django.template.context_processors.tz', 'django.contrib.messages.context_processors.messages', ], }, }, ] + +DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' diff --git a/tests/test_checks.py b/tests/test_checks.py index 24b29fc..2569dc1 100644 --- a/tests/test_checks.py +++ b/tests/test_checks.py @@ -1,5 +1,6 @@ -from enumfields import EnumField from django.db import models + +from enumfields import EnumField from tests.enums import LabeledEnum diff --git a/tests/test_django_admin.py b/tests/test_django_admin.py index febbc97..c289bb3 100644 --- a/tests/test_django_admin.py +++ b/tests/test_django_admin.py @@ -3,6 +3,7 @@ import pytest from django.urls import reverse + from enumfields import EnumIntegerField from .enums import Color, IntegerEnum, Taste, ZeroEnum diff --git a/tests/test_django_models.py b/tests/test_django_models.py index 9966fa9..908117c 100644 --- a/tests/test_django_models.py +++ b/tests/test_django_models.py @@ -1,6 +1,5 @@ -from django.db import connection - import pytest +from django.db import connection from .enums import Color, IntegerEnum, LabeledEnum, Taste, ZeroEnum from .models import MyModel @@ -95,9 +94,9 @@ def test_int_enum(): def test_serialization(): from django.core.serializers.python import Serializer as PythonSerializer m = MyModel(color=Color.RED, taste=Taste.SALTY) - ser = PythonSerializer() - ser.serialize([m]) - fields = ser.getvalue()[0]["fields"] + serializer = PythonSerializer() + serializer.serialize([m]) + fields = serializer.getvalue()[0]["fields"] assert fields["color"] == m.color.value assert fields["taste"] == m.taste.value diff --git a/tests/test_enums.py b/tests/test_enums.py index 8a1a238..b3ed40d 100644 --- a/tests/test_enums.py +++ b/tests/test_enums.py @@ -1,7 +1,7 @@ +import pytest from django.core.exceptions import ValidationError from django.forms import BaseForm -import pytest from enumfields import Enum, EnumField from .enums import Color, IntegerEnum @@ -72,3 +72,7 @@ def test_programmatic(): 'Green': 'g', 'Blue': 'b', }) + assert Foople.Red == Foople('r') + assert Foople.Red.label == 'Red' + assert Foople.Red.value == 'r' + assert Foople.Red.name == 'Red' diff --git a/tests/test_form_fields.py b/tests/test_form_fields.py index 2b0290b..cb4fd43 100644 --- a/tests/test_form_fields.py +++ b/tests/test_form_fields.py @@ -1,8 +1,7 @@ +import pytest from django.db.models import BLANK_CHOICE_DASH from django.forms.models import model_to_dict, modelform_factory -import pytest - from .enums import Color, ZeroEnum from .models import MyModel diff --git a/tests/test_serializers.py b/tests/test_serializers.py index cb132a4..0f95693 100644 --- a/tests/test_serializers.py +++ b/tests/test_serializers.py @@ -1,9 +1,10 @@ import uuid import pytest +from rest_framework import serializers + from enumfields.drf import EnumField from enumfields.drf.serializers import EnumSupportSerializerMixin -from rest_framework import serializers from .enums import Color, IntegerEnum, Taste from .models import MyModel diff --git a/tests/urls.py b/tests/urls.py index 6a9db2c..1496e89 100644 --- a/tests/urls.py +++ b/tests/urls.py @@ -1,7 +1,7 @@ from django.conf import settings -from django.urls import re_path from django.contrib import admin from django.contrib.staticfiles.urls import staticfiles_urlpatterns +from django.urls import re_path admin.autodiscover()