From b3a35e0f7aca0eb11aa171f3919d3229e789a45b Mon Sep 17 00:00:00 2001 From: clarktr1 Date: Mon, 21 Sep 2026 17:46:35 -0500 Subject: [PATCH 1/9] upgrade django, python, docker configs, and syntax --- Dockerfile | 2 +- README.md | 2 +- docker-compose.yml | 2 +- docs/conf.py | 17 +++++++---------- name/__init__.py | 2 +- name/api/serializers.py | 2 +- name/api/stats.py | 6 +++--- name/api/views.py | 2 +- name/decorators.py | 2 +- name/feeds.py | 6 +++--- name/models.py | 15 ++++++++------- name/views.py | 8 ++++---- pyproject.toml | 40 ++++++++++++++++++++++++++-------------- runtests.py | 3 +-- tests/conftest.py | 12 ++++++------ tests/test_decorators.py | 2 +- tests/test_models.py | 4 ++-- tests/test_views.py | 5 ++--- 18 files changed, 70 insertions(+), 62 deletions(-) diff --git a/Dockerfile b/Dockerfile index 801439b..e261c3b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.9 +FROM python:3.14 ENV PYTHONUNBUFFERED 1 ENV PYTHONPATH /app diff --git a/README.md b/README.md index c4a00b5..5c90075 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Contributors: ## Requirements -- Python 3.9 or later +- Python 3.12 or later ## Development diff --git a/docker-compose.yml b/docker-compose.yml index ea4005b..6d51778 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: mariadb: - image: mariadb:10.5 + image: mariadb:11.4.13 environment: - MYSQL_ROOT_PASSWORD=root - MYSQL_DATABASE=name diff --git a/docs/conf.py b/docs/conf.py index 7ed78e0..5c72bc0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Django Name documentation build configuration file, created by # sphinx-quickstart on Fri May 8 09:55:15 2015. @@ -12,10 +11,8 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys import os import re -import shlex # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -47,9 +44,9 @@ master_doc = 'index' # General information about the project. -project = u'Django Name' -copyright = u'2017, University of North Texas Libraries' -author = u'University of North Texas Libraries' +project = 'Django Name' +copyright = '2017, University of North Texas Libraries' +author = 'University of North Texas Libraries' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -235,8 +232,8 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'DjangoName.tex', u'Django Name Documentation', - u'University of North Texas Libraries', 'manual'), + (master_doc, 'DjangoName.tex', 'Django Name Documentation', + 'University of North Texas Libraries', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -265,7 +262,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'djangoname', u'Django Name Documentation', + (master_doc, 'djangoname', 'Django Name Documentation', [author], 1) ] @@ -279,7 +276,7 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'DjangoName', u'Django Name Documentation', + (master_doc, 'DjangoName', 'Django Name Documentation', author, 'DjangoName', 'One line description of project.', 'Miscellaneous'), ] diff --git a/name/__init__.py b/name/__init__.py index 8cf0c0e..44e23ef 100644 --- a/name/__init__.py +++ b/name/__init__.py @@ -1,2 +1,2 @@ __title__ = 'Django Name' -__version__ = '5.0.0' +__version__ = '6.0.0' diff --git a/name/api/serializers.py b/name/api/serializers.py index 848684a..9722139 100644 --- a/name/api/serializers.py +++ b/name/api/serializers.py @@ -144,7 +144,7 @@ def get_label(self, obj): " ()" """ if obj.disambiguation: - return '{0} ({1})'.format(obj.name, obj.disambiguation) + return f'{obj.name} ({obj.disambiguation})' return obj.name diff --git a/name/api/stats.py b/name/api/stats.py index d85ecd6..1fc82df 100644 --- a/name/api/stats.py +++ b/name/api/stats.py @@ -4,7 +4,7 @@ from dateutil.relativedelta import relativedelta -class NameStatisticsMonth(object): +class NameStatisticsMonth: """A simple datatype to represent Name statistics for a single month. """ @@ -15,7 +15,7 @@ def __init__(self, **kwargs): self.month = kwargs.get('month', None) -class NameStatisticsType(object): +class NameStatisticsType: """Statistics class for calculating the number of Name objects in the database using a DateTime field. @@ -98,7 +98,7 @@ def process_raw_stats(self): current += delta -class NameStatistics(object): +class NameStatistics: """Container class for all statistics gathered on Name objects. """ diff --git a/name/api/views.py b/name/api/views.py index ecb1ac2..e194d51 100644 --- a/name/api/views.py +++ b/name/api/views.py @@ -14,7 +14,7 @@ class JSONResponse(http.HttpResponse): def __init__(self, data, **kwargs): content = JSONRenderer().render(data, renderer_context={'indent': 4}) kwargs['content_type'] = 'application/json' - super(JSONResponse, self).__init__(content, **kwargs) + super().__init__(content, **kwargs) def name_json(request, name_id): diff --git a/name/decorators.py b/name/decorators.py index 1c14ed9..a7faa49 100644 --- a/name/decorators.py +++ b/name/decorators.py @@ -22,7 +22,7 @@ def jsonp_wrapper(request, *args, **kwargs): if 'callback' in request.GET: callback = request.GET['callback'] resp['Content-Type'] = 'application/javascript; charset=utf-8' - resp.content = "%s(%s)" % (callback, resp.content) + resp.content = f"{callback}({resp.content})" return resp else: return resp diff --git a/name/feeds.py b/name/feeds.py index c9546dd..910dacf 100644 --- a/name/feeds.py +++ b/name/feeds.py @@ -18,12 +18,12 @@ class NameAtomFeedType(Atom1Feed): GEO_RSS_NS = 'http://www.georss.org/georss' def root_attributes(self): - attrs = super(NameAtomFeedType, self).root_attributes() + attrs = super().root_attributes() attrs['xmlns:georss'] = self.GEO_RSS_NS return attrs def add_item_elements(self, handler, item): - super(NameAtomFeedType, self).add_item_elements(handler, item) + super().add_item_elements(handler, item) # Add the georss:point element if the item has a geo_point # attribute. @@ -50,7 +50,7 @@ def item_title(self, obj): return obj.name def item_description(self, obj): - return 'Name Type: {0}'.format(obj.get_name_type_label()) + return f'Name Type: {obj.get_name_type_label()}' def item_link(self, obj): return obj.get_absolute_url() diff --git a/name/models.py b/name/models.py index 67e924f..44c50fb 100644 --- a/name/models.py +++ b/name/models.py @@ -148,7 +148,7 @@ def save(self, *args, **kwargs): self.normalized_variant = normalizeSimplified(self.variant) if 'update_fields' in kwargs: kwargs['update_fields'] = {'normalized_variant'}.union(kwargs['update_fields']) - super(Variant, self).save(*args, **kwargs) + super().save(*args, **kwargs) def __str__(self): return self.variant @@ -196,7 +196,7 @@ def ticket(self): return self.id def __str__(self): - return 'nm{ticket:07d}'.format(ticket=self.ticket) + return f'nm{self.ticket:07d}' class NameManager(models.Manager): @@ -513,8 +513,9 @@ def save(self, *args, **kwargs): self.__normalize_name() self.__assign_name_id() if 'update_fields' in kwargs: - kwargs['update_fields'] = {'normalized_name', 'name_id', 'last_modified'}.union(kwargs['update_fields']) - super(Name, self).save(*args, **kwargs) + kwargs['update_fields'] = ({'normalized_name', 'name_id', 'last_modified'} + .union(kwargs['update_fields'])) + super().save(*args, **kwargs) if self.is_building() and not self.location_set.count(): self.__find_location() @@ -522,7 +523,7 @@ def clean(self, *args, **kwargs): # Call merged_with_validator here so that we can pass in # the model instance. validate_merged_with(self) - super(Name, self).clean(*args, **kwargs) + super().clean(*args, **kwargs) def __str__(self): return self.name_id @@ -587,14 +588,14 @@ class Meta: base_manager_name = 'objects' def geo_point(self): - return '{lat} {lng}'.format(lat=self.latitude, lng=self.longitude) + return f'{self.latitude} {self.longitude}' def is_current(self): """True if the Location has a status of Current.""" return self.CURRENT == self.status def save(self, *args, **kwargs): - super(Location, self).save(*args, **kwargs) + super().save(*args, **kwargs) # When this instance's status is CURRENT, get all other locations # related the belong_to_name, and set the status to FORMER. if self.is_current(): diff --git a/name/views.py b/name/views.py index 8b7a1df..073b7dd 100644 --- a/name/views.py +++ b/name/views.py @@ -31,13 +31,13 @@ def label(request, name_value): except Name.DoesNotExist: return http.HttpResponseNotFound( - 'No matching term found - authoritative or variant - for "{0}"' - .format(name_value)) + f'No matching term found - authoritative or variant - for "{name_value}"' + ) except Name.MultipleObjectsReturned: return http.HttpResponseNotFound( - 'There are multiple Name objects with the same name: "{0}".' - .format(normalized_name)) + f'There are multiple Name objects with the same name: "{normalized_name}".' + ) def detail(request, name_id): diff --git a/pyproject.toml b/pyproject.toml index 3a1b05d..90f5369 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,10 +6,10 @@ build-backend = "setuptools.build_meta" name = "django-name" description = "Name Authority App for Django." readme = "README.md" -version = "5.0.0" +version = "6.0.0" license = {file = 'LICENSE'} keywords = ["django", "name", "citation"] -requires-python = ">=3.9,<4.0" +requires-python = ">=3.12" authors = [ { name = "University of North Texas Libraries", email = "mark.phillips@unt.edu" } ] @@ -19,7 +19,9 @@ classifiers = [ "Intended Audience :: End Users/Desktop", "Natural Language :: English", "Programming Language :: Python", - "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application" ] dependencies = [ @@ -35,28 +37,38 @@ Repository = "https://github.com/unt-libraries/django-name" [project.optional-dependencies] -codestyle = ["flake8"] dev = [ - "Django==4.2.27", + "Django~=6.1", "django-debug-toolbar==3.8.1", - "mysqlclient==2.0.1", + "mysqlclient~=2.3.0", ] test = [ - "tox>=3.3.0", "markdown2>=2.4.0", "pytest>=7.1.0", "pytest-django>=4.6.2", "pytest-cov>=7.0.0", "psycopg2-binary>=2.9.9", "tomli>=2.0.1", + "ruff~=0.15.9", ] +[tool.ruff] +line-length = 99 +target-version = "py314" +extend-exclude = ['migrations'] + +[tool.ruff.format] +quote-style = "single" + +[tool.ruff.lint] +select = ["E", "F", "W"] + [tool.tox] legacy_tox_ini =''' [tox] envlist = - py39-django42-{postgres,mariadb}, - py39-flake8, + py314-django61-{postgres,mariadb}, + ruff docs [testenv] @@ -65,20 +77,20 @@ legacy_tox_ini =''' extras = test dev - codestyle commands = mariadb: ./runtests.py {posargs} --nolint --ds=tests.settings.test_mariadb postgres: ./runtests.py {posargs} --nolint --ds=tests.settings.test_postgres - [testenv:py39-django42-mariadb] + [testenv:py3{12,13,14}-django61-mariadb] commands = ./runtests.py {posargs} --nolint --ds=tests.settings.test_mariadb --cov=name allowlist_externals = ./runtests.py - [testenv:py39-flake8] + [testenv:ruff] + skip_install = true + deps = ruff commands = - ./runtests.py --lintonly - allowlist_externals = ./runtests.py + ruff check . [testenv:docs] deps = Sphinx>=4.0 diff --git a/runtests.py b/runtests.py index cbcb417..d557c18 100755 --- a/runtests.py +++ b/runtests.py @@ -1,5 +1,4 @@ #! /usr/bin/env python -from __future__ import print_function import pytest import sys @@ -32,7 +31,7 @@ def flake8_main(args): def split_class_and_function(string): class_string, function_string = string.split('.', 1) - return "%s and %s" % (class_string, function_string) + return f"{class_string} and {function_string}" def is_function(string): diff --git a/tests/conftest.py b/tests/conftest.py index 1bec3b7..db0f17b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -36,7 +36,7 @@ def twenty_name_fixtures(db, scope="session"): """ for x in range(21): Name.objects.create( - name="Name {0}".format(x), + name=f"Name {x}", name_type=random.randint(0, 4), begin='2012-01-12') return Name.objects.all() @@ -75,13 +75,13 @@ def search_fixtures(db, scope='module'): """ for x in range(1, 5): Name.objects.create( - name="Personal {0}".format(x), name_type=Name.PERSONAL) + name=f"Personal {x}", name_type=Name.PERSONAL) Name.objects.create( - name="Organization {0}".format(x), name_type=Name.ORGANIZATION) + name=f"Organization {x}", name_type=Name.ORGANIZATION) Name.objects.create( - name="Event {0}".format(x), name_type=Name.EVENT) + name=f"Event {x}", name_type=Name.EVENT) Name.objects.create( - name="Software {0}".format(x), name_type=Name.SOFTWARE) + name=f"Software {x}", name_type=Name.SOFTWARE) Name.objects.create( - name="Building {0}".format(x), name_type=Name.BUILDING) + name=f"Building {x}", name_type=Name.BUILDING) return Name.objects.all() diff --git a/tests/test_decorators.py b/tests/test_decorators.py index c35f86c..7fa1291 100644 --- a/tests/test_decorators.py +++ b/tests/test_decorators.py @@ -38,7 +38,7 @@ def test_jsonp_returns_with_callback(): result = decorated_f(request) - expected = 'init({0})'.format(json) + expected = f'init({json})' assert expected == result.content diff --git a/tests/test_models.py b/tests/test_models.py index 0d6aded..371f5b4 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -60,10 +60,10 @@ class TestBaseTicketing: def test_has_str_method(self): ticket_id = 1 ticket = BaseTicketing(id=ticket_id) - assert 'nm{:07d}'.format(ticket_id) == str(ticket) + assert f'nm{ticket_id:07d}' == str(ticket) -class TestNameManager(object): +class TestNameManager: @pytest.fixture def time_series_names(self): diff --git a/tests/test_views.py b/tests/test_views.py index 75c05d8..194a8de 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -88,8 +88,7 @@ def test_label_returns_not_found_multiple_names_found(client): def test_export(client, name_fixture): response = client.get(reverse('name:export')) - expected = 'personal\ttest person\thttp://testserver{}\r\n'.format( - name_fixture.get_absolute_url()) + expected = f'personal\ttest person\thttp://testserver{name_fixture.get_absolute_url()}\r\n' assert expected == response.content.decode() assert 200 == response.status_code @@ -99,7 +98,7 @@ def test_export_json(client, name_fixture): expected = [ { 'i': name_fixture.name_id, - 'l': 'http://testserver{}'.format(name_fixture.get_absolute_url()), + 'l': f'http://testserver{name_fixture.get_absolute_url()}', 't': name_fixture.name, }, ] From 4d5c6538014293d088d3772930dd27297e0aa6c6 Mon Sep 17 00:00:00 2001 From: clarktr1 Date: Tue, 22 Sep 2026 13:24:20 -0500 Subject: [PATCH 2/9] add tox to container build --- .github/workflows/test.yml | 2 +- Dockerfile | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 160c33a..9445866 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,6 +12,6 @@ jobs: uses: actions/checkout@v3 - name: Start the app run: docker compose up -d - - name: Run the tests and flake8 + - name: Run the tests and ruff run: docker compose run --rm web tox diff --git a/Dockerfile b/Dockerfile index e261c3b..8e82f85 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,4 +15,5 @@ WORKDIR /app COPY . /app/ # Install dependencies +RUN pip install tox RUN pip install .'[dev,test,codestyle]' From d8df06be2e14bff08fd8f30b8b66967d5b1a86b7 Mon Sep 17 00:00:00 2001 From: clarktr1 Date: Wed, 23 Sep 2026 10:26:28 -0500 Subject: [PATCH 3/9] replace double quotes in f-strings with single quotes --- name/decorators.py | 2 +- runtests.py | 2 +- tests/conftest.py | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/name/decorators.py b/name/decorators.py index a7faa49..44418f3 100644 --- a/name/decorators.py +++ b/name/decorators.py @@ -22,7 +22,7 @@ def jsonp_wrapper(request, *args, **kwargs): if 'callback' in request.GET: callback = request.GET['callback'] resp['Content-Type'] = 'application/javascript; charset=utf-8' - resp.content = f"{callback}({resp.content})" + resp.content = f'{callback}({resp.content})' return resp else: return resp diff --git a/runtests.py b/runtests.py index d557c18..5f04a76 100755 --- a/runtests.py +++ b/runtests.py @@ -31,7 +31,7 @@ def flake8_main(args): def split_class_and_function(string): class_string, function_string = string.split('.', 1) - return f"{class_string} and {function_string}" + return f'{class_string} and {function_string}' def is_function(string): diff --git a/tests/conftest.py b/tests/conftest.py index db0f17b..b13f081 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -36,7 +36,7 @@ def twenty_name_fixtures(db, scope="session"): """ for x in range(21): Name.objects.create( - name=f"Name {x}", + name='Name {x}', name_type=random.randint(0, 4), begin='2012-01-12') return Name.objects.all() @@ -75,13 +75,13 @@ def search_fixtures(db, scope='module'): """ for x in range(1, 5): Name.objects.create( - name=f"Personal {x}", name_type=Name.PERSONAL) + name=f'Personal {x}', name_type=Name.PERSONAL) Name.objects.create( - name=f"Organization {x}", name_type=Name.ORGANIZATION) + name=f'Organization {x}', name_type=Name.ORGANIZATION) Name.objects.create( - name=f"Event {x}", name_type=Name.EVENT) + name=f'Event {x}', name_type=Name.EVENT) Name.objects.create( - name=f"Software {x}", name_type=Name.SOFTWARE) + name=f'Software {x}', name_type=Name.SOFTWARE) Name.objects.create( - name=f"Building {x}", name_type=Name.BUILDING) + name=f'Building {x}', name_type=Name.BUILDING) return Name.objects.all() From 551399de5b5eb35cc30a7fb7faad649b640f64fb Mon Sep 17 00:00:00 2001 From: clarktr1 Date: Wed, 23 Sep 2026 10:33:19 -0500 Subject: [PATCH 4/9] remove unused envs from tox --- pyproject.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 90f5369..04a1737 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -81,7 +81,7 @@ legacy_tox_ini =''' mariadb: ./runtests.py {posargs} --nolint --ds=tests.settings.test_mariadb postgres: ./runtests.py {posargs} --nolint --ds=tests.settings.test_postgres - [testenv:py3{12,13,14}-django61-mariadb] + [testenv:py314-django61-mariadb] commands = ./runtests.py {posargs} --nolint --ds=tests.settings.test_mariadb --cov=name allowlist_externals = ./runtests.py @@ -93,6 +93,7 @@ legacy_tox_ini =''' ruff check . [testenv:docs] + skip_install = true deps = Sphinx>=4.0 changedir = docs commands = {envbindir}/sphinx-build -W -b html . {envtmpdir}/html From 9e2cacb4df7044c3dc19e2b52cebeacacbe89922 Mon Sep 17 00:00:00 2001 From: clarktr1 Date: Wed, 23 Sep 2026 11:28:22 -0500 Subject: [PATCH 5/9] remove codestyle from installs --- Dockerfile | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8e82f85..ed37db9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,4 +16,4 @@ COPY . /app/ # Install dependencies RUN pip install tox -RUN pip install .'[dev,test,codestyle]' +RUN pip install .'[dev,test]' diff --git a/README.md b/README.md index 5c90075..2d2b783 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ $ source env/bin/activate Install the dev dependencies ```sh -$ pip install .'[dev,test,codestyle]' +$ pip install .'[dev,test]' ``` Replace the `DATABASES` Django setting in `./tests/settings/dev.py` with From 32cc30fadc83eeff78f0cc66434630f05435d1b7 Mon Sep 17 00:00:00 2001 From: clarktr1 Date: Fri, 25 Sep 2026 09:39:25 -0500 Subject: [PATCH 6/9] add missing f-string --- tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index b13f081..926c893 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -36,7 +36,7 @@ def twenty_name_fixtures(db, scope="session"): """ for x in range(21): Name.objects.create( - name='Name {x}', + name=f'Name {x}', name_type=random.randint(0, 4), begin='2012-01-12') return Name.objects.all() From 4f741d2e0302ec022dfc598d1d926348a20a47ed Mon Sep 17 00:00:00 2001 From: clarktr1 Date: Thu, 8 Oct 2026 16:20:32 -0500 Subject: [PATCH 7/9] switch flake8 with ruff in tests, update test import, readme, and pyproject, remove coveragerc --- .coveragerc | 7 ------- README.md | 2 +- pyproject.toml | 24 ++++++++++++++++-------- runtests.py | 20 ++++++++++---------- tests/test_search.py | 2 +- 5 files changed, 28 insertions(+), 27 deletions(-) delete mode 100644 .coveragerc diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 2292bec..0000000 --- a/.coveragerc +++ /dev/null @@ -1,7 +0,0 @@ -[run] -source = name -omit = */migrations/* -branch = true - -[report] -show_missing = true diff --git a/README.md b/README.md index 2d2b783..6ef9648 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Contributors: ## Requirements -- Python 3.12 or later +- Python 3.12 - 3.14 ## Development diff --git a/pyproject.toml b/pyproject.toml index 04a1737..7378861 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ readme = "README.md" version = "6.0.0" license = {file = 'LICENSE'} keywords = ["django", "name", "citation"] -requires-python = ">=3.12" +requires-python = ">=3.12,<3.15" authors = [ { name = "University of North Texas Libraries", email = "mark.phillips@unt.edu" } ] @@ -38,8 +38,8 @@ Repository = "https://github.com/unt-libraries/django-name" [project.optional-dependencies] dev = [ - "Django~=6.1", - "django-debug-toolbar==3.8.1", + "Django~=6.1.0", + "django-debug-toolbar~=7.1.0", "mysqlclient~=2.3.0", ] test = [ @@ -55,7 +55,7 @@ test = [ [tool.ruff] line-length = 99 target-version = "py314" -extend-exclude = ['migrations'] +extend-exclude = ["migrations"] [tool.ruff.format] quote-style = "single" @@ -63,6 +63,14 @@ quote-style = "single" [tool.ruff.lint] select = ["E", "F", "W"] +[tool.coverage.run] +source = ["name"] +omit = ["*/migrations/*"] +branch = true + +[tool.coverage.report] +show_missing = true + [tool.tox] legacy_tox_ini =''' [tox] @@ -78,19 +86,19 @@ legacy_tox_ini =''' test dev commands = - mariadb: ./runtests.py {posargs} --nolint --ds=tests.settings.test_mariadb - postgres: ./runtests.py {posargs} --nolint --ds=tests.settings.test_postgres + mariadb: ./runtests.py {posargs} --ds=tests.settings.test_mariadb + postgres: ./runtests.py {posargs} --ds=tests.settings.test_postgres [testenv:py314-django61-mariadb] commands = - ./runtests.py {posargs} --nolint --ds=tests.settings.test_mariadb --cov=name + ./runtests.py {posargs} --ds=tests.settings.test_mariadb --cov=name allowlist_externals = ./runtests.py [testenv:ruff] skip_install = true - deps = ruff commands = ruff check . + allowlist_externals = ruff [testenv:docs] skip_install = true diff --git a/runtests.py b/runtests.py index 5f04a76..bb6307b 100755 --- a/runtests.py +++ b/runtests.py @@ -11,7 +11,7 @@ 'fast': ['tests', '-q'], } -FLAKE8_ARGS = ['name', 'tests', '--ignore=F403,E501,F999,W504'] +RUFF_ARGS = ['check', '.'] sys.path.append(os.path.dirname(__file__)) @@ -22,10 +22,10 @@ def exit_on_failure(ret, message=None): sys.exit(ret) -def flake8_main(args): - print('Running flake8 code linting') - ret = subprocess.call(['flake8'] + args) - print('flake8 failed' if ret else 'flake8 passed') +def ruff_main(args): + print('Running ruff code linting') + ret = subprocess.call(['ruff'] + args) + print('ruff failed' if ret else 'ruff passed') return ret @@ -48,9 +48,9 @@ def is_class(string): try: sys.argv.remove('--nolint') except ValueError: - run_flake8 = True + run_ruff = True else: - run_flake8 = False + run_ruff = False try: sys.argv.remove('--lintonly') @@ -65,7 +65,7 @@ def is_class(string): style = 'default' else: style = 'fast' - run_flake8 = False + run_ruff = False if len(sys.argv) > 1: pytest_args = sys.argv[1:] @@ -86,5 +86,5 @@ def is_class(string): if run_tests: exit_on_failure(pytest.main(pytest_args)) - if run_flake8: - exit_on_failure(flake8_main(FLAKE8_ARGS)) + if run_ruff: + exit_on_failure(ruff_main(RUFF_ARGS)) diff --git a/tests/test_search.py b/tests/test_search.py index 2d22798..5651e5b 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -4,7 +4,7 @@ from django.urls import reverse # All test need access to the database in this file. -pytestmark = pytest.mark.django +pytestmark = pytest.mark.django_db query_template = '?q_type={0}&q={1}' From c96f0884f42ab4e17a950092fd539d5c0da18b2c Mon Sep 17 00:00:00 2001 From: clarktr1 Date: Fri, 9 Oct 2026 12:17:23 -0500 Subject: [PATCH 8/9] remove lint from runtest script --- pyproject.toml | 6 +++--- runtests.py | 31 +------------------------------ 2 files changed, 4 insertions(+), 33 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7378861..613a7ec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,7 +33,7 @@ dependencies = [ [project.urls] Homepage = "https://github.com/unt-libraries/django-name" -Repository = "https://github.com/unt-libraries/django-name" +Repository = "https://github.com/unt-libraries/django-name.git" [project.optional-dependencies] @@ -75,7 +75,7 @@ show_missing = true legacy_tox_ini =''' [tox] envlist = - py314-django61-{postgres,mariadb}, + py314-django61-{postgres,mariadb} ruff docs @@ -90,7 +90,7 @@ legacy_tox_ini =''' postgres: ./runtests.py {posargs} --ds=tests.settings.test_postgres [testenv:py314-django61-mariadb] - commands = + commands = ./runtests.py {posargs} --ds=tests.settings.test_mariadb --cov=name allowlist_externals = ./runtests.py diff --git a/runtests.py b/runtests.py index bb6307b..59fb2fd 100755 --- a/runtests.py +++ b/runtests.py @@ -3,7 +3,6 @@ import pytest import sys import os -import subprocess PYTEST_ARGS = { @@ -11,9 +10,6 @@ 'fast': ['tests', '-q'], } -RUFF_ARGS = ['check', '.'] - - sys.path.append(os.path.dirname(__file__)) @@ -22,13 +18,6 @@ def exit_on_failure(ret, message=None): sys.exit(ret) -def ruff_main(args): - print('Running ruff code linting') - ret = subprocess.call(['ruff'] + args) - print('ruff failed' if ret else 'ruff passed') - return ret - - def split_class_and_function(string): class_string, function_string = string.split('.', 1) return f'{class_string} and {function_string}' @@ -45,27 +34,12 @@ def is_class(string): if __name__ == "__main__": - try: - sys.argv.remove('--nolint') - except ValueError: - run_ruff = True - else: - run_ruff = False - - try: - sys.argv.remove('--lintonly') - except ValueError: - run_tests = True - else: - run_tests = False - try: sys.argv.remove('--fast') except ValueError: style = 'default' else: style = 'fast' - run_ruff = False if len(sys.argv) > 1: pytest_args = sys.argv[1:] @@ -84,7 +58,4 @@ def is_class(string): else: pytest_args = PYTEST_ARGS[style] - if run_tests: - exit_on_failure(pytest.main(pytest_args)) - if run_ruff: - exit_on_failure(ruff_main(RUFF_ARGS)) + exit_on_failure(pytest.main(pytest_args)) From 259cff4b00fbd181a560cd994005107a33010978 Mon Sep 17 00:00:00 2001 From: clarktr1 Date: Fri, 9 Oct 2026 16:46:47 -0500 Subject: [PATCH 9/9] update pyproject for ruff to use py314 --- pyproject.toml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 613a7ec..79d232e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,7 +76,7 @@ legacy_tox_ini =''' [tox] envlist = py314-django61-{postgres,mariadb} - ruff + py314-ruff docs [testenv] @@ -94,11 +94,9 @@ legacy_tox_ini =''' ./runtests.py {posargs} --ds=tests.settings.test_mariadb --cov=name allowlist_externals = ./runtests.py - [testenv:ruff] - skip_install = true + [testenv:py314-ruff] commands = ruff check . - allowlist_externals = ruff [testenv:docs] skip_install = true