diff --git a/ormar/models/metaclass.py b/ormar/models/metaclass.py index 73a5978..c2baf9e 100644 --- a/ormar/models/metaclass.py +++ b/ormar/models/metaclass.py @@ -60,7 +60,7 @@ def register_relation_on_build_new(new_model: Type["Model"], field_name: str) -> def register_many_to_many_relation_on_build_new( - new_model: Type["Model"], field: Type[ManyToManyField] + new_model: Type["Model"], field: Type[ManyToManyField] ) -> None: alias_manager.add_relation_type_new( field.through, new_model.get_name(), is_multi=True @@ -71,11 +71,11 @@ def register_many_to_many_relation_on_build_new( def reverse_field_not_already_registered( - child: Type["Model"], child_model_name: str, parent_model: Type["Model"] + child: Type["Model"], child_model_name: str, parent_model: Type["Model"] ) -> bool: return ( - child_model_name not in parent_model.__fields__ - and child.get_name() not in parent_model.__fields__ + child_model_name not in parent_model.__fields__ + and child.get_name() not in parent_model.__fields__ ) @@ -86,7 +86,7 @@ def expand_reverse_relationships(model: Type["Model"]) -> None: parent_model = model_field.to child = model if reverse_field_not_already_registered( - child, child_model_name, parent_model + child, child_model_name, parent_model ): register_reverse_model_fields( parent_model, child, child_model_name, model_field @@ -94,10 +94,10 @@ def expand_reverse_relationships(model: Type["Model"]) -> None: def register_reverse_model_fields( - model: Type["Model"], - child: Type["Model"], - child_model_name: str, - model_field: Type["ForeignKeyField"], + model: Type["Model"], + child: Type["Model"], + child_model_name: str, + model_field: Type["ForeignKeyField"], ) -> None: if issubclass(model_field, ManyToManyField): model.Meta.model_fields[child_model_name] = ManyToMany( @@ -139,7 +139,7 @@ def adjust_through_many_to_many_model( def create_pydantic_field( - field_name: str, model: Type["Model"], model_field: Type[ManyToManyField] + field_name: str, model: Type["Model"], model_field: Type[ManyToManyField] ) -> None: model_field.through.__fields__[field_name] = ModelField( name=field_name, @@ -161,7 +161,7 @@ def get_pydantic_field(field_name: str, model: Type["Model"]) -> "ModelField": def create_and_append_m2m_fk( - model: Type["Model"], model_field: Type[ManyToManyField] + model: Type["Model"], model_field: Type[ManyToManyField] ) -> None: column = sqlalchemy.Column( model.get_name(), @@ -177,7 +177,7 @@ def create_and_append_m2m_fk( def check_pk_column_validity( - field_name: str, field: BaseField, pkname: Optional[str] + field_name: str, field: BaseField, pkname: Optional[str] ) -> Optional[str]: if pkname is not None: raise ModelDefinitionError("Only one primary key column is allowed.") @@ -187,7 +187,7 @@ def check_pk_column_validity( def validate_related_names_in_relations( - model_fields: Dict, new_model: Type["Model"] + model_fields: Dict, new_model: Type["Model"] ) -> None: already_registered: Dict[str, List[Optional[str]]] = dict() for field in model_fields.values(): @@ -206,7 +206,7 @@ def validate_related_names_in_relations( def sqlalchemy_columns_from_model_fields( - model_fields: Dict, new_model: Type["Model"] + model_fields: Dict, new_model: Type["Model"] ) -> Tuple[Optional[str], List[sqlalchemy.Column]]: columns = [] pkname = None @@ -221,16 +221,16 @@ def sqlalchemy_columns_from_model_fields( if field.primary_key: pkname = check_pk_column_validity(field_name, field, pkname) if ( - not field.pydantic_only - and not field.virtual - and not issubclass(field, ManyToManyField) + not field.pydantic_only + and not field.virtual + and not issubclass(field, ManyToManyField) ): columns.append(field.get_column(field.get_alias())) return pkname, columns def register_relation_in_alias_manager_new( - new_model: Type["Model"], field: Type[ForeignKeyField], field_name: str + new_model: Type["Model"], field: Type[ForeignKeyField], field_name: str ) -> None: if issubclass(field, ManyToManyField): register_many_to_many_relation_on_build_new(new_model=new_model, field=field) @@ -239,7 +239,7 @@ def register_relation_in_alias_manager_new( def populate_default_pydantic_field_value( - ormar_field: Type[BaseField], field_name: str, attrs: dict + ormar_field: Type[BaseField], field_name: str, attrs: dict ) -> dict: curr_def_value = attrs.get(field_name, ormar.Undefined) if lenient_issubclass(curr_def_value, ormar.fields.BaseField): @@ -284,7 +284,7 @@ def extract_annotations_and_default_vals(attrs: dict) -> Tuple[Dict, Dict]: def populate_meta_tablename_columns_and_pk( - name: str, new_model: Type["Model"] + name: str, new_model: Type["Model"] ) -> Type["Model"]: tablename = name.lower() + "s" new_model.Meta.tablename = ( @@ -309,7 +309,7 @@ def populate_meta_tablename_columns_and_pk( def populate_meta_sqlalchemy_table_if_required( - new_model: Type["Model"], + new_model: Type["Model"], ) -> Type["Model"]: """ Constructs sqlalchemy table out of columns and parameters set on Meta class. @@ -400,7 +400,7 @@ def populate_choices_validators(model: Type["Model"]) -> None: # noqa CCR001 def populate_default_options_values( - new_model: Type["Model"], model_fields: Dict + new_model: Type["Model"], model_fields: Dict ) -> None: """ Sets all optional Meta values to it's defaults @@ -522,11 +522,11 @@ def get_potential_fields(attrs: Dict) -> Dict: def check_conflicting_fields( - new_fields: Set, - attrs: Dict, - base_class: type, - curr_class: type, - previous_fields: Set = None, + new_fields: Set, + attrs: Dict, + base_class: type, + curr_class: type, + previous_fields: Set = None, ) -> None: """ You cannot redefine fields with same names in inherited classes. @@ -556,11 +556,11 @@ def check_conflicting_fields( def update_attrs_and_fields( - attrs: Dict, - new_attrs: Dict, - model_fields: Dict, - new_model_fields: Dict, - new_fields: Set, + attrs: Dict, + new_attrs: Dict, + model_fields: Dict, + new_model_fields: Dict, + new_fields: Set, ) -> None: """ Updates __annotations__, values of model fields (so pydantic FieldInfos) @@ -583,7 +583,9 @@ def update_attrs_and_fields( model_fields.update(new_model_fields) -def update_attrs_from_base_meta(base_class: "Model", attrs: Dict, ) -> None: +def update_attrs_from_base_meta( # noqa: CCR001 + base_class: "Model", attrs: Dict, +) -> None: """ Updates Meta parameters in child from parent if needed. @@ -594,22 +596,28 @@ def update_attrs_from_base_meta(base_class: "Model", attrs: Dict, ) -> None: """ params_to_update = ["metadata", "database", "constraints"] for param in params_to_update: - current_value = attrs.get('Meta', {}).__dict__.get(param, ormar.Undefined) - parent_value = base_class.Meta.__dict__.get(param) if hasattr(base_class, 'Meta') else None + current_value = attrs.get("Meta", {}).__dict__.get(param, ormar.Undefined) + parent_value = ( + base_class.Meta.__dict__.get(param) if hasattr(base_class, "Meta") else None + ) if parent_value: + if param == "constraints": + parent_value = [ + ormar.UniqueColumns(*x._pending_colargs) for x in parent_value + ] if isinstance(current_value, list): current_value.extend(parent_value) else: setattr(attrs["Meta"], param, parent_value) -def extract_from_parents_definition( - base_class: type, - curr_class: type, - attrs: Dict, - model_fields: Dict[ - str, Union[Type[BaseField], Type[ForeignKeyField], Type[ManyToManyField]] - ], +def extract_from_parents_definition( # noqa: CCR001 + base_class: type, + curr_class: type, + attrs: Dict, + model_fields: Dict[ + str, Union[Type[BaseField], Type[ForeignKeyField], Type[ManyToManyField]] + ], ) -> Tuple[Dict, Dict]: """ Extracts fields from base classes if they have valid oramr fields. @@ -714,7 +722,7 @@ def extract_from_parents_definition( class ModelMetaclass(pydantic.main.ModelMetaclass): def __new__( # type: ignore # noqa: CCR001 - mcs: "ModelMetaclass", name: str, bases: Any, attrs: dict + mcs: "ModelMetaclass", name: str, bases: Any, attrs: dict ) -> "ModelMetaclass": attrs["Config"] = get_pydantic_base_orm_config() attrs["__name__"] = name diff --git a/tests/test_inheritance_concrete.py b/tests/test_inheritance_concrete.py index 978c020..93b500e 100644 --- a/tests/test_inheritance_concrete.py +++ b/tests/test_inheritance_concrete.py @@ -92,6 +92,7 @@ def test_init_of_abstract_model(): def test_field_redefining_raises_error(): with pytest.raises(ModelDefinitionError): + class WrongField(DateFieldsModel): # pragma: no cover class Meta(ormar.ModelMeta): tablename = "wrongs" @@ -104,6 +105,7 @@ def test_field_redefining_raises_error(): def test_model_subclassing_non_abstract_raises_error(): with pytest.raises(ModelDefinitionError): + class WrongField2(DateFieldsModelNoSubclass): # pragma: no cover class Meta(ormar.ModelMeta): tablename = "wrongs" @@ -121,7 +123,7 @@ def test_params_are_inherited(): def round_date_to_seconds( - date: datetime.datetime, + date: datetime.datetime, ) -> datetime.datetime: # pragma: no cover if date.microsecond >= 500000: date = date + datetime.timedelta(seconds=1) @@ -163,9 +165,9 @@ async def test_fields_inherited_from_mixin(): sub2 = ( await Subject.objects.select_related("category") - .order_by("-created_date") - .exclude_fields("updated_date") - .get() + .order_by("-created_date") + .exclude_fields("updated_date") + .get() ) assert round_date_to_seconds(sub2.created_date) == round_date_to_seconds( sub.created_date