diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-12-14 13:49:11 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-12-14 15:38:32 -0500 |
| commit | 2bac535f506dd68595d64d6cdf21e2d4937c2c9f (patch) | |
| tree | 7e05f77fa8fccbd63c2d1488278af6e5f56c325d /lib/sqlalchemy | |
| parent | a8d76cff39dbaf6354d42d35cd68332df469d124 (diff) | |
| download | sqlalchemy-2bac535f506dd68595d64d6cdf21e2d4937c2c9f.tar.gz | |
warn when backref will replace existing userland descriptor
A warning is emitted if a backref name used in :func:`_orm.relationship`
names an attribute on the target class which already has a method or
attribute assigned to that name, as the backref declaration will replace
that attribute.
Fixes: #4629
Change-Id: I0059b35ce60f43b0f3d8be008f12411154484ea1
Diffstat (limited to 'lib/sqlalchemy')
| -rw-r--r-- | lib/sqlalchemy/orm/mapper.py | 20 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/relationships.py | 4 |
2 files changed, 21 insertions, 3 deletions
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 7a7524621..93b6c4ecb 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -1658,7 +1658,7 @@ class Mapper( ) continue - self._configure_property(key, possible_col_prop, False) + self._configure_property(key, possible_col_prop, init=False) # step 2: pull properties from the inherited mapper. reconcile # columns with those which are explicit above. for properties that @@ -1698,7 +1698,7 @@ class Mapper( # it now in the order in which it corresponds to the # Table / selectable key, prop = explicit_col_props_by_column[column] - self._configure_property(key, prop, False) + self._configure_property(key, prop, init=False) continue elif column in self._columntoproperty: @@ -1962,8 +1962,10 @@ class Mapper( self, key: str, prop_arg: Union[KeyedColumnElement[Any], MapperProperty[Any]], + *, init: bool = True, setparent: bool = True, + warn_for_existing: bool = False, ) -> MapperProperty[Any]: descriptor_props = util.preloaded.orm_descriptor_props self._log( @@ -2073,6 +2075,20 @@ class Mapper( oldprop = self._props[key] self._path_registry.pop(oldprop, None) + if ( + warn_for_existing + and self.class_.__dict__.get(key, None) is not None + and not isinstance( + self._props.get(key, None), + (descriptor_props.ConcreteInheritedProperty,), + ) + ): + util.warn( + "User-placed attribute %r on %s being replaced with " + 'new property "%s"; the old attribute will be discarded' + % (self.class_.__dict__[key], self, prop) + ) + self._props[key] = prop if not self.non_primary: diff --git a/lib/sqlalchemy/orm/relationships.py b/lib/sqlalchemy/orm/relationships.py index 2a659bdef..9852fa9a9 100644 --- a/lib/sqlalchemy/orm/relationships.py +++ b/lib/sqlalchemy/orm/relationships.py @@ -2108,7 +2108,9 @@ class RelationshipProperty( back_populates=self.key, **kwargs, ) - mapper._configure_property(backref_key, relationship) + mapper._configure_property( + backref_key, relationship, warn_for_existing=True + ) if self.back_populates: self._add_reverse_property(self.back_populates) |
