diff --git a/.coveragerc b/.coveragerc index e55531e..4cbd89e 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,4 +1,4 @@ [run] include = edc_registration/* omit = edc_registration/tests/*,edc_registration/migrations/* -branch = 1 \ No newline at end of file +branch = 1 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4ec2681..950e9aa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,20 +5,17 @@ on: [push, pull_request] jobs: build: - name: build (Python ${{ matrix.python-version }}, Django ${{ matrix.django-version }}) + name: | + build (Python ${{ matrix.python-version }}, Django ${{ matrix.django-version }}, ${{ matrix.database-engine }}) runs-on: ubuntu-latest strategy: fail-fast: false matrix: - python-version: ['3.11', '3.12'] - django-version: ['4.2', '5.0', 'dev'] + python-version: ['3.12', '3.13'] + django-version: ['5.1', 'dev'] + database-engine: ["mysql", "postgres"] - exclude: - - python-version: '3.12' - django-version: '4.2' - - python-version: '3.11' - django-version: 'dev' services: mysql: image: mysql:latest @@ -28,6 +25,17 @@ jobs: ports: - 3306:3306 options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + postgres: + image: postgres:latest + env: + POSTGRES_PASSWORD: postgres + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + - 5432:5432 steps: - name: Install pycups and words dependency @@ -36,9 +44,9 @@ jobs: sudo apt-get -y update sudo apt-get install libcups2-dev wamerican - - uses: actions/checkout@v3 + - 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 }} @@ -48,7 +56,7 @@ jobs: echo "dir=$(pip cache dir)" >>$GITHUB_OUTPUT - name: Cache - uses: actions/cache@v3 + uses: actions/cache@v4 with: path: ${{ steps.pip-cache.outputs.dir }} key: @@ -61,7 +69,6 @@ jobs: python -m pip install --upgrade pip python -m pip install -r https://raw.githubusercontent.com/clinicedc/edc/develop/requirements.tests/tox.txt - - name: Tox tests run: | tox -v diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6f3af91..bace820 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -3,46 +3,49 @@ exclude: tests/etc/user-* repos: - repo: https://github.com/PyCQA/bandit - rev: 1.7.5 + rev: 1.7.10 hooks: - id: bandit args: - "-x *test*.py" - repo: https://github.com/psf/black - rev: 23.9.1 + rev: 24.10.0 hooks: - id: black - language_version: python3.11 + language_version: python3.12 - repo: https://github.com/pycqa/flake8 - rev: 6.1.0 + rev: 7.1.1 hooks: - id: flake8 args: - "--config=setup.cfg" - repo: https://github.com/PyCQA/isort - rev: 5.12.0 + rev: 5.13.2 hooks: - id: isort - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v5.0.0 hooks: - - id: requirements-txt-fixer - files: requirements/.*\.txt$ - - id: trailing-whitespace - id: check-added-large-files - - id: fix-byte-order-marker - id: check-docstring-first - id: check-executables-have-shebangs - id: check-merge-conflict + - id: check-toml + - id: check-yaml - id: debug-statements - id: detect-private-key + - id: end-of-file-fixer + - id: fix-byte-order-marker + - id: requirements-txt-fixer + files: requirements/.*\.txt$ + - id: trailing-whitespace - repo: https://github.com/adrienverge/yamllint - rev: v1.32.0 + rev: v1.35.1 hooks: - id: yamllint args: diff --git a/LICENSE b/LICENSE index 8cdb845..23cb790 100644 --- a/LICENSE +++ b/LICENSE @@ -337,4 +337,3 @@ proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. - diff --git a/README.rst b/README.rst index 3712ee1..8b3b93b 100644 --- a/README.rst +++ b/README.rst @@ -67,8 +67,8 @@ A subject's ``RegisteredSubject`` instance is created and updated in a ``post_sa .. |pypi| image:: https://img.shields.io/pypi/v/edc-registration.svg :target: https://pypi.python.org/pypi/edc-registration -.. |actions| image:: https://github.com/clinicedc/edc-registration/workflows/build/badge.svg?branch=develop - :target: https://github.com/clinicedc/edc-registration/actions?query=workflow:build +.. |actions| image:: https://github.com/clinicedc/edc-registration/actions/workflows/build.yml/badge.svg + :target: https://github.com/clinicedc/edc-registration/actions/workflows/build.yml .. |codecov| image:: https://codecov.io/gh/clinicedc/edc-registration/branch/develop/graph/badge.svg :target: https://codecov.io/gh/clinicedc/edc-registration diff --git a/edc_registration/model_mixins/updates_or_creates_registered_subject_model_mixin.py b/edc_registration/model_mixins/updates_or_creates_registered_subject_model_mixin.py index 26138f2..3642779 100644 --- a/edc_registration/model_mixins/updates_or_creates_registered_subject_model_mixin.py +++ b/edc_registration/model_mixins/updates_or_creates_registered_subject_model_mixin.py @@ -17,7 +17,6 @@ class UpdatesOrCreatesRegistrationModelError(Exception): class UpdatesOrCreatesRegistrationModelMixin(models.Model): - """A model mixin that creates or updates Registration model (e.g. RegisteredSubject) on post_save signal. """ diff --git a/edc_registration/modeladmin_mixins.py b/edc_registration/modeladmin_mixins.py index fbe0918..f01760c 100644 --- a/edc_registration/modeladmin_mixins.py +++ b/edc_registration/modeladmin_mixins.py @@ -62,6 +62,7 @@ def get_list_display(self, request): "initials", "gender", "subject_type", + "screening_identifier", "sid", "registration_status", "site", @@ -74,6 +75,7 @@ def get_list_display(self, request): "dashboard", "gender", "subject_type", + "screening_identifier", "sid", "registration_status", "site", diff --git a/edc_registration/tests/models.py b/edc_registration/tests/models.py index 9dee74f..a1f57e8 100644 --- a/edc_registration/tests/models.py +++ b/edc_registration/tests/models.py @@ -19,7 +19,6 @@ def registration_unique_field(self): class SubjectModelTwo(UpdatesOrCreatesRegistrationModelMixin, BaseUuidModel): - """Note: registration_unique_field is overridden.""" subject_identifier = models.CharField(max_length=25, null=True) @@ -32,7 +31,6 @@ def registration_unique_field(self): class SubjectModelThree(UpdatesOrCreatesRegistrationModelMixin, BaseUuidModel): - """Note: registration_unique_field is overridden.""" subject_identifier = models.CharField(max_length=25, null=True) diff --git a/edc_registration/tests/test_settings.py b/edc_registration/tests/test_settings.py new file mode 100644 index 0000000..1978755 --- /dev/null +++ b/edc_registration/tests/test_settings.py @@ -0,0 +1,61 @@ +import sys +from pathlib import Path + +from edc_test_settings.default_test_settings import DefaultTestSettings + +app_name = "edc_registration" +base_dir = Path(__file__).absolute().parent.parent.parent + +project_settings = DefaultTestSettings( + calling_file=__file__, + BASE_DIR=base_dir, + APP_NAME=app_name, + SILENCED_SYSTEM_CHECKS=[ + "sites.E101", + "edc_navbar.E002", + "edc_sites.E001", + "edc_sites.E002", + ], + SUBJECT_VISIT_MODEL="edc_visit_tracking.subjectvisit", + INSTALLED_APPS=[ + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.sites", + "django_crypto_fields.apps.AppConfig", + "django_revision.apps.AppConfig", + "multisite", + "adverse_event_app.apps.AppConfig", + "edc_action_item.apps.AppConfig", + "edc_adverse_event.apps.AppConfig", + "edc_appointment.apps.AppConfig", + # "edc_auth.apps.AppConfig", + "edc_dashboard.apps.AppConfig", + # "edc_data_manager.apps.AppConfig", + # "edc_device.apps.AppConfig", + # "edc_facility.apps.AppConfig", + # "edc_form_runners.apps.AppConfig", + # "edc_identifier.apps.AppConfig", + # "edc_lab.apps.AppConfig", + # "edc_label.apps.AppConfig", + # "edc_locator.apps.AppConfig", + # "edc_metadata.apps.AppConfig", + "edc_notification.apps.AppConfig", + # "edc_offstudy.apps.AppConfig", + "edc_registration.apps.AppConfig", + "edc_review_dashboard.apps.AppConfig", + "edc_sites.apps.AppConfig", + "edc_subject_dashboard.apps.AppConfig", + # "edc_timepoint.apps.AppConfig", + "edc_visit_schedule.apps.AppConfig", + "edc_visit_tracking.apps.AppConfig", + "edc_appconfig.apps.AppConfig", + ], + add_dashboard_middleware=True, +).settings + +for k, v in project_settings.items(): + setattr(sys.modules[__name__], k, v) diff --git a/pyproject.toml b/pyproject.toml index 9afec50..888cb41 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,17 +1,18 @@ [build-system] requires = ["setuptools>=60", "setuptools-scm>=8.0"] +build-backend = "setuptools.build_meta" [tool.setuptools_scm] -version_file="_version.py" +version_file = "_version.py" [tool.black] line-length = 95 -target-version = ["py311"] +target-version = ["py312"] extend-exclude = '''^(.*\/)*\b(migrations)\b($|\/.*$)''' [tool.isort] profile = "black" -py_version = "311" +py_version = "312" skip = [".tox", ".eggs", "migrations"] [tool.coverage.run] @@ -35,35 +36,33 @@ exclude_lines = [ legacy_tox_ini = """ [tox] envlist = - py{311}-dj{42,50}, - py{312}-dj{50,dev}, + py{312,313}-dj{51,dev}, lint + pre-commit isolated_build = true [gh-actions] python = - 3.11: py311 - 3.12: py312, lint + 3.12: py312, lint, pre-commit + 3.13: py313 [gh-actions:env] DJANGO = - 4.2: dj42 - 5.0: dj50 - dev: djdev, lint + 5.1: dj51 + dev: djdev, lint, pre-commit [testenv] deps = -r https://raw.githubusercontent.com/clinicedc/edc/develop/requirements.tests/tox.txt -r https://raw.githubusercontent.com/clinicedc/edc/develop/requirements.tests/test_utils.txt -r https://raw.githubusercontent.com/clinicedc/edc/develop/requirements.tests/edc.txt - -r https://raw.githubusercontent.com/clinicedc/edc/develop/requirements.tests/third_party_dev.txt - dj42: Django>=4.2,<5.0 - dj50: Django>=5.0 + dj51: Django>=5.1,<5.2 djdev: https://github.com/django/django/tarball/main commands = - pip install -U pip coverage[toml] + pip install -U pip + python --version pip --version pip freeze coverage run -a runtests.py @@ -72,7 +71,19 @@ commands = [testenv:lint] deps = -r https://raw.githubusercontent.com/clinicedc/edc/develop/requirements.tests/lint.txt commands = + python --version + pip --version + pip freeze isort --profile=black --check --diff . black --check --diff . flake8 . + +[testenv:pre-commit] +deps = pre-commit +commands = + python --version + pip --version + pip freeze + pre-commit autoupdate + pre-commit run --all-files """ diff --git a/runtests.py b/runtests.py index 9fb5963..220f674 100644 --- a/runtests.py +++ b/runtests.py @@ -1,67 +1,5 @@ #!/usr/bin/env python -import logging -from pathlib import Path - -from edc_test_utils import DefaultTestSettings, func_main - -app_name = "edc_registration" -base_dir = Path(__file__).absolute().parent - -project_settings = DefaultTestSettings( - calling_file=__file__, - BASE_DIR=base_dir, - APP_NAME=app_name, - SILENCED_SYSTEM_CHECKS=[ - "sites.E101", - "edc_navbar.E002", - "edc_navbar.E003", - "edc_consent.E001", - "edc_sites.E001", - "edc_sites.E002", - ], - SUBJECT_VISIT_MODEL="edc_visit_tracking.subjectvisit", - ETC_DIR=str(base_dir / app_name / "tests" / "etc"), - INSTALLED_APPS=[ - "django.contrib.admin", - "django.contrib.auth", - "django.contrib.contenttypes", - "django.contrib.sessions", - "django.contrib.messages", - "django.contrib.staticfiles", - "django.contrib.sites", - "django_crypto_fields.apps.AppConfig", - "django_revision.apps.AppConfig", - "multisite", - "edc_action_item.apps.AppConfig", - "edc_appointment.apps.AppConfig", - "edc_auth.apps.AppConfig", - "edc_data_manager.apps.AppConfig", - "edc_device.apps.AppConfig", - "edc_facility.apps.AppConfig", - "edc_form_runners.apps.AppConfig", - "edc_identifier.apps.AppConfig", - "edc_lab.apps.AppConfig", - "edc_label.apps.AppConfig", - "edc_locator.apps.AppConfig", - "edc_metadata.apps.AppConfig", - "edc_notification.apps.AppConfig", - "edc_offstudy.apps.AppConfig", - "edc_registration.apps.AppConfig", - "edc_sites.apps.AppConfig", - "edc_timepoint.apps.AppConfig", - "edc_visit_schedule.apps.AppConfig", - "edc_visit_tracking.apps.AppConfig", - "edc_appconfig.apps.AppConfig", - ], - RANDOMIZATION_LIST_PATH=str(base_dir / app_name / "tests" / "test_randomization_list.csv"), - add_dashboard_middleware=True, -).settings - - -def main(): - func_main(project_settings, *[f"{app_name}.tests"]) - +from edc_test_settings.func_main import func_main2 if __name__ == "__main__": - logging.basicConfig() - main() + func_main2("edc_registration.tests.test_settings", "edc_registration.tests") diff --git a/setup.cfg b/setup.cfg index 2ae3843..f38b964 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,16 +12,15 @@ keywords = django edc registration, clinicedc, clinical trials classifiers= Environment :: Web Environment Framework :: Django - Framework :: Django :: 4.2 + Framework :: Django :: 5.1 Intended Audience :: Developers Intended Audience :: Science/Research Operating System :: OS Independent - Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3.12 License :: OSI Approved :: GNU General Public License v3 (GPLv3) - [options] -python_requires = >=3.11 +python_requires = >=3.12 zip_safe = False include_package_data = True packages = find: