Skip to content

Commit

Permalink
refactor complex method ModelMeta.__new__
Browse files Browse the repository at this point in the history
  • Loading branch information
waketzheng committed Jan 13, 2025
1 parent bd70544 commit 2aa549f
Showing 1 changed file with 30 additions and 19 deletions.
49 changes: 30 additions & 19 deletions tortoise/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -540,33 +540,25 @@ def parse_custom_pk(attrs: dict, pk_attr: str, name: str, is_abstract) -> tuple[
)
return attrs, pk_attr

def __new__(cls, name: str, bases: tuple[Type, ...], attrs: dict) -> "ModelMeta":
fields_db_projection: dict[str, str] = {}
@staticmethod
def dispatch_fields(attrs: dict, fields_db_projection: dict, is_abstract) -> tuple[
dict[str, Field],
dict[str, FilterInfoDict],
set[str],
set[str],
set[str],
]:
fields_map: dict[str, Field] = {}
filters: dict[str, FilterInfoDict] = {}
fk_fields: set[str] = set()
m2m_fields: set[str] = set()
o2o_fields: set[str] = set()
meta_class: "Model.Meta" = attrs.get("Meta", type("Meta", (), {}))
pk_attr: str = "id"

# Start searching for fields in the base classes.
inherited_attrs: dict = {}
for base in bases:
_search_for_field_attributes(base, inherited_attrs)
if inherited_attrs:
# Ensure that the inherited fields are before the defined ones.
attrs = {**inherited_attrs, **attrs}
is_abstract = getattr(meta_class, "abstract", False)
if name != "Model":
attrs, pk_attr = cls.parse_custom_pk(attrs, pk_attr, name, is_abstract)

for key, value in attrs.items():
if isinstance(value, Field):
if is_abstract:
value = deepcopy(value)

fields_map[key] = value
field = fields_map[key] = value
value.model_field_name = key

if isinstance(value, OneToOneFieldInstance):
Expand All @@ -576,7 +568,6 @@ def __new__(cls, name: str, bases: tuple[Type, ...], attrs: dict) -> "ModelMeta"
elif isinstance(value, ManyToManyFieldInstance):
m2m_fields.add(key)
else:
field = fields_map[key]
source_field = fields_db_projection[key] = value.source_field or key
filters.update(
get_filters_for_field(
Expand All @@ -589,6 +580,26 @@ def __new__(cls, name: str, bases: tuple[Type, ...], attrs: dict) -> "ModelMeta"
field_name="pk", field=field, source_field=source_field
)
)
return (fields_map, filters, fk_fields, m2m_fields, o2o_fields)

def __new__(mcs, name: str, bases: tuple[Type, ...], attrs: dict) -> "ModelMeta":
fields_db_projection: dict[str, str] = {}
meta_class: "Model.Meta" = attrs.get("Meta", type("Meta", (), {}))
pk_attr: str = "id"

# Start searching for fields in the base classes.
inherited_attrs: dict = {}
for base in bases:
_search_for_field_attributes(base, inherited_attrs)
if inherited_attrs:
# Ensure that the inherited fields are before the defined ones.
attrs = {**inherited_attrs, **attrs}
is_abstract = getattr(meta_class, "abstract", False)
if name != "Model":
attrs, pk_attr = mcs.parse_custom_pk(attrs, pk_attr, name, is_abstract)
(fields_map, filters, fk_fields, m2m_fields, o2o_fields) = mcs.dispatch_fields(
attrs, fields_db_projection, is_abstract
)

# Clean the class attributes
for slot in fields_map:
Expand Down Expand Up @@ -617,7 +628,7 @@ def __new__(cls, name: str, bases: tuple[Type, ...], attrs: dict) -> "ModelMeta"
if not fields_map:
meta.abstract = True

new_class = super().__new__(cls, name, bases, attrs)
new_class = super().__new__(mcs, name, bases, attrs)
for field in meta.fields_map.values():
field.model = new_class # type: ignore

Expand Down

0 comments on commit 2aa549f

Please sign in to comment.