From 780c2e0735b0f3efcb2e3013ee4c7647139715eb Mon Sep 17 00:00:00 2001 From: Rick van Hattem Date: Sat, 12 Mar 2022 03:28:45 +0100 Subject: [PATCH 1/4] Re-added support for __set_name__ as the Python class datamodel prescribes --- tests/fields/subclass_fields.py | 9 +++++++++ tests/fields/subclass_models.py | 6 +++++- tortoise/fields/base.py | 7 +++++++ tortoise/models.py | 7 ++++++- 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/tests/fields/subclass_fields.py b/tests/fields/subclass_fields.py index 8c8f6e6b6..5959e971f 100644 --- a/tests/fields/subclass_fields.py +++ b/tests/fields/subclass_fields.py @@ -76,3 +76,12 @@ def to_python_value(self, value: Any) -> Any: return self.enum_type(value) except ValueError: raise ValueError(f"Database value {value} does not exist on Enum {self.enum_type}.") + + +class NamedField(CharField): + def __init__(self, name: str, **kwargs): + super().__init__(128, **kwargs) + self.name = name + + def __set_name__(self, owner: Type[Any], name: str) -> None: + assert self.name == name diff --git a/tests/fields/subclass_models.py b/tests/fields/subclass_models.py index a99d5a68a..46675b643 100644 --- a/tests/fields/subclass_models.py +++ b/tests/fields/subclass_models.py @@ -1,6 +1,6 @@ from enum import Enum, IntEnum -from tests.fields.subclass_fields import EnumField, IntEnumField +from tests.fields.subclass_fields import EnumField, IntEnumField, NamedField from tortoise import fields from tortoise.models import Model @@ -29,3 +29,7 @@ class ContactTypeEnum(IntEnum): class Contact(Model): id = fields.IntField(pk=True) type = IntEnumField(ContactTypeEnum, default=ContactTypeEnum.other) + + +class NamedFields(Model): + a = NamedField("a") diff --git a/tortoise/fields/base.py b/tortoise/fields/base.py index f4a32ec37..db7aae2f1 100644 --- a/tortoise/fields/base.py +++ b/tortoise/fields/base.py @@ -168,6 +168,13 @@ def __init__( self.model: Type["Model"] = model # type: ignore self.reference: "Optional[Field]" = None + def __set_name__(self, owner: Type[Any], name: str) -> None: + """Set the name of the field on the model and the model. + Needed because Mypy is not yet __set_name__ aware: + https://github.com/python/mypy/issues/8057 + """ + ... + def to_db_value(self, value: Any, instance: "Union[Type[Model], Model]") -> Any: """ Converts from the Python type to the DB type. diff --git a/tortoise/models.py b/tortoise/models.py index af7cb9487..354238108 100644 --- a/tortoise/models.py +++ b/tortoise/models.py @@ -619,9 +619,14 @@ def __search_for_field_attributes(base: Type, attrs: dict) -> None: meta.abstract = True new_class = super().__new__(mcs, name, bases, attrs) - for field in meta.fields_map.values(): + for name, field in meta.fields_map.items(): field.model = new_class # type: ignore + # Call __set_name__ so fields know their own attribute name and parent model + # https://docs.python.org/3/reference/datamodel.html#object.__set_name__ + if hasattr(field, "__set_name__"): + field.__set_name__(new_class, name) + for fname, comment in _get_comments(new_class).items(): # type: ignore if fname in fields_map: fields_map[fname].docstring = comment From 7a650c0a87db928c348eda83df4bf419dc252746 Mon Sep 17 00:00:00 2001 From: Rick van Hattem Date: Sat, 12 Mar 2022 03:37:46 +0100 Subject: [PATCH 2/4] updated changelog and contributors file --- CHANGELOG.rst | 1 + CONTRIBUTORS.rst | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6eab884ca..1b17cec5d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -13,6 +13,7 @@ Changelog Added ^^^^^ - Added psycopg backend support. +- Added __set_name__ support for custom fields Fixed ^^^^^ - Fix `bulk_create` doesn't work correctly with more than 1 update_fields. (#1046) diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index df2ef7cc2..0902d5534 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -50,6 +50,7 @@ Contributors * Vinay Karanam ``@vinayinvicible`` * Aleksandr Rozum ``@rozumalex`` * Mojix Coder ``@MojixCoder`` +* Rick van Hattem ``@wolph`` Special Thanks ============== From ab11f877b72f818fc1983cea7ad16a4dbd81cabf Mon Sep 17 00:00:00 2001 From: Rick van Hattem Date: Sat, 12 Mar 2022 03:44:06 +0100 Subject: [PATCH 3/4] Even in tests CI is not happy about assert statements --- tests/fields/subclass_fields.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/fields/subclass_fields.py b/tests/fields/subclass_fields.py index 5959e971f..f39d9af22 100644 --- a/tests/fields/subclass_fields.py +++ b/tests/fields/subclass_fields.py @@ -84,4 +84,5 @@ def __init__(self, name: str, **kwargs): self.name = name def __set_name__(self, owner: Type[Any], name: str) -> None: - assert self.name == name + if self.name != name: + raise RuntimeError(f"Field name {name} does not match {self.name}") From 21c45ba801b6ef836a36dce121d22e52cde965c6 Mon Sep 17 00:00:00 2001 From: Rick van Hattem Date: Sat, 12 Mar 2022 03:58:02 +0100 Subject: [PATCH 4/4] make codacy happy --- tortoise/fields/base.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tortoise/fields/base.py b/tortoise/fields/base.py index db7aae2f1..7f04b753c 100644 --- a/tortoise/fields/base.py +++ b/tortoise/fields/base.py @@ -169,7 +169,9 @@ def __init__( self.reference: "Optional[Field]" = None def __set_name__(self, owner: Type[Any], name: str) -> None: - """Set the name of the field on the model and the model. + """ + Set the name of the field on the model and the model. + Needed because Mypy is not yet __set_name__ aware: https://github.com/python/mypy/issues/8057 """