Skip to content

Commit

Permalink
fix(types): Fix fields type (#739)
Browse files Browse the repository at this point in the history
Most likely, this won't cause any troubles for standard use-cases. But, if you used `get_options_for_model()` and `.fields` from this instance, you need to rename it to `.all_fields`.

BREAKING CHANGE: Rename `fields` (dict with set of TranslationField) to `all_fields`, on the TranslationOptions instance.
  • Loading branch information
last-partizan authored May 26, 2024
1 parent 47f8083 commit b97c22c
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 26 deletions.
20 changes: 10 additions & 10 deletions modeltranslation/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def formfield_for_dbfield(
def patch_translation_field(
self, db_field: Field, field: forms.Field, request: HttpRequest, **kwargs: Any
) -> None:
if db_field.name in self.trans_opts.fields:
if db_field.name in self.trans_opts.all_fields:
if field.required:
field.required = False
field.blank = True
Expand Down Expand Up @@ -140,8 +140,8 @@ def _exclude_original_fields(self, exclude: _ListOrTuple[str] | None = None) ->
exclude = tuple()
if exclude:
exclude_new = tuple(exclude)
return exclude_new + tuple(self.trans_opts.fields.keys())
return tuple(self.trans_opts.fields.keys())
return exclude_new + tuple(self.trans_opts.all_fields.keys())
return tuple(self.trans_opts.all_fields.keys())

def replace_orig_field(self, option: Iterable[str | Sequence[str]]) -> _ListOrTuple[str]:
"""
Expand Down Expand Up @@ -171,11 +171,11 @@ def replace_orig_field(self, option: Iterable[str | Sequence[str]]) -> _ListOrTu
if option:
option_new = list(option)
for opt in option:
if opt in self.trans_opts.fields:
if opt in self.trans_opts.all_fields:
index = option_new.index(opt)
option_new[index : index + 1] = get_translation_fields(opt) # type: ignore[arg-type]
elif isinstance(opt, (tuple, list)) and (
[o for o in opt if o in self.trans_opts.fields]
[o for o in opt if o in self.trans_opts.all_fields]
):
index = option_new.index(opt)
option_new[index : index + 1] = self.replace_orig_field(opt)
Expand All @@ -198,15 +198,15 @@ def localize(sources: Sequence[str], lang: str) -> tuple[str, ...]:
"Append lang suffix (if applicable) to field list"

def append_lang(source: str) -> str:
if source in self.trans_opts.fields:
if source in self.trans_opts.all_fields:
return build_localized_fieldname(source, lang)
return source

return tuple(map(append_lang, sources))

prepopulated_fields: dict[str, Sequence[str]] = {}
for dest, sources in self.prepopulated_fields.items():
if dest in self.trans_opts.fields:
if dest in self.trans_opts.all_fields:
for lang in mt_settings.AVAILABLE_LANGUAGES:
key = build_localized_fieldname(dest, lang)
prepopulated_fields[key] = localize(sources, lang)
Expand Down Expand Up @@ -273,7 +273,7 @@ def get_translation_field_excludes(
if exclude_languages:
excl_languages = exclude_languages
exclude = []
for orig_fieldname, translation_fields in self.trans_opts.fields.items():
for orig_fieldname, translation_fields in self.trans_opts.all_fields.items():
for tfield in translation_fields:
if tfield.language in excl_languages and tfield not in exclude:
exclude.append(tfield)
Expand Down Expand Up @@ -301,7 +301,7 @@ def _patch_list_editable(self) -> None:
editable_new = list(self.list_editable)
display_new = list(self.list_display)
for field in self.list_editable:
if field in self.trans_opts.fields:
if field in self.trans_opts.all_fields:
index = editable_new.index(field)
display_index = display_new.index(field)
translation_fields = get_translation_fields(field)
Expand Down Expand Up @@ -350,7 +350,7 @@ def _group_fieldsets(self, fieldsets: list) -> list:
)

temp_fieldsets = {}
for orig_field, trans_fields in self.trans_opts.fields.items():
for orig_field, trans_fields in self.trans_opts.all_fields.items():
trans_fieldnames = [f.name for f in sorted(trans_fields, key=lambda x: x.name)]
if any(f in trans_fieldnames for f in flattened_fieldsets):
# Extract the original field's verbose_name for use as this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def handle(self, *args: Any, **options: Any) -> None:
self.stdout.write("Updating data of model '%s'" % model)

opts = translator.get_options_for_model(model)
for field_name in opts.fields.keys():
for field_name in opts.all_fields.keys():
def_lang_fieldname = build_localized_fieldname(field_name, lang)

# We'll only update fields which do not have an existing value
Expand Down
4 changes: 2 additions & 2 deletions modeltranslation/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def append_fallback(model: type[Model], fields: Sequence[str]) -> tuple[set[str]
from modeltranslation.translator import translator

opts = translator.get_options_for_model(model)
for key, _ in opts.fields.items():
for key, _ in opts.all_fields.items():
if key in fields_set:
langs = resolution_order(get_language(), getattr(model, key).fallback_languages)
fields_set = fields_set.union(build_localized_fieldname(key, lang) for lang in langs)
Expand All @@ -96,7 +96,7 @@ def append_translated(model: type[Model], fields: Sequence[str]) -> set[str]:
from modeltranslation.translator import translator

opts = translator.get_options_for_model(model)
for key, translated in opts.fields.items():
for key, translated in opts.all_fields.items():
if key in fields_set:
fields_set = fields_set.union(f.name for f in translated)
return fields_set
Expand Down
4 changes: 2 additions & 2 deletions modeltranslation/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ def _test_constructor(self, keywords):
n = models.TestModel(**keywords)
m = models.TestModel.objects.create(**keywords)
opts = translator.translator.get_options_for_model(models.TestModel)
for base_field, trans_fields in opts.fields.items():
for base_field, trans_fields in opts.all_fields.items():
self._compare_instances(n, m, base_field)
for lang_field in trans_fields:
self._compare_instances(n, m, lang_field.name)
Expand Down Expand Up @@ -2268,7 +2268,7 @@ def assertLocalFields(model, local_fields):
def assertFields(model, fields):
# The given fields are inherited.
opts = translator.translator.get_options_for_model(model)
assert set(opts.fields.keys()) == set(fields)
assert set(opts.all_fields.keys()) == set(fields)
# Inherited translation fields are available on the model.
model_fields = get_field_names(model)
for field in fields:
Expand Down
22 changes: 11 additions & 11 deletions modeltranslation/translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class FieldsAggregationMetaClass(type):
Metaclass to handle custom inheritance of fields between classes.
"""

fields: Iterable[str]
fields: Sequence[str]

def __new__(cls, name: str, bases: tuple[type, ...], attrs: dict[str, Any]) -> type:
attrs["fields"] = set(attrs.get("fields", ()))
Expand All @@ -89,11 +89,11 @@ class TranslationOptions(metaclass=FieldsAggregationMetaClass):
attributes.
Options instances hold info about translatable fields for a model and its
superclasses. The ``local_fields`` and ``fields`` attributes are mappings
superclasses. The ``local_fields`` and ``all_fields`` attributes are mappings
from fields to sets of their translation fields; ``local_fields`` contains
only those fields that are handled in the model's database table (those
inherited from abstract superclasses, unless there is a concrete superclass
in between in the inheritance chain), while ``fields`` also includes fields
in between in the inheritance chain), while ``all_fields`` also includes fields
inherited from concrete supermodels (giving all translated fields available
on a model).
Expand All @@ -112,7 +112,7 @@ def __init__(self, model: Model) -> None:
self.registered = False
self.related = False
self.local_fields: dict[str, set[TranslationField]] = {f: set() for f in self.fields}
self.fields: dict[str, set[TranslationField]] = {f: set() for f in self.fields}
self.all_fields: dict[str, set[TranslationField]] = {f: set() for f in self.fields}
self.related_fields: list[str] = []

def validate(self) -> None:
Expand All @@ -127,7 +127,7 @@ def validate(self) -> None:
else:
self._check_languages(self.required_languages.keys(), extra=("default",))
for fieldnames in self.required_languages.values():
if any(f not in self.fields for f in fieldnames):
if any(f not in self.all_fields for f in fieldnames):
raise ImproperlyConfigured(
"Fieldname in required_languages which is not in fields option."
)
Expand All @@ -149,24 +149,24 @@ def update(self, other: TranslationOptions):
"""
if other.model._meta.abstract:
self.local_fields.update(other.local_fields)
self.fields.update(other.fields)
self.all_fields.update(other.all_fields)

def add_translation_field(self, field: str, translation_field):
"""
Add a new translation field to both fields dicts.
"""
self.local_fields[field].add(translation_field)
self.fields[field].add(translation_field)
self.all_fields[field].add(translation_field)

def get_field_names(self) -> list[str]:
"""
Return name of all fields that can be used in filtering.
"""
return list(self.fields.keys()) + self.related_fields
return list(self.all_fields.keys()) + self.related_fields

def __str__(self) -> str:
local = tuple(self.local_fields.keys())
inherited = tuple(set(self.fields.keys()) - set(local))
inherited = tuple(set(self.all_fields.keys()) - set(local))
return "%s: %s + %s" % (self.__class__.__name__, local, inherited)


Expand Down Expand Up @@ -434,10 +434,10 @@ def populate_translation_fields(sender: type[Model], kwargs: Any):

opts = translator.get_options_for_model(sender)
for key, val in list(kwargs.items()):
if key in opts.fields:
if key in opts.all_fields:
if populate == "all":
# Set the value for every language.
for translation_field in opts.fields[key]:
for translation_field in opts.all_fields[key]:
kwargs.setdefault(translation_field.name, val)
elif populate == "default":
default = build_localized_fieldname(key, mt_settings.DEFAULT_LANGUAGE)
Expand Down

0 comments on commit b97c22c

Please sign in to comment.