From 2dc50b61089754bb7e1cd3cf8b31da88d3f824d2 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 13 Apr 2023 14:37:56 -0400 Subject: [PATCH] Clean up base modules --- netbox/ipam/api/views.py | 4 ++-- netbox/netbox/constants.py | 11 +++++++++++ netbox/utilities/api.py | 7 +++++++ netbox/utilities/constants.py | 15 --------------- netbox/utilities/exceptions.py | 1 + netbox/utilities/fields.py | 12 +++++++----- netbox/utilities/files.py | 4 ++++ netbox/utilities/filters.py | 16 ++++++++++++++++ netbox/utilities/graphql_optimizer.py | 9 ++++++--- netbox/utilities/htmx.py | 5 +++++ netbox/utilities/markdown.py | 4 ++++ netbox/utilities/migration.py | 4 ++++ netbox/utilities/mptt.py | 5 +++++ netbox/utilities/ordering.py | 5 +++++ netbox/utilities/paginator.py | 6 ++++++ netbox/utilities/query_functions.py | 7 ++++++- netbox/utilities/querysets.py | 5 +++++ netbox/utilities/tables.py | 5 +++++ netbox/utilities/urls.py | 4 ++++ netbox/utilities/validators.py | 16 +++++++++++++++- 20 files changed, 118 insertions(+), 27 deletions(-) diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py index 5263b049a..f432e0e6b 100644 --- a/netbox/ipam/api/views.py +++ b/netbox/ipam/api/views.py @@ -2,7 +2,7 @@ from django.core.exceptions import ObjectDoesNotExist, PermissionDenied from django.db import transaction from django.shortcuts import get_object_or_404 from django_pglocks import advisory_lock -from drf_spectacular.utils import extend_schema, extend_schema_view +from drf_spectacular.utils import extend_schema from rest_framework import status from rest_framework.response import Response from rest_framework.routers import APIRootView @@ -15,7 +15,7 @@ from ipam.models import * from netbox.api.viewsets import NetBoxModelViewSet from netbox.api.viewsets.mixins import ObjectValidationMixin from netbox.config import get_config -from utilities.constants import ADVISORY_LOCK_KEYS +from netbox.constants import ADVISORY_LOCK_KEYS from utilities.utils import count_related from . import serializers from ipam.models import L2VPN, L2VPNTermination diff --git a/netbox/netbox/constants.py b/netbox/netbox/constants.py index 0889f6a5c..d69edc69c 100644 --- a/netbox/netbox/constants.py +++ b/netbox/netbox/constants.py @@ -5,3 +5,14 @@ NESTED_SERIALIZER_PREFIX = 'Nested' RQ_QUEUE_DEFAULT = 'default' RQ_QUEUE_HIGH = 'high' RQ_QUEUE_LOW = 'low' + +# Keys for PostgreSQL advisory locks. These are arbitrary bigints used by the advisory_lock +# context manager. When a lock is acquired, one of these keys will be used to identify said lock. +# When adding a new key, pick something arbitrary and unique so that it is easily searchable in +# query logs. +ADVISORY_LOCK_KEYS = { + 'available-prefixes': 100100, + 'available-ips': 100200, + 'available-vlans': 100300, + 'available-asns': 100400, +} diff --git a/netbox/utilities/api.py b/netbox/utilities/api.py index e3fc3c8d4..81e5c637c 100644 --- a/netbox/utilities/api.py +++ b/netbox/utilities/api.py @@ -10,6 +10,13 @@ from rest_framework.utils import formatting from netbox.api.exceptions import GraphQLTypeNotFound, SerializerNotFound from .utils import dynamic_import +__all__ = ( + 'get_graphql_type_for_model', + 'get_serializer_for_model', + 'get_view_name', + 'is_api_request', +) + def get_serializer_for_model(model, prefix=''): """ diff --git a/netbox/utilities/constants.py b/netbox/utilities/constants.py index 096b60a70..366d8f796 100644 --- a/netbox/utilities/constants.py +++ b/netbox/utilities/constants.py @@ -31,21 +31,6 @@ FILTER_TREENODE_NEGATION_LOOKUP_MAP = dict( n='in' ) - -# Keys for PostgreSQL advisory locks. These are arbitrary bigints used by -# the advisory_lock contextmanager. When a lock is acquired, -# one of these keys will be used to identify said lock. -# -# When adding a new key, pick something arbitrary and unique so -# that it is easily searchable in query logs. - -ADVISORY_LOCK_KEYS = { - 'available-prefixes': 100100, - 'available-ips': 100200, - 'available-vlans': 100300, - 'available-asns': 100400, -} - # # HTTP Request META safe copy # diff --git a/netbox/utilities/exceptions.py b/netbox/utilities/exceptions.py index d7418d0cb..512bb4b60 100644 --- a/netbox/utilities/exceptions.py +++ b/netbox/utilities/exceptions.py @@ -3,6 +3,7 @@ from rest_framework.exceptions import APIException __all__ = ( 'AbortRequest', + 'AbortScript', 'AbortTransaction', 'PermissionsViolation', 'RQWorkerNotRunningException', diff --git a/netbox/utilities/fields.py b/netbox/utilities/fields.py index b2bc4d2cd..d09cee025 100644 --- a/netbox/utilities/fields.py +++ b/netbox/utilities/fields.py @@ -1,21 +1,23 @@ from collections import defaultdict from django.contrib.contenttypes.fields import GenericForeignKey -from django.core.validators import RegexValidator from django.db import models from utilities.ordering import naturalize from .forms import ColorSelect +from .validators import ColorValidator -ColorValidator = RegexValidator( - regex='^[0-9a-f]{6}$', - message='Enter a valid hexadecimal RGB color code.', - code='invalid' +__all__ = ( + 'ColorField', + 'NaturalOrderingField', + 'NullableCharField', + 'RestrictedGenericForeignKey', ) # Deprecated: Retained only to ensure successful migration from early releases # Use models.CharField(null=True) instead +# TODO: Remove in v4.0 class NullableCharField(models.CharField): description = "Stores empty values as NULL rather than ''" diff --git a/netbox/utilities/files.py b/netbox/utilities/files.py index 68afe2962..09ed2c90b 100644 --- a/netbox/utilities/files.py +++ b/netbox/utilities/files.py @@ -1,5 +1,9 @@ import hashlib +__all__ = ( + 'sha256_hash', +) + def sha256_hash(filepath): """ diff --git a/netbox/utilities/filters.py b/netbox/utilities/filters.py index cfe21063b..1bf17beae 100644 --- a/netbox/utilities/filters.py +++ b/netbox/utilities/filters.py @@ -6,6 +6,22 @@ from django_filters.constants import EMPTY_VALUES from drf_spectacular.utils import extend_schema_field from drf_spectacular.types import OpenApiTypes +__all__ = ( + 'ContentTypeFilter', + 'MACAddressFilter', + 'MultiValueCharFilter', + 'MultiValueDateFilter', + 'MultiValueDateTimeFilter', + 'MultiValueDecimalFilter', + 'MultiValueMACAddressFilter', + 'MultiValueNumberFilter', + 'MultiValueTimeFilter', + 'MultiValueWWNFilter', + 'NullableCharFieldFilter', + 'NumericArrayFilter', + 'TreeNodeMultipleChoiceFilter', +) + def multivalue_field_factory(field_class): """ diff --git a/netbox/utilities/graphql_optimizer.py b/netbox/utilities/graphql_optimizer.py index e50a5a44b..9af96a83c 100644 --- a/netbox/utilities/graphql_optimizer.py +++ b/netbox/utilities/graphql_optimizer.py @@ -1,20 +1,23 @@ import functools -import graphql from django.core.exceptions import FieldDoesNotExist -from django.db.models import ForeignKey, Prefetch +from django.db.models import ForeignKey from django.db.models.constants import LOOKUP_SEP from django.db.models.fields.reverse_related import ManyToOneRel from graphene import InputObjectType from graphene.types.generic import GenericScalar from graphene.types.resolver import default_resolver from graphene_django import DjangoObjectType -from graphql import FieldNode, GraphQLObjectType, GraphQLResolveInfo, GraphQLSchema +from graphql import GraphQLResolveInfo, GraphQLSchema from graphql.execution.execute import get_field_def from graphql.language.ast import FragmentSpreadNode, InlineFragmentNode, VariableNode from graphql.pyutils import Path from graphql.type.definition import GraphQLInterfaceType, GraphQLUnionType +__all__ = ( + 'gql_query_optimizer', +) + def gql_query_optimizer(queryset, info, **options): return QueryOptimizer(info).optimize(queryset) diff --git a/netbox/utilities/htmx.py b/netbox/utilities/htmx.py index 347453e94..d12478b67 100644 --- a/netbox/utilities/htmx.py +++ b/netbox/utilities/htmx.py @@ -1,5 +1,10 @@ from urllib.parse import urlparse +__all__ = ( + 'is_embedded', + 'is_htmx', +) + def is_htmx(request): """ diff --git a/netbox/utilities/markdown.py b/netbox/utilities/markdown.py index 00b6330f1..655539acb 100644 --- a/netbox/utilities/markdown.py +++ b/netbox/utilities/markdown.py @@ -1,6 +1,10 @@ import markdown from markdown.inlinepatterns import SimpleTagPattern +__all__ = ( + 'StrikethroughExtension', +) + STRIKE_RE = r'(~{2})(.+?)(~{2})' diff --git a/netbox/utilities/migration.py b/netbox/utilities/migration.py index 2c261b0d3..d85e9dd60 100644 --- a/netbox/utilities/migration.py +++ b/netbox/utilities/migration.py @@ -3,6 +3,10 @@ from timezone_field import TimeZoneField from netbox.config import ConfigItem +__all__ = ( + 'custom_deconstruct', +) + SKIP_FIELDS = ( TimeZoneField, diff --git a/netbox/utilities/mptt.py b/netbox/utilities/mptt.py index 1bae2053d..7ded5b72b 100644 --- a/netbox/utilities/mptt.py +++ b/netbox/utilities/mptt.py @@ -4,6 +4,11 @@ from mptt.querysets import TreeQuerySet as TreeQuerySet_ from django.db.models import Manager from .querysets import RestrictedQuerySet +__all__ = ( + 'TreeManager', + 'TreeQuerySet', +) + class TreeQuerySet(TreeQuerySet_, RestrictedQuerySet): """ diff --git a/netbox/utilities/ordering.py b/netbox/utilities/ordering.py index c5287b1e1..f153426a7 100644 --- a/netbox/utilities/ordering.py +++ b/netbox/utilities/ordering.py @@ -1,5 +1,10 @@ import re +__all__ = ( + 'naturalize', + 'naturalize_interface', +) + INTERFACE_NAME_REGEX = r'(^(?P[^\d\.:]+)?)' \ r'((?P\d+)/)?' \ r'((?P\d+)/)?' \ diff --git a/netbox/utilities/paginator.py b/netbox/utilities/paginator.py index db6326a9c..ebf7a6257 100644 --- a/netbox/utilities/paginator.py +++ b/netbox/utilities/paginator.py @@ -2,6 +2,12 @@ from django.core.paginator import Paginator, Page from netbox.config import get_config +__all__ = ( + 'EnhancedPage', + 'EnhancedPaginator', + 'get_paginate_count', +) + class EnhancedPaginator(Paginator): default_page_lengths = ( diff --git a/netbox/utilities/query_functions.py b/netbox/utilities/query_functions.py index 8ad7ceead..da4721051 100644 --- a/netbox/utilities/query_functions.py +++ b/netbox/utilities/query_functions.py @@ -1,5 +1,10 @@ from django.contrib.postgres.aggregates import JSONBAgg -from django.db.models import F, Func +from django.db.models import Func + +__all__ = ( + 'CollateAsChar', + 'EmptyGroupByJSONBAgg', +) class CollateAsChar(Func): diff --git a/netbox/utilities/querysets.py b/netbox/utilities/querysets.py index 0e5f1cd5c..ba4b28418 100644 --- a/netbox/utilities/querysets.py +++ b/netbox/utilities/querysets.py @@ -3,6 +3,11 @@ from django.db.models import Prefetch, QuerySet from users.constants import CONSTRAINT_TOKEN_USER from utilities.permissions import permission_is_exempt, qs_filter_from_constraints +__all__ = ( + 'RestrictedPrefetch', + 'RestrictedQuerySet', +) + class RestrictedPrefetch(Prefetch): """ diff --git a/netbox/utilities/tables.py b/netbox/utilities/tables.py index c8420e084..bf6aa15a9 100644 --- a/netbox/utilities/tables.py +++ b/netbox/utilities/tables.py @@ -1,3 +1,8 @@ +__all__ = ( + 'linkify_phone', +) + + def linkify_phone(value): """ Render a telephone number as a hyperlink. diff --git a/netbox/utilities/urls.py b/netbox/utilities/urls.py index f344b9b61..a1132d81c 100644 --- a/netbox/utilities/urls.py +++ b/netbox/utilities/urls.py @@ -4,6 +4,10 @@ from django.views.generic import View from netbox.registry import registry +__all__ = ( + 'get_model_urls', +) + def get_model_urls(app_label, model_name): """ diff --git a/netbox/utilities/validators.py b/netbox/utilities/validators.py index 9c3413893..eaea1c34b 100644 --- a/netbox/utilities/validators.py +++ b/netbox/utilities/validators.py @@ -1,10 +1,24 @@ import re from django.core.exceptions import ValidationError -from django.core.validators import _lazy_re_compile, BaseValidator, URLValidator +from django.core.validators import BaseValidator, RegexValidator, URLValidator, _lazy_re_compile from netbox.config import get_config +__all__ = ( + 'ColorValidator', + 'EnhancedURLValidator', + 'ExclusionValidator', + 'validate_regex', +) + + +ColorValidator = RegexValidator( + regex='^[0-9a-f]{6}$', + message='Enter a valid hexadecimal RGB color code.', + code='invalid' +) + class EnhancedURLValidator(URLValidator): """