diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml deleted file mode 100644 index 76f0b9305..000000000 --- a/.github/workflows/security.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Check Security Vulnerabilities - -on: - pull_request: - push: - branches: - - main - -jobs: - safety: - name: safety - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Set up Python 3.x - uses: actions/setup-python@v5 - with: - python-version: "3.13" - - run: python -m pip install tox - - name: safety - run: tox - env: - TOXENV: safety diff --git a/.gitignore b/.gitignore index 4c713189c..b6e8c9437 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ django-sample-app*/ *.swp *.swo *.sqlite3 +.app-style.json diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c1cfddb13..38e3ced0f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,7 +18,6 @@ repos: - id: mixed-line-ending args: [ '--fix=lf' ] description: Forces to replace line ending by the UNIX 'lf' character. - - id: fix-encoding-pragma - id: name-tests-test args: - --django diff --git a/django_extensions/__init__.py b/django_extensions/__init__.py index 87cef4971..f93ccdf85 100644 --- a/django_extensions/__init__.py +++ b/django_extensions/__init__.py @@ -1,6 +1,5 @@ -# -*- coding: utf-8 -*- from django.utils.version import get_version -VERSION = (4, 1, 0, "final", 0) +VERSION = (4, 2, 0, "alpha", 0) __version__ = get_version(VERSION) diff --git a/django_extensions/admin/__init__.py b/django_extensions/admin/__init__.py index ab9e69749..cfb39ec0e 100644 --- a/django_extensions/admin/__init__.py +++ b/django_extensions/admin/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # Autocomplete feature for admin panel # diff --git a/django_extensions/admin/filter.py b/django_extensions/admin/filter.py index 392b0c9c9..3a40def2a 100644 --- a/django_extensions/admin/filter.py +++ b/django_extensions/admin/filter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.contrib.admin import FieldListFilter from django.contrib.admin.utils import prepare_lookup_value from django.utils.translation import gettext_lazy as _ diff --git a/django_extensions/admin/widgets.py b/django_extensions/admin/widgets.py index 9ed89c303..69c12d2c5 100644 --- a/django_extensions/admin/widgets.py +++ b/django_extensions/admin/widgets.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import urllib from django import forms diff --git a/django_extensions/apps.py b/django_extensions/apps.py index 2a869f0de..d01cbf0d0 100644 --- a/django_extensions/apps.py +++ b/django_extensions/apps.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.apps import AppConfig diff --git a/django_extensions/auth/mixins.py b/django_extensions/auth/mixins.py index 791651ff5..ef42d3427 100644 --- a/django_extensions/auth/mixins.py +++ b/django_extensions/auth/mixins.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.contrib.auth.mixins import UserPassesTestMixin diff --git a/django_extensions/collision_resolvers.py b/django_extensions/collision_resolvers.py index 15ef1a840..df28252bb 100644 --- a/django_extensions/collision_resolvers.py +++ b/django_extensions/collision_resolvers.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import inspect import sys from abc import abstractmethod, ABCMeta diff --git a/django_extensions/compat.py b/django_extensions/compat.py index 8df20cd09..583286348 100644 --- a/django_extensions/compat.py +++ b/django_extensions/compat.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from io import BytesIO import csv diff --git a/django_extensions/db/fields/__init__.py b/django_extensions/db/fields/__init__.py index 2a2e0036e..20d4104da 100644 --- a/django_extensions/db/fields/__init__.py +++ b/django_extensions/db/fields/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Django Extensions additional model fields diff --git a/django_extensions/db/fields/json.py b/django_extensions/db/fields/json.py index 435a8de8e..b63c47e62 100644 --- a/django_extensions/db/fields/json.py +++ b/django_extensions/db/fields/json.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ JSONField automatically serializes most Python terms to JSON data. Creates a TEXT field with a default value of "{}". See test_json.py for diff --git a/django_extensions/db/models.py b/django_extensions/db/models.py index 1e35b9369..cb7ea551b 100644 --- a/django_extensions/db/models.py +++ b/django_extensions/db/models.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.db import models from django.utils.timezone import now from django.utils.translation import gettext_lazy as _ diff --git a/django_extensions/import_subclasses.py b/django_extensions/import_subclasses.py index f31dd25c8..13d826c8b 100644 --- a/django_extensions/import_subclasses.py +++ b/django_extensions/import_subclasses.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from importlib import import_module from inspect import ( getmembers, diff --git a/django_extensions/jobs/daily/cache_cleanup.py b/django_extensions/jobs/daily/cache_cleanup.py index a387ecf6c..4eb1e4135 100644 --- a/django_extensions/jobs/daily/cache_cleanup.py +++ b/django_extensions/jobs/daily/cache_cleanup.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Daily cleanup job. diff --git a/django_extensions/jobs/daily/daily_cleanup.py b/django_extensions/jobs/daily/daily_cleanup.py index 7abce710f..e5e2b7176 100644 --- a/django_extensions/jobs/daily/daily_cleanup.py +++ b/django_extensions/jobs/daily/daily_cleanup.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Daily cleanup job. diff --git a/django_extensions/logging/filters.py b/django_extensions/logging/filters.py index 3178c1ba6..29995020a 100644 --- a/django_extensions/logging/filters.py +++ b/django_extensions/logging/filters.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import time import logging from hashlib import md5 diff --git a/django_extensions/management/base.py b/django_extensions/management/base.py index ceabb6c80..60ebf401e 100644 --- a/django_extensions/management/base.py +++ b/django_extensions/management/base.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import sys from django.core.management.base import BaseCommand diff --git a/django_extensions/management/color.py b/django_extensions/management/color.py index ce893bbd0..884fa2b72 100644 --- a/django_extensions/management/color.py +++ b/django_extensions/management/color.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.core.management import color from django.utils import termcolors diff --git a/django_extensions/management/commands/admin_generator.py b/django_extensions/management/commands/admin_generator.py index ee2a13f93..d02b58c0d 100644 --- a/django_extensions/management/commands/admin_generator.py +++ b/django_extensions/management/commands/admin_generator.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ The Django Admin Generator is a project which can automatically generate (scaffold) a Django Admin for you. By doing this it will introspect your diff --git a/django_extensions/management/commands/clean_pyc.py b/django_extensions/management/commands/clean_pyc.py index 9565dbe53..5e1fd9a97 100644 --- a/django_extensions/management/commands/clean_pyc.py +++ b/django_extensions/management/commands/clean_pyc.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import fnmatch import os from os.path import join as _j diff --git a/django_extensions/management/commands/clear_cache.py b/django_extensions/management/commands/clear_cache.py index 3da26f82e..17540af28 100644 --- a/django_extensions/management/commands/clear_cache.py +++ b/django_extensions/management/commands/clear_cache.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Author: AxiaCore S.A.S. https://axiacore.com from django.conf import settings from django.core.cache import DEFAULT_CACHE_ALIAS, caches diff --git a/django_extensions/management/commands/compile_pyc.py b/django_extensions/management/commands/compile_pyc.py index 09a76b1d2..dc2d2d69d 100644 --- a/django_extensions/management/commands/compile_pyc.py +++ b/django_extensions/management/commands/compile_pyc.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import fnmatch import os import py_compile diff --git a/django_extensions/management/commands/create_command.py b/django_extensions/management/commands/create_command.py index 15bcd8b6d..23ecb6286 100644 --- a/django_extensions/management/commands/create_command.py +++ b/django_extensions/management/commands/create_command.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import sys import shutil diff --git a/django_extensions/management/commands/create_jobs.py b/django_extensions/management/commands/create_jobs.py index ec6adf7d5..0fba5aaf8 100644 --- a/django_extensions/management/commands/create_jobs.py +++ b/django_extensions/management/commands/create_jobs.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import sys import shutil diff --git a/django_extensions/management/commands/create_template_tags.py b/django_extensions/management/commands/create_template_tags.py index 21ad95c0f..7666a0451 100644 --- a/django_extensions/management/commands/create_template_tags.py +++ b/django_extensions/management/commands/create_template_tags.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import sys from typing import List diff --git a/django_extensions/management/commands/delete_squashed_migrations.py b/django_extensions/management/commands/delete_squashed_migrations.py index ea548c747..c41dcd7c8 100644 --- a/django_extensions/management/commands/delete_squashed_migrations.py +++ b/django_extensions/management/commands/delete_squashed_migrations.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +import difflib import os import inspect import re @@ -7,7 +7,7 @@ from django.db import DEFAULT_DB_ALIAS, connections from django.db.migrations.loader import AmbiguityError, MigrationLoader -REPLACES_REGEX = re.compile(r"\s+replaces\s*=\s*\[[^\]]+\]\s*") +REPLACES_REGEX = re.compile(r"^\s+replaces\s*=\s*\[[^\]]+\]\s*?$", flags=re.MULTILINE) PYC = ".pyc" @@ -146,32 +146,36 @@ def handle(self, **options): if squashed_migration_fn.endswith(PYC): squashed_migration_fn = py_from_pyc(squashed_migration_fn) with open(squashed_migration_fn) as fp: - squashed_migration_lines = list(fp) - - delete_lines = [] - for i, line in enumerate(squashed_migration_lines): - if REPLACES_REGEX.match(line): - delete_lines.append(i) - if i > 0 and squashed_migration_lines[i - 1].strip() == "": - delete_lines.insert(0, i - 1) - break - if not delete_lines: + squashed_migration_content = fp.read() + + cleaned_migration_content = re.sub( + REPLACES_REGEX, "", squashed_migration_content + ) + if cleaned_migration_content == squashed_migration_content: raise CommandError( ( - "Couldn't find 'replaces =' line in file %s. " + "Couldn't find 'replaces =' lines in file %s. " "Please finish cleaning up manually." ) % (squashed_migration_fn,) ) if self.verbosity > 0 or self.interactive: + # Print the differences between the original and new content + diff = difflib.unified_diff( + squashed_migration_content.splitlines(), + cleaned_migration_content.splitlines(), + lineterm="", + fromfile="Original", + tofile="Modified", + ) + self.stdout.write( self.style.MIGRATE_HEADING( - "Will delete line %s%s from file %s" + "The squashed migrations file %s will be modified like this :\n\n%s" % ( - delete_lines[0], - " and " + str(delete_lines[1]) if len(delete_lines) > 1 else "", squashed_migration_fn, + "\n".join(diff), ) ) ) @@ -179,12 +183,9 @@ def handle(self, **options): if not self.confirm(): return - for line_num in sorted(delete_lines, reverse=True): - del squashed_migration_lines[line_num] - - with open(squashed_migration_fn, "w") as fp: - if not self.dry_run: - fp.write("".join(squashed_migration_lines)) + if not self.dry_run: + with open(squashed_migration_fn, "w") as fp: + fp.write(cleaned_migration_content) def confirm(self): if self.interactive: diff --git a/django_extensions/management/commands/describe_form.py b/django_extensions/management/commands/describe_form.py index ed3686653..78f4b24da 100644 --- a/django_extensions/management/commands/describe_form.py +++ b/django_extensions/management/commands/describe_form.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.apps import apps from django.core.management.base import CommandError, LabelCommand from django.utils.encoding import force_str diff --git a/django_extensions/management/commands/drop_test_database.py b/django_extensions/management/commands/drop_test_database.py index 28742f322..106ebf4c7 100644 --- a/django_extensions/management/commands/drop_test_database.py +++ b/django_extensions/management/commands/drop_test_database.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import importlib.util from itertools import count import os diff --git a/django_extensions/management/commands/dumpscript.py b/django_extensions/management/commands/dumpscript.py index eeade42dc..d7d1f7bf2 100644 --- a/django_extensions/management/commands/dumpscript.py +++ b/django_extensions/management/commands/dumpscript.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Title: Dumpscript management command Project: Hardytools (queryset-refactor version) diff --git a/django_extensions/management/commands/export_emails.py b/django_extensions/management/commands/export_emails.py index 2ec75472d..142292f9c 100644 --- a/django_extensions/management/commands/export_emails.py +++ b/django_extensions/management/commands/export_emails.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import sys import csv diff --git a/django_extensions/management/commands/find_template.py b/django_extensions/management/commands/find_template.py index b39d07ae7..f48d3ac57 100644 --- a/django_extensions/management/commands/find_template.py +++ b/django_extensions/management/commands/find_template.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import sys from django.core.management.base import LabelCommand diff --git a/django_extensions/management/commands/generate_password.py b/django_extensions/management/commands/generate_password.py index 68b46908c..073a3a15e 100644 --- a/django_extensions/management/commands/generate_password.py +++ b/django_extensions/management/commands/generate_password.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import argparse import string import secrets diff --git a/django_extensions/management/commands/generate_secret_key.py b/django_extensions/management/commands/generate_secret_key.py index 0ec129118..14e294bb3 100644 --- a/django_extensions/management/commands/generate_secret_key.py +++ b/django_extensions/management/commands/generate_secret_key.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from typing import List from django.core.management.base import BaseCommand diff --git a/django_extensions/management/commands/graph_models.py b/django_extensions/management/commands/graph_models.py index 66610dde4..e0bfc2f12 100644 --- a/django_extensions/management/commands/graph_models.py +++ b/django_extensions/management/commands/graph_models.py @@ -1,8 +1,9 @@ -# -*- coding: utf-8 -*- import sys import json import os import tempfile +import fnmatch +from collections import OrderedDict from django.conf import settings from django.core.management.base import BaseCommand, CommandError @@ -27,26 +28,21 @@ except ImportError: HAS_PYDOT = False +DEFAULT_APP_STYLE_NAME = ".app-style.json" -def retheme(graph_data, app_style={}): - if isinstance(app_style, str): - if os.path.exists(app_style): - try: - with open(app_style, "rt") as f: - app_style = json.load(f) - except Exception as e: - print(f"Invalid app style file {app_style}") - raise Exception(e) - else: - return graph_data + +def retheme(graph_data: dict, app_style_filename: str): + with open(app_style_filename, "rt") as f: + app_style = json.load(f, object_pairs_hook=OrderedDict) for gc in graph_data["graphs"]: for g in gc: if "name" in g: for m in g["models"]: app_name = g["app_name"] - if app_name in app_style: - m["style"] = app_style[app_name] + for pattern, style in app_style.items(): + if fnmatch.fnmatchcase(app_name, pattern): + m["style"] = dict(style) return graph_data @@ -73,7 +69,7 @@ def __init__(self, *args, **kwargs): "action": "store", "help": "Path to style json to configure the style per app", "dest": "app-style", - "default": ".app-style.json", + "default": "", }, "--pygraphviz": { "action": "store_true", @@ -372,7 +368,21 @@ def handle(self, *args, **options): ) template = loader.get_template(template_name) - graph_data = retheme(graph_data, app_style=options["app-style"]) + app_style_filename = options["app-style"] + if app_style_filename and not os.path.exists(app_style_filename): + raise CommandError(f"--app-style file {app_style_filename} not found") + + if not app_style_filename: + # try default + default_app_style_filename = os.path.join( + settings.BASE_DIR, DEFAULT_APP_STYLE_NAME + ) + if os.path.exists(default_app_style_filename): + app_style_filename = default_app_style_filename + + if app_style_filename: + graph_data = retheme(graph_data, app_style_filename=app_style_filename) + dotdata = generate_dot(graph_data, template=template) if output == "pygraphviz": diff --git a/django_extensions/management/commands/list_model_info.py b/django_extensions/management/commands/list_model_info.py index d1a329236..286711020 100644 --- a/django_extensions/management/commands/list_model_info.py +++ b/django_extensions/management/commands/list_model_info.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Author: OmenApps. https://omenapps.com import inspect @@ -86,6 +85,9 @@ def list_model_info(self, options): ) default_methods = [ + "adelete", + "arefresh_from_db", + "asave", "check", "clean", "clean_fields", @@ -94,6 +96,7 @@ def list_model_info(self, options): "from_db", "full_clean", "get_absolute_url", + "get_constraints", "get_deferred_fields", "prepare_database_save", "refresh_from_db", @@ -101,6 +104,7 @@ def list_model_info(self, options): "save_base", "serializable_value", "unique_error_message", + "validate_constraints", "validate_unique", ] diff --git a/django_extensions/management/commands/list_signals.py b/django_extensions/management/commands/list_signals.py index b19f3d3e2..9cadc4f85 100644 --- a/django_extensions/management/commands/list_signals.py +++ b/django_extensions/management/commands/list_signals.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Based on https://gist.github.com/voldmar/1264102 # and https://gist.github.com/runekaagaard/2eecf0a8367959dc634b7866694daf2c diff --git a/django_extensions/management/commands/mail_debug.py b/django_extensions/management/commands/mail_debug.py index 74436f9f9..f12bbd221 100644 --- a/django_extensions/management/commands/mail_debug.py +++ b/django_extensions/management/commands/mail_debug.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import asyncio import sys diff --git a/django_extensions/management/commands/managestate.py b/django_extensions/management/commands/managestate.py index 6755310a3..e7ff244fd 100644 --- a/django_extensions/management/commands/managestate.py +++ b/django_extensions/management/commands/managestate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import json from operator import itemgetter from pathlib import Path diff --git a/django_extensions/management/commands/merge_model_instances.py b/django_extensions/management/commands/merge_model_instances.py index 204f792d9..3860be87e 100644 --- a/django_extensions/management/commands/merge_model_instances.py +++ b/django_extensions/management/commands/merge_model_instances.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.apps import apps from django.contrib.contenttypes.fields import GenericForeignKey from django.core.management import BaseCommand diff --git a/django_extensions/management/commands/notes.py b/django_extensions/management/commands/notes.py index 67d07a686..ed133ffb1 100644 --- a/django_extensions/management/commands/notes.py +++ b/django_extensions/management/commands/notes.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import re diff --git a/django_extensions/management/commands/print_settings.py b/django_extensions/management/commands/print_settings.py index 026a514a6..057d489d1 100644 --- a/django_extensions/management/commands/print_settings.py +++ b/django_extensions/management/commands/print_settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ print_settings ============== diff --git a/django_extensions/management/commands/print_user_for_session.py b/django_extensions/management/commands/print_user_for_session.py index c3760d738..5e36b00cb 100644 --- a/django_extensions/management/commands/print_user_for_session.py +++ b/django_extensions/management/commands/print_user_for_session.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import importlib from django.conf import settings diff --git a/django_extensions/management/commands/raise_test_exception.py b/django_extensions/management/commands/raise_test_exception.py index 9cc3b7599..4f69c2f54 100644 --- a/django_extensions/management/commands/raise_test_exception.py +++ b/django_extensions/management/commands/raise_test_exception.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.core.management.base import BaseCommand from django_extensions.management.utils import signalcommand diff --git a/django_extensions/management/commands/reset_db.py b/django_extensions/management/commands/reset_db.py index 0c5472396..d91cbb073 100644 --- a/django_extensions/management/commands/reset_db.py +++ b/django_extensions/management/commands/reset_db.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ reset_db command diff --git a/django_extensions/management/commands/reset_schema.py b/django_extensions/management/commands/reset_schema.py index 5e1d77c0b..e456b8a50 100644 --- a/django_extensions/management/commands/reset_schema.py +++ b/django_extensions/management/commands/reset_schema.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Recreates the public schema for current database (PostgreSQL only). Useful for Docker environments where you need to reset database diff --git a/django_extensions/management/commands/runjob.py b/django_extensions/management/commands/runjob.py index cfd38608f..2ecd31c4d 100644 --- a/django_extensions/management/commands/runjob.py +++ b/django_extensions/management/commands/runjob.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from django.core.management.base import BaseCommand diff --git a/django_extensions/management/commands/runjobs.py b/django_extensions/management/commands/runjobs.py index 6ed0d2b20..43844886f 100644 --- a/django_extensions/management/commands/runjobs.py +++ b/django_extensions/management/commands/runjobs.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging from django.apps import apps diff --git a/django_extensions/management/commands/runprofileserver.py b/django_extensions/management/commands/runprofileserver.py index 305a96eb8..c843d8e7a 100644 --- a/django_extensions/management/commands/runprofileserver.py +++ b/django_extensions/management/commands/runprofileserver.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ runprofileserver.py diff --git a/django_extensions/management/commands/runscript.py b/django_extensions/management/commands/runscript.py index edf3a4787..5e64e8873 100644 --- a/django_extensions/management/commands/runscript.py +++ b/django_extensions/management/commands/runscript.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import sys import importlib diff --git a/django_extensions/management/commands/runserver_plus.py b/django_extensions/management/commands/runserver_plus.py index beb1f00bf..f8667720a 100644 --- a/django_extensions/management/commands/runserver_plus.py +++ b/django_extensions/management/commands/runserver_plus.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging import os import re diff --git a/django_extensions/management/commands/set_default_site.py b/django_extensions/management/commands/set_default_site.py index 99e3eff40..4629888f8 100644 --- a/django_extensions/management/commands/set_default_site.py +++ b/django_extensions/management/commands/set_default_site.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import socket from django.conf import settings diff --git a/django_extensions/management/commands/set_fake_emails.py b/django_extensions/management/commands/set_fake_emails.py index 172eaa63a..269d13722 100644 --- a/django_extensions/management/commands/set_fake_emails.py +++ b/django_extensions/management/commands/set_fake_emails.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ set_fake_emails.py diff --git a/django_extensions/management/commands/set_fake_passwords.py b/django_extensions/management/commands/set_fake_passwords.py index cf05c7928..b82208994 100644 --- a/django_extensions/management/commands/set_fake_passwords.py +++ b/django_extensions/management/commands/set_fake_passwords.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ set_fake_passwords.py diff --git a/django_extensions/management/commands/shell_plus.py b/django_extensions/management/commands/shell_plus.py index aa5457a8b..d1367e0d1 100644 --- a/django_extensions/management/commands/shell_plus.py +++ b/django_extensions/management/commands/shell_plus.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import inspect import os import sys diff --git a/django_extensions/management/commands/show_permissions.py b/django_extensions/management/commands/show_permissions.py index d1eed7195..2df0182f8 100644 --- a/django_extensions/management/commands/show_permissions.py +++ b/django_extensions/management/commands/show_permissions.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.contrib.contenttypes.models import ContentType from django.core.management.base import BaseCommand, CommandError diff --git a/django_extensions/management/commands/show_template_tags.py b/django_extensions/management/commands/show_template_tags.py index ddd238826..94ccd6394 100644 --- a/django_extensions/management/commands/show_template_tags.py +++ b/django_extensions/management/commands/show_template_tags.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import inspect import os import re diff --git a/django_extensions/management/commands/show_urls.py b/django_extensions/management/commands/show_urls.py index 26e41793e..c61739b83 100644 --- a/django_extensions/management/commands/show_urls.py +++ b/django_extensions/management/commands/show_urls.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import functools import json import re diff --git a/django_extensions/management/commands/sqlcreate.py b/django_extensions/management/commands/sqlcreate.py index fccfbcf47..62f3c4621 100644 --- a/django_extensions/management/commands/sqlcreate.py +++ b/django_extensions/management/commands/sqlcreate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import socket import sys import warnings diff --git a/django_extensions/management/commands/sqldiff.py b/django_extensions/management/commands/sqldiff.py index 0dd30f273..58a40ca8a 100644 --- a/django_extensions/management/commands/sqldiff.py +++ b/django_extensions/management/commands/sqldiff.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ sqldiff.py - Prints the (approximated) difference between models and database diff --git a/django_extensions/management/commands/sqldsn.py b/django_extensions/management/commands/sqldsn.py index dbbab1674..592fded98 100644 --- a/django_extensions/management/commands/sqldsn.py +++ b/django_extensions/management/commands/sqldsn.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ sqldns.py diff --git a/django_extensions/management/commands/sync_s3.py b/django_extensions/management/commands/sync_s3.py index 7e833ba1e..e591302a4 100644 --- a/django_extensions/management/commands/sync_s3.py +++ b/django_extensions/management/commands/sync_s3.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Sync Media to S3 ================ diff --git a/django_extensions/management/commands/syncdata.py b/django_extensions/management/commands/syncdata.py index 8bbdd0cba..57b4bbba8 100644 --- a/django_extensions/management/commands/syncdata.py +++ b/django_extensions/management/commands/syncdata.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ SyncData ======== diff --git a/django_extensions/management/commands/unreferenced_files.py b/django_extensions/management/commands/unreferenced_files.py index 436b0ba54..efe37f1fe 100644 --- a/django_extensions/management/commands/unreferenced_files.py +++ b/django_extensions/management/commands/unreferenced_files.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os from collections import defaultdict diff --git a/django_extensions/management/commands/update_permissions.py b/django_extensions/management/commands/update_permissions.py index 3ffab6e9c..9ea86ba2e 100644 --- a/django_extensions/management/commands/update_permissions.py +++ b/django_extensions/management/commands/update_permissions.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.apps import apps as django_apps from django.contrib.auth.management import create_permissions from django.contrib.auth.management import _get_all_permissions # type: ignore diff --git a/django_extensions/management/commands/validate_templates.py b/django_extensions/management/commands/validate_templates.py index 57e4f65ac..33b6a503c 100644 --- a/django_extensions/management/commands/validate_templates.py +++ b/django_extensions/management/commands/validate_templates.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import fnmatch diff --git a/django_extensions/management/commands/verify_named_urls.py b/django_extensions/management/commands/verify_named_urls.py new file mode 100644 index 000000000..973cc842a --- /dev/null +++ b/django_extensions/management/commands/verify_named_urls.py @@ -0,0 +1,236 @@ +from collections import defaultdict +import fnmatch +import functools +import re +import os + +from django.apps import apps +from django.conf import settings +from django.core.exceptions import ViewDoesNotExist +from django.core.management.base import BaseCommand, CommandError +from django.template.loader import get_template +from django.urls import URLPattern, URLResolver +from django.utils import translation + +from django_extensions.compat import get_template_setting +from django_extensions.management.color import color_style, no_style +from django_extensions.management.utils import signalcommand + + +class RegexURLPattern: + pass + + +class RegexURLResolver: + pass + + +class LocaleRegexURLResolver: + pass + + +class Command(BaseCommand): + args = "" + help = "Verify named URLs in templates" + ignores = set( + [ + "*.swp", + "*~", + ] + ) + + def add_arguments(self, parser): + super().add_arguments(parser) + parser.add_argument( + "--ignore-app", + action="append", + dest="ignore_apps", + default=["admin"], + help="Ignore these apps", + ) + parser.add_argument( + "--urlconf", + "-c", + dest="urlconf", + default="ROOT_URLCONF", + help="Set the settings URL conf variable to use", + ) + + def ignore_filename(self, filename): + filename = os.path.basename(filename) + for ignore_pattern in self.ignores: + if fnmatch.fnmatch(filename, ignore_pattern): + return True + return False + + @signalcommand + def handle(self, *args, **options): + style = no_style() if options["no_color"] else color_style() + + self.names = defaultdict(list) + self.views = {} + + self.collect_templates(options) + self.collect_views(options) + + for name in sorted(self.names): + n = len(self.names[name]) + color = style.MODULE + try: + v = self.views[name] + print( + style.INFO( + f"Name: {name} ({n} occurences, handled in {v[0]}, {v[1]})" + ) + ) + except KeyError: + print(style.URL_NAME(f"Name: {name} ({n} occurences, UNKNOWN VIEW)")) + color = style.URL_NAME + for item in self.names[name]: + print(color(f"* {item[0]}:{item[1]}")) + + def collect_templates(self, options): + template_dirs = set(get_template_setting("DIRS", [])) + + for app in apps.get_app_configs(): + if app.name.split(".")[-1] in options["ignore_apps"]: + continue + app_template_dir = os.path.join(app.path, "templates") + if os.path.isdir(app_template_dir): + template_dirs.add(app_template_dir) + + settings.TEMPLATES[0]["DIRS"] = list(template_dirs) + + self.template_parse_errors = 0 + self.names_re = re.compile(r"\{%\s*url\s*['\"]([\w\-]+)['\"]") + + for template_dir in template_dirs: + for root, dirs, filenames in os.walk(template_dir): + for filename in filenames: + if self.ignore_filename(filename): + continue + filepath = os.path.join(root, filename) + self.process_template(filepath) + + if self.template_parse_errors > 0: + self.stdout.write( + f"{self.template_parse_errors} template parse errors found" + ) + + def collect_views(self, options): + urlconf = options["urlconf"] + + if not hasattr(settings, urlconf): + raise CommandError( + "Settings module {} does not have the attribute {}.".format( + settings, urlconf + ) + ) + + try: + urlconf = __import__(getattr(settings, urlconf), {}, {}, [""]) + except Exception as e: + raise CommandError( + "Error occurred while trying to load %s: %s" + % (getattr(settings, urlconf), str(e)) + ) + + view_functions = self.extract_views_from_urlpatterns(urlconf.urlpatterns) + for func, regex, view in view_functions: + if view is not None: + if isinstance(func, functools.partial): + func = func.func + if hasattr(func, "view_class"): + func = func.view_class + if hasattr(func, "__name__"): + func_name = func.__name__ + elif hasattr(func, "__class__"): + func_name = "%s()" % func.__class__.__name__ + else: + func_name = re.sub(r" at 0x[0-9a-f]+", "", repr(func)) + + self.views[view] = (func_name, regex) + + def process_template(self, filepath): + try: + get_template(filepath) + except Exception: + self.template_parse_errors += 1 + self.stdout.write(f"Error parsing template {filepath}") + + with open(filepath, "r") as file: + lineno = 1 + for line in file: + for match in self.names_re.findall(line): + self.names[match].append((filepath, lineno)) + lineno += 1 + + # copied from show_urls.py + def extract_views_from_urlpatterns(self, urlpatterns, base="", namespace=None): + """ + Return a list of views from a list of urlpatterns. + + Each object in the returned list is a three-tuple: (view_func, regex, name) + """ + views = [] + for p in urlpatterns: + if isinstance(p, (URLPattern, RegexURLPattern)): + try: + if not p.name: + name = p.name + elif namespace: + name = "{0}:{1}".format(namespace, p.name) + else: + name = p.name + pattern = describe_pattern(p) + views.append((p.callback, base + pattern, name)) + except ViewDoesNotExist: + continue + elif isinstance(p, (URLResolver, RegexURLResolver)): + try: + patterns = p.url_patterns + except ImportError: + continue + if namespace and p.namespace: + _namespace = "{0}:{1}".format(namespace, p.namespace) + else: + _namespace = p.namespace or namespace + pattern = describe_pattern(p) + if isinstance(p, LocaleRegexURLResolver): + for language in self.LANGUAGES: + with translation.override(language[0]): + views.extend( + self.extract_views_from_urlpatterns( + patterns, base + pattern, namespace=_namespace + ) + ) + else: + views.extend( + self.extract_views_from_urlpatterns( + patterns, base + pattern, namespace=_namespace + ) + ) + elif hasattr(p, "_get_callback"): + try: + views.append( + (p._get_callback(), base + describe_pattern(p), p.name) + ) + except ViewDoesNotExist: + continue + elif hasattr(p, "url_patterns") or hasattr(p, "_get_url_patterns"): + try: + patterns = p.url_patterns + except ImportError: + continue + views.extend( + self.extract_views_from_urlpatterns( + patterns, base + describe_pattern(p), namespace=namespace + ) + ) + else: + raise TypeError("%s does not appear to be a urlpattern object" % p) + return views + + +def describe_pattern(p): + return str(p.pattern) diff --git a/django_extensions/management/debug_cursor.py b/django_extensions/management/debug_cursor.py index 5236b24b7..d04cd2e82 100644 --- a/django_extensions/management/debug_cursor.py +++ b/django_extensions/management/debug_cursor.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import time import traceback from contextlib import contextmanager diff --git a/django_extensions/management/email_notifications.py b/django_extensions/management/email_notifications.py index 51f40336e..9f070b0a4 100644 --- a/django_extensions/management/email_notifications.py +++ b/django_extensions/management/email_notifications.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import sys import traceback diff --git a/django_extensions/management/jobs.py b/django_extensions/management/jobs.py index ebf7462d0..59668f052 100644 --- a/django_extensions/management/jobs.py +++ b/django_extensions/management/jobs.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import sys import importlib diff --git a/django_extensions/management/modelviz.py b/django_extensions/management/modelviz.py index 93deb08d8..b46a5571d 100644 --- a/django_extensions/management/modelviz.py +++ b/django_extensions/management/modelviz.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ modelviz.py - DOT file generator for Django Models diff --git a/django_extensions/management/mysql.py b/django_extensions/management/mysql.py index 3ce306687..0adec2900 100644 --- a/django_extensions/management/mysql.py +++ b/django_extensions/management/mysql.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import configparser diff --git a/django_extensions/management/notebook_extension.py b/django_extensions/management/notebook_extension.py index 9c38c2a82..477a6b986 100644 --- a/django_extensions/management/notebook_extension.py +++ b/django_extensions/management/notebook_extension.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- def load_ipython_extension(ipython): from django.core.management.color import no_style from django_extensions.management.shells import import_objects diff --git a/django_extensions/management/shells.py b/django_extensions/management/shells.py index bbd6a6f09..4afb9e9da 100644 --- a/django_extensions/management/shells.py +++ b/django_extensions/management/shells.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import ast import traceback import warnings diff --git a/django_extensions/management/signals.py b/django_extensions/management/signals.py index 3a490cf36..378d30aad 100644 --- a/django_extensions/management/signals.py +++ b/django_extensions/management/signals.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.dispatch import Signal run_minutely_jobs = Signal() diff --git a/django_extensions/management/technical_response.py b/django_extensions/management/technical_response.py index 08b776960..fd98cea59 100644 --- a/django_extensions/management/technical_response.py +++ b/django_extensions/management/technical_response.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import threading from django.core.handlers.wsgi import WSGIHandler diff --git a/django_extensions/management/utils.py b/django_extensions/management/utils.py index 0a31460aa..f12bc82f0 100644 --- a/django_extensions/management/utils.py +++ b/django_extensions/management/utils.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging import os import sys diff --git a/django_extensions/mongodb/fields/__init__.py b/django_extensions/mongodb/fields/__init__.py index 6773f831c..77754a38e 100644 --- a/django_extensions/mongodb/fields/__init__.py +++ b/django_extensions/mongodb/fields/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ MongoDB model fields emulating Django Extensions' additional model fields diff --git a/django_extensions/mongodb/fields/json.py b/django_extensions/mongodb/fields/json.py index e4d855429..e7c10ef6b 100644 --- a/django_extensions/mongodb/fields/json.py +++ b/django_extensions/mongodb/fields/json.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ JSONField automatically serializes most Python terms to JSON data. Creates a TEXT field with a default value of "{}". See test_json.py for diff --git a/django_extensions/mongodb/models.py b/django_extensions/mongodb/models.py index 50682fae8..19c67cd4f 100644 --- a/django_extensions/mongodb/models.py +++ b/django_extensions/mongodb/models.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import datetime from django.utils.translation import gettext_lazy as _ diff --git a/django_extensions/settings.py b/django_extensions/settings.py index 8562bb86c..b35c84cad 100644 --- a/django_extensions/settings.py +++ b/django_extensions/settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os from django.conf import settings @@ -43,3 +42,5 @@ ) DEFAULT_PRINT_SQL_TRUNCATE_CHARS = 1000 + +RUNSERVER_PLUS_EXCLUDE_PATTERNS = ["**/__pycache__/*"] diff --git a/django_extensions/templates/django_extensions/graph_models/django2018/label.dot b/django_extensions/templates/django_extensions/graph_models/django2018/label.dot index 6303a806c..b88f50641 100644 --- a/django_extensions/templates/django_extensions/graph_models/django2018/label.dot +++ b/django_extensions/templates/django_extensions/graph_models/django2018/label.dot @@ -12,8 +12,8 @@ style="rounded"{% endif %} {% indentby 2 if use_subgraph %}{% for model in graph.models %} {{ model.app_name }}_{{ model.name }} [label=< - -
+ + diff --git a/django_extensions/templates/django_extensions/graph_models/original/label.dot b/django_extensions/templates/django_extensions/graph_models/original/label.dot index 6db9980df..a46fbbe12 100644 --- a/django_extensions/templates/django_extensions/graph_models/original/label.dot +++ b/django_extensions/templates/django_extensions/graph_models/original/label.dot @@ -12,8 +12,8 @@ style="rounded"{% endif %} {% indentby 2 if use_subgraph %}{% for model in graph.models %} {{ model.app_name }}_{{ model.name }} [label=< -
{{ model.label }}{% if model.abstracts %}
<{{ model.abstracts|join:"," }}>{% endif %}
-
+ + diff --git a/django_extensions/templatetags/debugger_tags.py b/django_extensions/templatetags/debugger_tags.py index 5ff7dd04d..67d7e1436 100644 --- a/django_extensions/templatetags/debugger_tags.py +++ b/django_extensions/templatetags/debugger_tags.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Make debugging Django templates easier. diff --git a/django_extensions/templatetags/highlighting.py b/django_extensions/templatetags/highlighting.py index 9ff0e8372..6153e0069 100644 --- a/django_extensions/templatetags/highlighting.py +++ b/django_extensions/templatetags/highlighting.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Similar to syntax_color.py but this is intended more for being able to copy+paste actual code into your Django templates without needing to diff --git a/django_extensions/templatetags/indent_text.py b/django_extensions/templatetags/indent_text.py index fb3f2804b..a5c4abbce 100644 --- a/django_extensions/templatetags/indent_text.py +++ b/django_extensions/templatetags/indent_text.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django import template register = template.Library() diff --git a/django_extensions/templatetags/syntax_color.py b/django_extensions/templatetags/syntax_color.py index c82fc1888..180150ee0 100644 --- a/django_extensions/templatetags/syntax_color.py +++ b/django_extensions/templatetags/syntax_color.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- r""" Template filter for rendering a string with syntax highlighting. It relies on Pygments to accomplish this. diff --git a/django_extensions/templatetags/widont.py b/django_extensions/templatetags/widont.py index a0ab237b5..fd70d97d6 100644 --- a/django_extensions/templatetags/widont.py +++ b/django_extensions/templatetags/widont.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import re from django.template import Library diff --git a/django_extensions/utils/__init__.py b/django_extensions/utils/__init__.py index a5923e813..689090c6a 100644 --- a/django_extensions/utils/__init__.py +++ b/django_extensions/utils/__init__.py @@ -1,2 +1 @@ -# -*- coding: utf-8 -*- from .internal_ips import InternalIPS # NOQA diff --git a/django_extensions/utils/deprecation.py b/django_extensions/utils/deprecation.py index 9b7b835c2..b627c7659 100644 --- a/django_extensions/utils/deprecation.py +++ b/django_extensions/utils/deprecation.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - class MarkedForDeprecationWarning(DeprecationWarning): pass diff --git a/django_extensions/utils/dia2django.py b/django_extensions/utils/dia2django.py index 06736daec..7b2e53c68 100644 --- a/django_extensions/utils/dia2django.py +++ b/django_extensions/utils/dia2django.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Author Igor Támara igor@tamarapatino.org Use this little program as you wish, if you diff --git a/django_extensions/utils/internal_ips.py b/django_extensions/utils/internal_ips.py index 0a00e854d..afefb09b7 100644 --- a/django_extensions/utils/internal_ips.py +++ b/django_extensions/utils/internal_ips.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from collections.abc import Container import ipaddress import itertools diff --git a/django_extensions/validators.py b/django_extensions/validators.py index 05b12ad28..d5b93a3a5 100644 --- a/django_extensions/validators.py +++ b/django_extensions/validators.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import unicodedata import binascii diff --git a/docs/conf.py b/docs/conf.py index 442b3d683..ca5f3bdf7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # django-extensions documentation build configuration file, created by # sphinx-quickstart on Wed Apr 1 20:39:40 2009. diff --git a/docs/graph_models.rst b/docs/graph_models.rst index a736d4ac2..845364f58 100644 --- a/docs/graph_models.rst +++ b/docs/graph_models.rst @@ -84,6 +84,39 @@ Documentation on how to create dot files can be found here: https://www.graphviz the Django app *django-template-minifier* this automatically removed the newlines before/after template tags even for non-HTML templates which leads to a malformed file. + +App-based Styling +----------------- + +You can style models by app to visually distinguish them in the generated graph. This is useful when working with multiple apps that have interrelated models. + +To use this feature, provide a JSON file specifying styles for each app. You can either: + +- Place a `.app-style.json` file in the project root, or +- Use the `--app-style` command line option to specify a path to the file:: + + $ ./manage.py graph_models -a --app-style path/to/style.json -o styled_output.png + +The JSON file should map app labels to style dictionaries. The app labels can be exact matches or use wildcards (e.g., `django.*`) where the last entry wins. +For example: + +.. code-block:: json + + { + "app1": {"bg": "#341b56"}, + "app2": {"bg": "#1b3956"}, + "django.*": {"bg": "#561b4c"}, + "django.contrib.auth": {"bg": "#c41e3a"} + } + +Currently, the supported style option is `bg` (background color), but the system is designed to be extended in the future with support for additional styling such as font, shape, or border. +*Note: help is wanted to update themes to support more style options* + +This feature allows you to generate a single graph that highlights model groupings by app while still showing relationships across apps. + +*Note: an exception will be raised if the provided json file does not exist* + + Example Usage ------------- @@ -98,6 +131,9 @@ image by using the *graph_models* command:: # Create a PNG image file called my_project_visualized.png with application grouping $ ./manage.py graph_models -a -g -o my_project_visualized.png + # Create a PNG with per-app styling + $ ./manage.py graph_models -a --app-style path/to/style.json -o my_styled_project.png + # Same example but with explicit selection of pygraphviz or pydot $ ./manage.py graph_models --pygraphviz -a -g -o my_project_visualized.png $ ./manage.py graph_models --pydot -a -g -o my_project_visualized.png diff --git a/docs/verify_named_urls.rst b/docs/verify_named_urls.rst new file mode 100644 index 000000000..54ab2e8c0 --- /dev/null +++ b/docs/verify_named_urls.rst @@ -0,0 +1,51 @@ +verify_named_urls +================= + +:synopsis: Verify named URLs in templates + +This command will check whether the templates in your apps have matching named +URLs defined in your views. + +For example this template, when rendered, would result in a 500 on your site: + +:: + + Some template text + + {% url 'this-view-does-not-exist' %} + + Some other template text + +The intention is to help catching typos and leftover references when you rename +or remove a named view - before real users hit the relevant templates. + +Options +------- + +ignore-apps +~~~~~~~~~~~ + +Ignore these apps (comma separaded list) when looking for templates to check. +Default is "admin". + +urlconf +~~~~~~~ + +Set the settings URL conf variable to use + + +Usage Example +------------- + +:: + + ./manage.py verify_named_urls + +Example output, where the first named URL is defined, the second is missing: + +:: + + Name: entry-detail (1 occurences, handled in EntryDetailView, blog/) + * /home/myuser/django/blog/templates/blog/entry-list.html:9 + Name: this-view-is-removed-by-now (1 occurences, UNKNOWN VIEW) + * /home/myuser/django/blog/templates/blog/reference.html:6 diff --git a/manage.py b/manage.py index 1ca113a04..20a710164 100755 --- a/manage.py +++ b/manage.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- import os import sys diff --git a/pyproject.toml b/pyproject.toml index de2748d4c..dd4f0037b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,7 +2,7 @@ build-backend = "setuptools.build_meta" requires = [ "django>=4.2", - "setuptools>=61.2", + "setuptools>=77", ] [project] diff --git a/tests/__init__.py b/tests/__init__.py index d308e8165..d9ef5a71c 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from unittest import mock diff --git a/tests/auth/test_mixins.py b/tests/auth/test_mixins.py index e1d799316..fbc333cf7 100644 --- a/tests/auth/test_mixins.py +++ b/tests/auth/test_mixins.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.test import TestCase, RequestFactory from django.http import HttpResponse from django.views.generic import DetailView diff --git a/tests/collisions/apps.py b/tests/collisions/apps.py index 36ed52dfd..ce53e9dc4 100644 --- a/tests/collisions/apps.py +++ b/tests/collisions/apps.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.apps import AppConfig diff --git a/tests/collisions/models.py b/tests/collisions/models.py index 057b4e496..1c88e23b8 100644 --- a/tests/collisions/models.py +++ b/tests/collisions/models.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.db import models diff --git a/tests/db/fields/test_uniq_field_mixin.py b/tests/db/fields/test_uniq_field_mixin.py index 69a5aa9d2..9593bc0f2 100644 --- a/tests/db/fields/test_uniq_field_mixin.py +++ b/tests/db/fields/test_uniq_field_mixin.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from unittest import mock from django.db import models diff --git a/tests/db/fields/test_uniq_field_mixin_compat.py b/tests/db/fields/test_uniq_field_mixin_compat.py index 7b8e47ad2..e32dd0b9d 100644 --- a/tests/db/fields/test_uniq_field_mixin_compat.py +++ b/tests/db/fields/test_uniq_field_mixin_compat.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from unittest import mock from django.db import models diff --git a/tests/jobs/daily/test_cache_cleanup.py b/tests/jobs/daily/test_cache_cleanup.py index a099eb790..de61bd60f 100644 --- a/tests/jobs/daily/test_cache_cleanup.py +++ b/tests/jobs/daily/test_cache_cleanup.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.core.cache import caches from django.core.management import call_command from django.test import TestCase diff --git a/tests/management/commands/error_raising_command.py b/tests/management/commands/error_raising_command.py index b46e06ab8..0cc77456e 100644 --- a/tests/management/commands/error_raising_command.py +++ b/tests/management/commands/error_raising_command.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django_extensions.management.base import LoggingBaseCommand diff --git a/tests/management/commands/shell_plus_tests/test_collision_resolver.py b/tests/management/commands/shell_plus_tests/test_collision_resolver.py index c237cab5f..785065569 100644 --- a/tests/management/commands/shell_plus_tests/test_collision_resolver.py +++ b/tests/management/commands/shell_plus_tests/test_collision_resolver.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import sys from django.contrib.auth.models import Group, Permission from django.test import override_settings diff --git a/tests/management/commands/shell_plus_tests/test_import_subclasses.py b/tests/management/commands/shell_plus_tests/test_import_subclasses.py index fa3bbd44a..c30895da6 100644 --- a/tests/management/commands/shell_plus_tests/test_import_subclasses.py +++ b/tests/management/commands/shell_plus_tests/test_import_subclasses.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from typing import Optional, Set # noqa from django.conf import settings diff --git a/tests/management/commands/shell_plus_tests/test_shell_plus.py b/tests/management/commands/shell_plus_tests/test_shell_plus.py index 6e2a51a39..c97e068af 100644 --- a/tests/management/commands/shell_plus_tests/test_shell_plus.py +++ b/tests/management/commands/shell_plus_tests/test_shell_plus.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import re import pytest diff --git a/tests/management/commands/shell_plus_tests/test_utils.py b/tests/management/commands/shell_plus_tests/test_utils.py index 68eea7279..3d1110aec 100644 --- a/tests/management/commands/shell_plus_tests/test_utils.py +++ b/tests/management/commands/shell_plus_tests/test_utils.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import sys from io import StringIO from typing import Dict, Set, Type # noqa diff --git a/tests/management/commands/test_admin_generator.py b/tests/management/commands/test_admin_generator.py index 19c9fe0ab..1a9c2bc80 100644 --- a/tests/management/commands/test_admin_generator.py +++ b/tests/management/commands/test_admin_generator.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from io import StringIO from django.core.management import call_command diff --git a/tests/management/commands/test_clear_cache.py b/tests/management/commands/test_clear_cache.py index 46e1b4567..9d0a9860c 100644 --- a/tests/management/commands/test_clear_cache.py +++ b/tests/management/commands/test_clear_cache.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from unittest import mock import os from io import StringIO diff --git a/tests/management/commands/test_create_command.py b/tests/management/commands/test_create_command.py index 540c09e2b..272f3c1c0 100644 --- a/tests/management/commands/test_create_command.py +++ b/tests/management/commands/test_create_command.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import shutil diff --git a/tests/management/commands/test_create_jobs.py b/tests/management/commands/test_create_jobs.py index c1b97e417..913af3998 100644 --- a/tests/management/commands/test_create_jobs.py +++ b/tests/management/commands/test_create_jobs.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import shutil diff --git a/tests/management/commands/test_create_template_tags.py b/tests/management/commands/test_create_template_tags.py index 7218f2d41..078a9491d 100644 --- a/tests/management/commands/test_create_template_tags.py +++ b/tests/management/commands/test_create_template_tags.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import shutil diff --git a/tests/management/commands/test_delete_squashed_migrations.py b/tests/management/commands/test_delete_squashed_migrations.py index c47add571..4895d76d2 100644 --- a/tests/management/commands/test_delete_squashed_migrations.py +++ b/tests/management/commands/test_delete_squashed_migrations.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import pytest diff --git a/tests/management/commands/test_describe_form.py b/tests/management/commands/test_describe_form.py index 6f569e228..5a509f56f 100644 --- a/tests/management/commands/test_describe_form.py +++ b/tests/management/commands/test_describe_form.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from io import StringIO from django.test import TestCase diff --git a/tests/management/commands/test_drop_test_database.py b/tests/management/commands/test_drop_test_database.py index 84cea2549..60da29998 100644 --- a/tests/management/commands/test_drop_test_database.py +++ b/tests/management/commands/test_drop_test_database.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import importlib.util from io import StringIO from unittest.mock import MagicMock, Mock, PropertyMock, call, patch diff --git a/tests/management/commands/test_export_emails.py b/tests/management/commands/test_export_emails.py index ca1a73d1f..e03cc9a16 100644 --- a/tests/management/commands/test_export_emails.py +++ b/tests/management/commands/test_export_emails.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.core.management import call_command from django_extensions.management.commands.export_emails import full_name diff --git a/tests/management/commands/test_generate_password.py b/tests/management/commands/test_generate_password.py index f946b41d7..5bda529d1 100644 --- a/tests/management/commands/test_generate_password.py +++ b/tests/management/commands/test_generate_password.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.core.management import call_command diff --git a/tests/management/commands/test_generate_secret_key.py b/tests/management/commands/test_generate_secret_key.py index 99b41e6f0..10dc3b089 100644 --- a/tests/management/commands/test_generate_secret_key.py +++ b/tests/management/commands/test_generate_secret_key.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from io import StringIO from django.core.management import call_command diff --git a/tests/management/commands/test_graph_models.py b/tests/management/commands/test_graph_models.py index fa9e7578a..0191d1a83 100644 --- a/tests/management/commands/test_graph_models.py +++ b/tests/management/commands/test_graph_models.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import json import os import re diff --git a/tests/management/commands/test_list_signals.py b/tests/management/commands/test_list_signals.py index d97abc973..48b0fedfa 100644 --- a/tests/management/commands/test_list_signals.py +++ b/tests/management/commands/test_list_signals.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import re from io import StringIO diff --git a/tests/management/commands/test_mail_debug.py b/tests/management/commands/test_mail_debug.py index 5bd18ae56..514011894 100644 --- a/tests/management/commands/test_mail_debug.py +++ b/tests/management/commands/test_mail_debug.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.core.management import call_command from unittest import mock diff --git a/tests/management/commands/test_managestate.py b/tests/management/commands/test_managestate.py index 0ae25e97e..2b9a4659b 100644 --- a/tests/management/commands/test_managestate.py +++ b/tests/management/commands/test_managestate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import json from pathlib import Path from tempfile import TemporaryDirectory diff --git a/tests/management/commands/test_notes.py b/tests/management/commands/test_notes.py index 34d6dc620..ae1980b12 100644 --- a/tests/management/commands/test_notes.py +++ b/tests/management/commands/test_notes.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os from django.core.management import call_command @@ -8,8 +7,9 @@ def test_without_args(capsys, settings): call_command("notes") out, err = capsys.readouterr() + print([out]) assert ( - "tests/testapp/file_without_utf8_notes.py:\n * [ 3] TODO this is a test todo\n\n" + "tests/testapp/file_without_utf8_notes.py:\n * [ 1] TODO this is a test todo\n\n" in out ) @@ -19,7 +19,7 @@ def test_with_utf8(capsys, settings): out, err = capsys.readouterr() assert ( - "tests/testapp/file_with_utf8_notes.py:\n * [ 3] TODO Russian text followed: Это техт на кириллице\n\n" + "tests/testapp/file_with_utf8_notes.py:\n * [ 1] TODO Russian text followed: Это техт на кириллице\n\n" in out ) diff --git a/tests/management/commands/test_print_settings.py b/tests/management/commands/test_print_settings.py index 3e97f541b..9724228a3 100644 --- a/tests/management/commands/test_print_settings.py +++ b/tests/management/commands/test_print_settings.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import pytest from django.core.management import CommandError, call_command diff --git a/tests/management/commands/test_print_user_for_session.py b/tests/management/commands/test_print_user_for_session.py index f42a18d15..733980775 100644 --- a/tests/management/commands/test_print_user_for_session.py +++ b/tests/management/commands/test_print_user_for_session.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from importlib import import_module from io import StringIO diff --git a/tests/management/commands/test_raise_test_exception.py b/tests/management/commands/test_raise_test_exception.py index 74f7a8e7a..77bea014d 100644 --- a/tests/management/commands/test_raise_test_exception.py +++ b/tests/management/commands/test_raise_test_exception.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import pytest from django.core.management import call_command diff --git a/tests/management/commands/test_reset_db.py b/tests/management/commands/test_reset_db.py index d36d63c17..845da6551 100644 --- a/tests/management/commands/test_reset_db.py +++ b/tests/management/commands/test_reset_db.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import importlib.util import os from io import StringIO diff --git a/tests/management/commands/test_reset_schema.py b/tests/management/commands/test_reset_schema.py index 237fb5b65..944797029 100644 --- a/tests/management/commands/test_reset_schema.py +++ b/tests/management/commands/test_reset_schema.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from io import StringIO from django.core.management import CommandError, call_command diff --git a/tests/management/commands/test_runjob.py b/tests/management/commands/test_runjob.py index 8eb142f16..0a89271a5 100644 --- a/tests/management/commands/test_runjob.py +++ b/tests/management/commands/test_runjob.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import logging import sys from io import StringIO diff --git a/tests/management/commands/test_runserver_plus.py b/tests/management/commands/test_runserver_plus.py index c82948486..0de0bd1a6 100644 --- a/tests/management/commands/test_runserver_plus.py +++ b/tests/management/commands/test_runserver_plus.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import pytest from django.core.management import call_command diff --git a/tests/management/commands/test_set_default_site.py b/tests/management/commands/test_set_default_site.py index 671526afa..ddc9c2b71 100644 --- a/tests/management/commands/test_set_default_site.py +++ b/tests/management/commands/test_set_default_site.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from io import StringIO from django.conf import settings diff --git a/tests/management/commands/test_set_fake_emails.py b/tests/management/commands/test_set_fake_emails.py index 8bb9c3ab6..93878c0e3 100644 --- a/tests/management/commands/test_set_fake_emails.py +++ b/tests/management/commands/test_set_fake_emails.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from io import StringIO from django.core.management import call_command, CommandError diff --git a/tests/management/commands/test_set_fake_passwords.py b/tests/management/commands/test_set_fake_passwords.py index e72714d62..0bcc2317f 100644 --- a/tests/management/commands/test_set_fake_passwords.py +++ b/tests/management/commands/test_set_fake_passwords.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from io import StringIO import pytest diff --git a/tests/management/commands/test_show_permissions.py b/tests/management/commands/test_show_permissions.py index 31f157784..91b6fc988 100644 --- a/tests/management/commands/test_show_permissions.py +++ b/tests/management/commands/test_show_permissions.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import sys from io import StringIO diff --git a/tests/management/commands/test_show_template_tags.py b/tests/management/commands/test_show_template_tags.py index f13919784..a1c50ab82 100644 --- a/tests/management/commands/test_show_template_tags.py +++ b/tests/management/commands/test_show_template_tags.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from io import StringIO from django.core.management import call_command diff --git a/tests/management/commands/test_show_urls.py b/tests/management/commands/test_show_urls.py index cadcbf669..55eeac130 100644 --- a/tests/management/commands/test_show_urls.py +++ b/tests/management/commands/test_show_urls.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from io import StringIO from django.urls import path diff --git a/tests/management/commands/test_sqlcreate.py b/tests/management/commands/test_sqlcreate.py index d4788d91f..8d96a5911 100644 --- a/tests/management/commands/test_sqlcreate.py +++ b/tests/management/commands/test_sqlcreate.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from io import StringIO from django.core.management import CommandError, call_command diff --git a/tests/management/commands/test_sqldsn.py b/tests/management/commands/test_sqldsn.py index 63079f88b..0ef803cc4 100644 --- a/tests/management/commands/test_sqldsn.py +++ b/tests/management/commands/test_sqldsn.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from io import StringIO from django.core.management import CommandError, call_command diff --git a/tests/management/commands/test_sync_s3.py b/tests/management/commands/test_sync_s3.py index cb0b8a71d..bd852ee4c 100644 --- a/tests/management/commands/test_sync_s3.py +++ b/tests/management/commands/test_sync_s3.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import shutil diff --git a/tests/management/commands/test_syncdata.py b/tests/management/commands/test_syncdata.py index 78cac464d..3554b7b9b 100644 --- a/tests/management/commands/test_syncdata.py +++ b/tests/management/commands/test_syncdata.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import pytest diff --git a/tests/management/commands/test_unreferenced_files.py b/tests/management/commands/test_unreferenced_files.py index 3bdc65d9c..c48b25c78 100644 --- a/tests/management/commands/test_unreferenced_files.py +++ b/tests/management/commands/test_unreferenced_files.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import shutil from io import StringIO diff --git a/tests/management/commands/test_update_permissions.py b/tests/management/commands/test_update_permissions.py index ebc8a6d6d..99db8336c 100644 --- a/tests/management/commands/test_update_permissions.py +++ b/tests/management/commands/test_update_permissions.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import sys from io import StringIO diff --git a/tests/management/commands/test_validate_templates.py b/tests/management/commands/test_validate_templates.py index 449b53ce0..82eb04b99 100644 --- a/tests/management/commands/test_validate_templates.py +++ b/tests/management/commands/test_validate_templates.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import shutil from io import StringIO diff --git a/tests/management/test_email_notifications.py b/tests/management/test_email_notifications.py index 432537e20..db2f197dd 100644 --- a/tests/management/test_email_notifications.py +++ b/tests/management/test_email_notifications.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.core import mail from django.core.management import call_command from django.test import TestCase diff --git a/tests/management/test_modelviz.py b/tests/management/test_modelviz.py index d91192a38..8b276127b 100644 --- a/tests/management/test_modelviz.py +++ b/tests/management/test_modelviz.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.test import SimpleTestCase from django_extensions.management.modelviz import generate_graph_data, ON_DELETE_COLORS diff --git a/tests/pythonrc.py b/tests/pythonrc.py index a4576c5b1..1c1a48a25 100644 --- a/tests/pythonrc.py +++ b/tests/pythonrc.py @@ -1,3 +1,2 @@ -# -*- coding: utf-8 -*- def pythonrc_test_func(): return "pythonrc was loaded" diff --git a/tests/runner.py b/tests/runner.py index ffa42cde2..1b75fa439 100644 --- a/tests/runner.py +++ b/tests/runner.py @@ -1,6 +1,3 @@ -# -*- coding: utf-8 -*- - - class PytestTestRunner: """Runs pytest to discover and run tests.""" diff --git a/tests/templatetags/test_highlighting.py b/tests/templatetags/test_highlighting.py index fe001f03b..aa28903f1 100644 --- a/tests/templatetags/test_highlighting.py +++ b/tests/templatetags/test_highlighting.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.template import Context, Template, TemplateSyntaxError from django.test import TestCase diff --git a/tests/templatetags/test_indent_text.py b/tests/templatetags/test_indent_text.py index 8cfebc0e3..cd606958b 100644 --- a/tests/templatetags/test_indent_text.py +++ b/tests/templatetags/test_indent_text.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.test import TestCase from django.template import Context, Template, TemplateSyntaxError diff --git a/tests/templatetags/test_syntax_color.py b/tests/templatetags/test_syntax_color.py index 31d0981d1..b2f82c3a4 100644 --- a/tests/templatetags/test_syntax_color.py +++ b/tests/templatetags/test_syntax_color.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import html import shutil diff --git a/tests/test_admin_filter.py b/tests/test_admin_filter.py index 7279352d2..06ae238a5 100644 --- a/tests/test_admin_filter.py +++ b/tests/test_admin_filter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from unittest.mock import Mock from django.test import RequestFactory, TestCase diff --git a/tests/test_admin_widgets.py b/tests/test_admin_widgets.py index 3f46044b5..7d965ee68 100644 --- a/tests/test_admin_widgets.py +++ b/tests/test_admin_widgets.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.test import TestCase from django.utils.text import Truncator diff --git a/tests/test_autoslug_fields.py b/tests/test_autoslug_fields.py index 28aeea029..7c83a8608 100644 --- a/tests/test_autoslug_fields.py +++ b/tests/test_autoslug_fields.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import pytest from django.db import migrations, models diff --git a/tests/test_clean_pyc.py b/tests/test_clean_pyc.py index 0791906fb..1f9cfaead 100644 --- a/tests/test_clean_pyc.py +++ b/tests/test_clean_pyc.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import fnmatch import os import shutil diff --git a/tests/test_color.py b/tests/test_color.py index 191baf146..e419a0f05 100644 --- a/tests/test_color.py +++ b/tests/test_color.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.test import SimpleTestCase from django_extensions.management import color from . import force_color_support diff --git a/tests/test_compat.py b/tests/test_compat.py index 022da4e24..d0d5e9a03 100644 --- a/tests/test_compat.py +++ b/tests/test_compat.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.test import TestCase from django.test.utils import override_settings diff --git a/tests/test_compile_pyc.py b/tests/test_compile_pyc.py index be28e18e1..486fdbf25 100644 --- a/tests/test_compile_pyc.py +++ b/tests/test_compile_pyc.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import fnmatch import os diff --git a/tests/test_dumpscript.py b/tests/test_dumpscript.py index d0e1ca799..e68a17825 100644 --- a/tests/test_dumpscript.py +++ b/tests/test_dumpscript.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import ast import shutil import sys diff --git a/tests/test_find_template.py b/tests/test_find_template.py index ba378a377..841e09ef1 100644 --- a/tests/test_find_template.py +++ b/tests/test_find_template.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.core.management import call_command from django.test import TestCase from io import StringIO diff --git a/tests/test_json_field.py b/tests/test_json_field.py index 8bcceb72b..2264aaf7f 100644 --- a/tests/test_json_field.py +++ b/tests/test_json_field.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.test import TestCase from django_extensions.db.fields.json import dumps, loads, JSONField, JSONDict, JSONList from .testapp.models import JSONFieldTestModel diff --git a/tests/test_logging_filters.py b/tests/test_logging_filters.py index 000ada2f4..b91e977d5 100644 --- a/tests/test_logging_filters.py +++ b/tests/test_logging_filters.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import time from django.test import TestCase diff --git a/tests/test_management_command.py b/tests/test_management_command.py index 4ed2975be..ea205ed72 100644 --- a/tests/test_management_command.py +++ b/tests/test_management_command.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os from unittest import mock import logging diff --git a/tests/test_models.py b/tests/test_models.py index 1c6c84841..7e7bebec6 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.test import TestCase from django_extensions.db.models import ActivatorModel diff --git a/tests/test_modificationdatetime_fields.py b/tests/test_modificationdatetime_fields.py index 281670edc..1fe0d8359 100644 --- a/tests/test_modificationdatetime_fields.py +++ b/tests/test_modificationdatetime_fields.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from datetime import datetime from django.test import TestCase diff --git a/tests/test_module_in_project_dir.py b/tests/test_module_in_project_dir.py index 6e5d8bc9b..8fe53a1ec 100644 --- a/tests/test_module_in_project_dir.py +++ b/tests/test_module_in_project_dir.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from tests.testapp.classes_to_include import BaseIncludedClass diff --git a/tests/test_parse_mysql_cnf.py b/tests/test_parse_mysql_cnf.py index aefa25e37..7f8976b2c 100644 --- a/tests/test_parse_mysql_cnf.py +++ b/tests/test_parse_mysql_cnf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import shutil from tempfile import mkdtemp diff --git a/tests/test_randomchar_field.py b/tests/test_randomchar_field.py index 8d66d06e2..62ed9bfe1 100644 --- a/tests/test_randomchar_field.py +++ b/tests/test_randomchar_field.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import string import pytest diff --git a/tests/test_runscript.py b/tests/test_runscript.py index c61aa3398..6e23168f5 100644 --- a/tests/test_runscript.py +++ b/tests/test_runscript.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os import sys import importlib diff --git a/tests/test_runserver.py b/tests/test_runserver.py index 24bb051f7..8250b2a70 100644 --- a/tests/test_runserver.py +++ b/tests/test_runserver.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import pytest from os.path import join diff --git a/tests/test_shortuuid_field.py b/tests/test_shortuuid_field.py index 290fcffb3..70e88c020 100644 --- a/tests/test_shortuuid_field.py +++ b/tests/test_shortuuid_field.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - from django.test import TestCase from .testapp.models import ( diff --git a/tests/test_sqldiff.py b/tests/test_sqldiff.py index 708353604..64ba4c6e8 100644 --- a/tests/test_sqldiff.py +++ b/tests/test_sqldiff.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from unittest import mock import pytest from io import StringIO diff --git a/tests/test_template_rendering.py b/tests/test_template_rendering.py index d5f14ef18..d0963ffff 100644 --- a/tests/test_template_rendering.py +++ b/tests/test_template_rendering.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.test import TestCase from django.template import Context, Template diff --git a/tests/test_templatetags.py b/tests/test_templatetags.py index e696b42e9..64fd2f3da 100644 --- a/tests/test_templatetags.py +++ b/tests/test_templatetags.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.template import engines from django.test import TestCase diff --git a/tests/test_timestamped_model.py b/tests/test_timestamped_model.py index 3e39b6f77..cbba93bfe 100644 --- a/tests/test_timestamped_model.py +++ b/tests/test_timestamped_model.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import time from django.test import TestCase diff --git a/tests/test_validators.py b/tests/test_validators.py index 87885374e..5eadb2b71 100644 --- a/tests/test_validators.py +++ b/tests/test_validators.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from unittest.mock import patch from django.core.exceptions import ValidationError diff --git a/tests/testapp/admin.py b/tests/testapp/admin.py index 117a40b3a..d768fa152 100644 --- a/tests/testapp/admin.py +++ b/tests/testapp/admin.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.contrib import admin from . import models diff --git a/tests/testapp/apps.py b/tests/testapp/apps.py index bbd342be4..15626fb6b 100644 --- a/tests/testapp/apps.py +++ b/tests/testapp/apps.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.apps import AppConfig diff --git a/tests/testapp/classes_to_include.py b/tests/testapp/classes_to_include.py index 5d494fd83..589a7b424 100644 --- a/tests/testapp/classes_to_include.py +++ b/tests/testapp/classes_to_include.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- class BaseIncludedClass: pass diff --git a/tests/testapp/derived_classes_for_testing/__init__.py b/tests/testapp/derived_classes_for_testing/__init__.py index db038e56b..432ef5219 100644 --- a/tests/testapp/derived_classes_for_testing/__init__.py +++ b/tests/testapp/derived_classes_for_testing/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from tests.testapp.classes_to_include import BaseIncludedClass diff --git a/tests/testapp/derived_classes_for_testing/test_module.py b/tests/testapp/derived_classes_for_testing/test_module.py index c4127235f..fa79f5fa3 100644 --- a/tests/testapp/derived_classes_for_testing/test_module.py +++ b/tests/testapp/derived_classes_for_testing/test_module.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from tests.testapp.classes_to_include import IncludedMixin diff --git a/tests/testapp/factories.py b/tests/testapp/factories.py index fff2e31eb..7aa98f20b 100644 --- a/tests/testapp/factories.py +++ b/tests/testapp/factories.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import factory from factory.django import DjangoModelFactory diff --git a/tests/testapp/fields.py b/tests/testapp/fields.py index 4727ce367..021ab8792 100644 --- a/tests/testapp/fields.py +++ b/tests/testapp/fields.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.db import models from django_extensions.db.fields import UniqueFieldMixin diff --git a/tests/testapp/file_with_utf8_notes.py b/tests/testapp/file_with_utf8_notes.py index 4722afe5c..200ab8157 100644 --- a/tests/testapp/file_with_utf8_notes.py +++ b/tests/testapp/file_with_utf8_notes.py @@ -1,3 +1 @@ -# -*- coding: utf-8 -*- - # TODO: Russian text followed: Это техт на кириллице diff --git a/tests/testapp/file_without_utf8_notes.py b/tests/testapp/file_without_utf8_notes.py index 2fb1a381c..4be8892bd 100644 --- a/tests/testapp/file_without_utf8_notes.py +++ b/tests/testapp/file_without_utf8_notes.py @@ -1,3 +1 @@ -# -*- coding: utf-8 -*- - # TODO: this is a test todo diff --git a/tests/testapp/jobs/daily/test_daily_job.py b/tests/testapp/jobs/daily/test_daily_job.py index 6294d3ef1..c185e795d 100644 --- a/tests/testapp/jobs/daily/test_daily_job.py +++ b/tests/testapp/jobs/daily/test_daily_job.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django_extensions.management.jobs import DailyJob from unittest import mock diff --git a/tests/testapp/jobs/hourly/test_hourly_job.py b/tests/testapp/jobs/hourly/test_hourly_job.py index ac3198ce8..4c4f96677 100644 --- a/tests/testapp/jobs/hourly/test_hourly_job.py +++ b/tests/testapp/jobs/hourly/test_hourly_job.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django_extensions.management.jobs import HourlyJob from unittest import mock diff --git a/tests/testapp/jobs/monthly/test_monthly_job.py b/tests/testapp/jobs/monthly/test_monthly_job.py index 6adaec08b..e58f6346c 100644 --- a/tests/testapp/jobs/monthly/test_monthly_job.py +++ b/tests/testapp/jobs/monthly/test_monthly_job.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django_extensions.management.jobs import MonthlyJob from unittest import mock diff --git a/tests/testapp/jobs/sample.py b/tests/testapp/jobs/sample.py index c868ad189..b1ae62cb8 100644 --- a/tests/testapp/jobs/sample.py +++ b/tests/testapp/jobs/sample.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django_extensions.management.jobs import BaseJob diff --git a/tests/testapp/jobs/sample_job.py b/tests/testapp/jobs/sample_job.py index 722522916..b63acb2a9 100644 --- a/tests/testapp/jobs/sample_job.py +++ b/tests/testapp/jobs/sample_job.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django_extensions.management.jobs import BaseJob diff --git a/tests/testapp/jobs/weekly/test_weekly_job.py b/tests/testapp/jobs/weekly/test_weekly_job.py index 6951a5bee..e66a504a6 100644 --- a/tests/testapp/jobs/weekly/test_weekly_job.py +++ b/tests/testapp/jobs/weekly/test_weekly_job.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django_extensions.management.jobs import WeeklyJob from unittest import mock diff --git a/tests/testapp/jobs/yearly/test_yearly_job.py b/tests/testapp/jobs/yearly/test_yearly_job.py index d5dfb86aa..9897924c1 100644 --- a/tests/testapp/jobs/yearly/test_yearly_job.py +++ b/tests/testapp/jobs/yearly/test_yearly_job.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django_extensions.management.jobs import YearlyJob from unittest import mock diff --git a/tests/testapp/management/commands/test_email_notification_command.py b/tests/testapp/management/commands/test_email_notification_command.py index 0b3a92bad..6b1617af9 100644 --- a/tests/testapp/management/commands/test_email_notification_command.py +++ b/tests/testapp/management/commands/test_email_notification_command.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django_extensions.management.email_notifications import EmailNotificationCommand diff --git a/tests/testapp/models.py b/tests/testapp/models.py index ca317405e..278402f51 100644 --- a/tests/testapp/models.py +++ b/tests/testapp/models.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.db import models from django.contrib.auth import get_user_model from django.db.models import UniqueConstraint diff --git a/tests/testapp/scripts/directory_checker_script.py b/tests/testapp/scripts/directory_checker_script.py index 7c91f23d1..0380be894 100644 --- a/tests/testapp/scripts/directory_checker_script.py +++ b/tests/testapp/scripts/directory_checker_script.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os diff --git a/tests/testapp/scripts/error_script.py b/tests/testapp/scripts/error_script.py index 6dfd200bc..033ba598c 100644 --- a/tests/testapp/scripts/error_script.py +++ b/tests/testapp/scripts/error_script.py @@ -1,3 +1,2 @@ -# -*- coding: utf-8 -*- def run(): raise Exception diff --git a/tests/testapp/scripts/invalid_import_script.py b/tests/testapp/scripts/invalid_import_script.py index 8800598ea..c76c09b35 100644 --- a/tests/testapp/scripts/invalid_import_script.py +++ b/tests/testapp/scripts/invalid_import_script.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import invalidpackage # NOQA diff --git a/tests/testapp/scripts/sample_script.py b/tests/testapp/scripts/sample_script.py index c80e928e3..d04d42367 100644 --- a/tests/testapp/scripts/sample_script.py +++ b/tests/testapp/scripts/sample_script.py @@ -1,3 +1,2 @@ -# -*- coding: utf-8 -*- def run(): pass diff --git a/tests/testapp/settings.py b/tests/testapp/settings.py index 57e0eef08..c03c56140 100644 --- a/tests/testapp/settings.py +++ b/tests/testapp/settings.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os SECRET_KEY = "dummy" diff --git a/tests/testapp/templatetags/dummy_tags.py b/tests/testapp/templatetags/dummy_tags.py index cfe5b670a..a94b2a213 100644 --- a/tests/testapp/templatetags/dummy_tags.py +++ b/tests/testapp/templatetags/dummy_tags.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django import template register = template.Library() diff --git a/tests/testapp/urls.py b/tests/testapp/urls.py index 3dcca6a26..f17ae7d02 100644 --- a/tests/testapp/urls.py +++ b/tests/testapp/urls.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ URL Configuration diff --git a/tests/testapp_with_appconfig/admin.py b/tests/testapp_with_appconfig/admin.py index f05f6941a..4185d360e 100644 --- a/tests/testapp_with_appconfig/admin.py +++ b/tests/testapp_with_appconfig/admin.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # from django.contrib import admin # Register your models here. diff --git a/tests/testapp_with_appconfig/apps.py b/tests/testapp_with_appconfig/apps.py index d0493294c..d4fe181fb 100644 --- a/tests/testapp_with_appconfig/apps.py +++ b/tests/testapp_with_appconfig/apps.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django.apps import AppConfig diff --git a/tests/testapp_with_appconfig/models.py b/tests/testapp_with_appconfig/models.py index 00f43d369..0b4331b36 100644 --- a/tests/testapp_with_appconfig/models.py +++ b/tests/testapp_with_appconfig/models.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # from django.db import models # Create your models here. diff --git a/tests/testapp_with_appconfig/templatetags/dummy_tags_appconfig.py b/tests/testapp_with_appconfig/templatetags/dummy_tags_appconfig.py index 29732e5eb..206e620c4 100644 --- a/tests/testapp_with_appconfig/templatetags/dummy_tags_appconfig.py +++ b/tests/testapp_with_appconfig/templatetags/dummy_tags_appconfig.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- from django import template register = template.Library() diff --git a/tests/testapp_with_appconfig/tests.py b/tests/testapp_with_appconfig/tests.py index 5da68aead..a79ca8be5 100644 --- a/tests/testapp_with_appconfig/tests.py +++ b/tests/testapp_with_appconfig/tests.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # from django.test import TestCase # Create your tests here. diff --git a/tests/testapp_with_appconfig/views.py b/tests/testapp_with_appconfig/views.py index 4d80df8e5..fd0e04495 100644 --- a/tests/testapp_with_appconfig/views.py +++ b/tests/testapp_with_appconfig/views.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # from django.shortcuts import render # Create your views here. diff --git a/tests/testapp_with_no_models_file/scripts/other_directory_checker_script.py b/tests/testapp_with_no_models_file/scripts/other_directory_checker_script.py index 5c13ecdf0..b07b297ff 100644 --- a/tests/testapp_with_no_models_file/scripts/other_directory_checker_script.py +++ b/tests/testapp_with_no_models_file/scripts/other_directory_checker_script.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- import os diff --git a/tests/testapp_with_no_models_file/teslacar.py b/tests/testapp_with_no_models_file/teslacar.py index 5662ac0f6..4484fed9f 100644 --- a/tests/testapp_with_no_models_file/teslacar.py +++ b/tests/testapp_with_no_models_file/teslacar.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # An app without a models.py file for issue #936 from django.db import models diff --git a/tox.ini b/tox.ini index 90840c002..bd177ff9e 100644 --- a/tox.ini +++ b/tox.ini @@ -7,7 +7,6 @@ envlist = ruff precommit - safety mypy {py39,py312,pypy}-dj42 {py311,py312,py313,pypy}-dj51 @@ -58,14 +57,6 @@ deps = pre-commit commands = pre-commit run -a -[testenv:safety] -deps = - pip >= 21.1 - safety -# https://github.com/pyupio/safety/issues/539 -# Ignore 70612 / CVE-2019-8341 -commands = safety --disable-optional-telemetry check --full-report --ignore 70612 - [testenv:mypy] allowlist_externals= echo
{{ model.label }}{% if model.abstracts %}
<{{ model.abstracts|join:"," }}>{% endif %}