From d4eea4f6deb76deaf37681d4fef9fc61134ef097 Mon Sep 17 00:00:00 2001 From: Petter Friberg Date: Sun, 1 May 2022 22:26:48 +0200 Subject: [PATCH 1/2] Change test runner to `pytest` --- MANIFEST.in | 1 - Makefile | 12 +-- django_enumfield/enum.py | 5 +- django_enumfield/tests/conftest.py | 62 ++++++++++++++ django_enumfield/tests/models.py | 12 ++- django_enumfield/tests/test_settings.py | 12 --- mypy.ini | 2 +- pyproject.toml | 9 ++ run_tests.py | 107 ------------------------ setup.py | 21 +++-- tox.ini | 8 +- 11 files changed, 106 insertions(+), 145 deletions(-) create mode 100644 django_enumfield/tests/conftest.py delete mode 100644 django_enumfield/tests/test_settings.py create mode 100644 pyproject.toml delete mode 100644 run_tests.py diff --git a/MANIFEST.in b/MANIFEST.in index 1319aea..f522e0b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,4 @@ include AUTHORS include LICENSE include README.md -include run_tests.py include django_enumfield/py.typed diff --git a/Makefile b/Makefile index e28e38b..29c3395 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: test test: - python setup.py test + pytest $(test) .PHONY: flake8 flake8: @@ -12,15 +12,15 @@ mypy: .PHONY: isort isort: - isort -rc django_enumfield run_tests.py setup.py + isort -rc django_enumfield setup.py .PHONY: black black: - black django_enumfield run_tests.py setup.py + black django_enumfield setup.py .PHONY: black-check black-check: - black --check django_enumfield run_tests.py setup.py + black --check django_enumfield setup.py .PHONY: checks checks: mypy flake8 black-check @@ -36,10 +36,6 @@ install: develop: python setup.py develop -.PHONY: coverage -coverage: - coverage run --include=django_enumfield/* setup.py test - .PHONY: clean clean: rm -rf .tox/ dist/ *.egg *.egg-info .coverage* .eggs diff --git a/django_enumfield/enum.py b/django_enumfield/enum.py index 82cb05c..4639a68 100644 --- a/django_enumfield/enum.py +++ b/django_enumfield/enum.py @@ -1,8 +1,9 @@ from __future__ import absolute_import -import logging import enum -from typing import Any, List, Optional, Sequence, Tuple, TypeVar, Union, cast, Mapping +import logging +from typing import Any, List, Mapping, Optional, Sequence, Tuple, TypeVar, Union, cast + from django.utils.encoding import force_str try: diff --git a/django_enumfield/tests/conftest.py b/django_enumfield/tests/conftest.py new file mode 100644 index 0000000..01c2b9f --- /dev/null +++ b/django_enumfield/tests/conftest.py @@ -0,0 +1,62 @@ +import os +from pathlib import Path + +import django +import pytest + +SECRET_KEY = "secret" +INSTALLED_APPS = [ + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.admin", + "django.contrib.sessions", + "django.contrib.messages", + "django_enumfield", + "django_enumfield.tests", +] +TEMPLATES = [ + { + "BACKEND": "django.template.backends.django.DjangoTemplates", + "APP_DIRS": True, + "OPTIONS": { + "debug": True, # Raise template errors + }, + } +] +DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}} +ROOT_URLCONF = "django_enumfield.tests.urls" +DEBUG = True +MIDDLEWARE = [ + "django.middleware.common.CommonMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", +] + + +def pytest_configure(config): + from django.conf import settings + + settings.configure( + SECRET_KEY=SECRET_KEY, + INSTALLED_APPS=INSTALLED_APPS, + TEMPLATES=TEMPLATES, + DATABASES=DATABASES, + ROOT_URLCONF=ROOT_URLCONF, + DEBUG=DEBUG, + MIDDLEWARE=MIDDLEWARE, + ) + + django.setup() + + +@pytest.fixture(scope="session", autouse=True) +def delete_migrations(): + migrations_dir = Path(__file__).parent / "migrations" + if migrations_dir.exists() and migrations_dir.is_dir(): + os.system("rm -r " + str(migrations_dir)) + + yield + + if migrations_dir.exists() and migrations_dir.is_dir(): + os.system("rm -r " + str(migrations_dir)) diff --git a/django_enumfield/tests/models.py b/django_enumfield/tests/models.py index ebb29bd..5fddf00 100644 --- a/django_enumfield/tests/models.py +++ b/django_enumfield/tests/models.py @@ -5,6 +5,12 @@ from django_enumfield.enum import Enum +class BaseModel(models.Model): + class Meta: + app_label = "tests" + abstract = True + + class LampState(Enum): OFF = 0 ON = 1 @@ -12,7 +18,7 @@ class LampState(Enum): __default__ = OFF -class Lamp(models.Model): +class Lamp(BaseModel): state = EnumField(LampState, verbose_name="stately_state") @@ -41,7 +47,7 @@ class PersonStatusDefault(Enum): __default__ = UNBORN -class Person(models.Model): +class Person(BaseModel): example = models.CharField(max_length=100, default="foo") status = EnumField(PersonStatus, default=PersonStatus.ALIVE) @@ -78,7 +84,7 @@ def get_default_beer_label(): return LabelBeer.JUPILER -class Beer(models.Model): +class Beer(BaseModel): style = EnumField(BeerStyle) state = EnumField(BeerState, null=True, blank=True) label = EnumField(LabelBeer, default=get_default_beer_label) diff --git a/django_enumfield/tests/test_settings.py b/django_enumfield/tests/test_settings.py deleted file mode 100644 index 66c58c7..0000000 --- a/django_enumfield/tests/test_settings.py +++ /dev/null @@ -1,12 +0,0 @@ -import os - -TEST_DIR = os.path.abspath(os.path.dirname(__file__)) - - -DATABASES = {"default": {"ENGINE": "django.db.backends.sqlite3", "NAME": ":memory:"}} -CACHES = {"default": {"BACKEND": "django.core.cache.backends.locmem.LocMemCache"}} - -INSTALLED_APPS = ["django_enumfield", "django_enumfield.tests"] - - -SECRET_KEY = "iufoj=mibkpdz*%bob952x(%49rqgv8gg45k36kjcg76&-y5=!" diff --git a/mypy.ini b/mypy.ini index 959d5e1..1c5c1ee 100644 --- a/mypy.ini +++ b/mypy.ini @@ -8,7 +8,7 @@ plugins = mypy_django_plugin.main [mypy.plugins.django-stubs] -django_settings_module = django_enumfield.tests.test_settings +django_settings_module = django_enumfield.tests.conftest [mypy-*.migrations.*] ignore_errors = True diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..6b9a3ef --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,9 @@ +[build-system] +requires = ["setuptools>=57.0.0", "wheel"] +build-backend = "setuptools.build_meta" + +[tool.pytest.ini_options] +python_files = "tests.py test_*.py *_tests.py" +testpaths = ["django_enumfield"] +pythonpath = "django_enumfield" +addopts = "--cov --no-cov-on-fail" diff --git a/run_tests.py b/run_tests.py deleted file mode 100644 index 196b176..0000000 --- a/run_tests.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python -from __future__ import print_function - -import os -import sys - -import django -from django.conf import settings - - -def _format_version(version_tuple): - return ".".join(map(str, version_tuple)) - - -def delete_migrations(): - from os.path import exists, abspath, dirname, join - - migrations_dir = join( - dirname(abspath(__file__)), "django_enumfield", "tests", "migrations" - ) - if exists(migrations_dir): - os.system("rm -r " + migrations_dir) - - -def main(): - print( - "Running tests for Python {} and Django {}".format( - _format_version(sys.version_info[:3]), _format_version(django.VERSION[:3]) - ) - ) - import warnings - - # Ignore deprecation warning caused by Django on 3.7/3.8 + 2.0/2.1 - if sys.version_info[:2] in ((3, 7), (3, 8)) and django.VERSION[:2] in ( - (2, 0), - (2, 1), - ): - module = r"(?!django).*" - else: - module = "" - - warnings.filterwarnings("error", module=module, category=DeprecationWarning) - - delete_migrations() - - if not settings.configured: - # Dynamically configure the Django settings with the minimum necessary to - # get Django running tests - settings.configure( - SECRET_KEY="secret", - INSTALLED_APPS=[ - "django.contrib.auth", - "django.contrib.contenttypes", - "django.contrib.admin", - "django.contrib.sessions", - "django.contrib.messages", - "django_enumfield", - "django_enumfield.tests", - ], - TEMPLATES=[ - { - "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [], - "APP_DIRS": True, - "OPTIONS": { - "context_processors": [ - "django.contrib.auth.context_processors.auth", - "django.contrib.messages.context_processors.messages", - ] - }, - } - ], - # Django replaces this, but it still wants it. *shrugs* - DATABASE_ENGINE="django.db.backends.sqlite3", - DATABASES={"default": {"ENGINE": "django.db.backends.sqlite3"}}, - MEDIA_ROOT="/tmp/django_enums/", - MEDIA_PATH="/media/", - ROOT_URLCONF="django_enumfield.tests.urls", - DEBUG=True, - TEMPLATE_DEBUG=True, - MIDDLEWARE_CLASSES=[], - MIDDLEWARE=[ - "django.contrib.sessions.middleware.SessionMiddleware", - "django.contrib.messages.middleware.MessageMiddleware", - "django.contrib.auth.middleware.AuthenticationMiddleware", - ], - ) - - # Compatibility with Django 1.7's stricter initialization - if hasattr(django, "setup"): - django.setup() - - from django.test.utils import get_runner - - test_runner = get_runner(settings)(verbosity=2, interactive=True) - if "--failfast" in sys.argv: - test_runner.failfast = True - - failures = test_runner.run_tests(["django_enumfield"]) - - delete_migrations() - - sys.exit(failures) - - -if __name__ == "__main__": - main() diff --git a/setup.py b/setup.py index e0f81c0..af7a912 100644 --- a/setup.py +++ b/setup.py @@ -3,6 +3,7 @@ from distutils.command.install import INSTALL_SCHEMES from distutils.command.install_data import install_data from io import open +from pathlib import Path try: from setuptools import setup @@ -51,7 +52,10 @@ def fullsplit(path, result=None): elif filenames: data_files.append([dirpath, [os.path.join(dirpath, f) for f in filenames]]) -version = __import__("django_enumfield").__version__ +root_init = Path(__file__).resolve().parent / "django_enumfield" / "__init__.py" +init_globals = {} +exec(root_init.read_text(), init_globals) +version = init_globals["__version__"] with open(os.path.join(root_dir, "README.md"), encoding="utf-8") as f: description = f.read() @@ -91,14 +95,19 @@ def fullsplit(path, result=None): data_files=data_files, packages=packages, include_package_data=True, - tests_require=[ - "Django", - "djangorestframework", - ], + install_requires=["Django>=2.2"], + python_requires=">=3.7", zip_safe=False, - test_suite="run_tests.main", extras_require={ + "test": [ + "djangorestframework", + "pytest", + "pytest-cov", + "pytest-django", + ], "dev": [ + "pytest", + "pytest-cov", "black", "isort", "Django", diff --git a/tox.ini b/tox.ini index d868164..b5b3fe7 100644 --- a/tox.ini +++ b/tox.ini @@ -9,6 +9,7 @@ envlist = [testenv] whitelist_externals = make deps= + .[test] django22: Django>=2.2,<2.3 django30: Django>=3.0b1,<3.1 django31: Django>=3.1,<3.2 @@ -21,10 +22,9 @@ basepython = python3.7 passenv = TOXENV CI whitelist_externals = make deps = + .[test] Django>=2.2,<2.3 - coverage==4.5.2 flake8 - python-coveralls mypy django-stubs djangorestframework-stubs @@ -32,6 +32,4 @@ deps = setenv = COVERALLS_REPO_TOKEN=LdECqqwg7eelQx9w8gvooUZCFIaCqGZCv commands = - make checks coverage - coverage report - coveralls --ignore-errors + make checks From 007affbf08328c1b9f3971d60f8850251f5c46c5 Mon Sep 17 00:00:00 2001 From: Petter Friberg Date: Wed, 4 May 2022 22:08:45 +0200 Subject: [PATCH 2/2] fixup! Change test runner to `pytest` --- setup.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index af7a912..ebe34ea 100644 --- a/setup.py +++ b/setup.py @@ -106,11 +106,13 @@ def fullsplit(path, result=None): "pytest-django", ], "dev": [ + "Django", + "djangorestframework", "pytest", "pytest-cov", + "pytest-django", "black", "isort", - "Django", "mypy", "django-stubs", "djangorestframework-stubs",