From d718d99017b83987fe994fab968d6c3039f352b2 Mon Sep 17 00:00:00 2001 From: manav014 Date: Tue, 22 Jun 2021 09:14:27 +0200 Subject: [PATCH] Refs #29898 -- Moved django.db.migrations.operations.utils to django.db.migrations.utils. --- django/db/migrations/operations/fields.py | 4 +- django/db/migrations/operations/models.py | 5 +- django/db/migrations/operations/utils.py | 74 ----------------------- django/db/migrations/utils.py | 72 ++++++++++++++++++++++ 4 files changed, 78 insertions(+), 77 deletions(-) delete mode 100644 django/db/migrations/operations/utils.py diff --git a/django/db/migrations/operations/fields.py b/django/db/migrations/operations/fields.py index 728105ea05..b303f70465 100644 --- a/django/db/migrations/operations/fields.py +++ b/django/db/migrations/operations/fields.py @@ -1,9 +1,11 @@ from django.core.exceptions import FieldDoesNotExist +from django.db.migrations.utils import ( + field_is_referenced, field_references, get_references, +) from django.db.models import NOT_PROVIDED from django.utils.functional import cached_property from .base import Operation -from .utils import field_is_referenced, field_references, get_references class FieldOperation(Operation): diff --git a/django/db/migrations/operations/models.py b/django/db/migrations/operations/models.py index a39731e412..10f2686dc6 100644 --- a/django/db/migrations/operations/models.py +++ b/django/db/migrations/operations/models.py @@ -1,14 +1,15 @@ from django.db import models from django.db.migrations.operations.base import Operation from django.db.migrations.state import ModelState -from django.db.migrations.utils import resolve_relation +from django.db.migrations.utils import ( + field_references, get_references, resolve_relation, +) from django.db.models.options import normalize_together from django.utils.functional import cached_property from .fields import ( AddField, AlterField, FieldOperation, RemoveField, RenameField, ) -from .utils import field_references, get_references def _check_for_duplicates(arg_name, objs): diff --git a/django/db/migrations/operations/utils.py b/django/db/migrations/operations/utils.py deleted file mode 100644 index 0ea55bd3f7..0000000000 --- a/django/db/migrations/operations/utils.py +++ /dev/null @@ -1,74 +0,0 @@ -from collections import namedtuple - -from django.db.migrations.utils import resolve_relation - -FieldReference = namedtuple('FieldReference', 'to through') - - -def field_references( - model_tuple, - field, - reference_model_tuple, - reference_field_name=None, - reference_field=None, -): - """ - Return either False or a FieldReference if `field` references provided - context. - - False positives can be returned if `reference_field_name` is provided - without `reference_field` because of the introspection limitation it - incurs. This should not be an issue when this function is used to determine - whether or not an optimization can take place. - """ - remote_field = field.remote_field - if not remote_field: - return False - references_to = None - references_through = None - if resolve_relation(remote_field.model, *model_tuple) == reference_model_tuple: - to_fields = getattr(field, 'to_fields', None) - if ( - reference_field_name is None or - # Unspecified to_field(s). - to_fields is None or - # Reference to primary key. - (None in to_fields and (reference_field is None or reference_field.primary_key)) or - # Reference to field. - reference_field_name in to_fields - ): - references_to = (remote_field, to_fields) - through = getattr(remote_field, 'through', None) - if through and resolve_relation(through, *model_tuple) == reference_model_tuple: - through_fields = remote_field.through_fields - if ( - reference_field_name is None or - # Unspecified through_fields. - through_fields is None or - # Reference to field. - reference_field_name in through_fields - ): - references_through = (remote_field, through_fields) - if not (references_to or references_through): - return False - return FieldReference(references_to, references_through) - - -def get_references(state, model_tuple, field_tuple=()): - """ - Generator of (model_state, name, field, reference) referencing - provided context. - - If field_tuple is provided only references to this particular field of - model_tuple will be generated. - """ - for state_model_tuple, model_state in state.models.items(): - for name, field in model_state.fields.items(): - reference = field_references(state_model_tuple, field, model_tuple, *field_tuple) - if reference: - yield model_state, name, field, reference - - -def field_is_referenced(state, model_tuple, field_tuple): - """Return whether `field_tuple` is referenced by any state models.""" - return next(get_references(state, model_tuple, field_tuple), None) is not None diff --git a/django/db/migrations/utils.py b/django/db/migrations/utils.py index 7ce2c5bc82..97bd96a90a 100644 --- a/django/db/migrations/utils.py +++ b/django/db/migrations/utils.py @@ -1,8 +1,11 @@ import datetime import re +from collections import namedtuple from django.db.models.fields.related import RECURSIVE_RELATIONSHIP_CONSTANT +FieldReference = namedtuple('FieldReference', 'to through') + COMPILED_REGEX_TYPE = type(re.compile('')) @@ -44,3 +47,72 @@ def resolve_relation(model, app_label=None, model_name=None): ) return app_label, model.lower() return model._meta.app_label, model._meta.model_name + + +def field_references( + model_tuple, + field, + reference_model_tuple, + reference_field_name=None, + reference_field=None, +): + """ + Return either False or a FieldReference if `field` references provided + context. + + False positives can be returned if `reference_field_name` is provided + without `reference_field` because of the introspection limitation it + incurs. This should not be an issue when this function is used to determine + whether or not an optimization can take place. + """ + remote_field = field.remote_field + if not remote_field: + return False + references_to = None + references_through = None + if resolve_relation(remote_field.model, *model_tuple) == reference_model_tuple: + to_fields = getattr(field, 'to_fields', None) + if ( + reference_field_name is None or + # Unspecified to_field(s). + to_fields is None or + # Reference to primary key. + (None in to_fields and (reference_field is None or reference_field.primary_key)) or + # Reference to field. + reference_field_name in to_fields + ): + references_to = (remote_field, to_fields) + through = getattr(remote_field, 'through', None) + if through and resolve_relation(through, *model_tuple) == reference_model_tuple: + through_fields = remote_field.through_fields + if ( + reference_field_name is None or + # Unspecified through_fields. + through_fields is None or + # Reference to field. + reference_field_name in through_fields + ): + references_through = (remote_field, through_fields) + if not (references_to or references_through): + return False + return FieldReference(references_to, references_through) + + +def get_references(state, model_tuple, field_tuple=()): + """ + Generator of (model_state, name, field, reference) referencing + provided context. + + If field_tuple is provided only references to this particular field of + model_tuple will be generated. + """ + for state_model_tuple, model_state in state.models.items(): + for name, field in model_state.fields.items(): + reference = field_references(state_model_tuple, field, model_tuple, *field_tuple) + if reference: + yield model_state, name, field, reference + + +def field_is_referenced(state, model_tuple, field_tuple): + """Return whether `field_tuple` is referenced by any state models.""" + return next(get_references(state, model_tuple, field_tuple), None) is not None