diff options
Diffstat (limited to 'lib/sqlalchemy/orm')
| -rw-r--r-- | lib/sqlalchemy/orm/_orm_constructors.py | 18 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/properties.py | 52 |
2 files changed, 58 insertions, 12 deletions
diff --git a/lib/sqlalchemy/orm/_orm_constructors.py b/lib/sqlalchemy/orm/_orm_constructors.py index 63fd3b76e..bafad09f2 100644 --- a/lib/sqlalchemy/orm/_orm_constructors.py +++ b/lib/sqlalchemy/orm/_orm_constructors.py @@ -125,6 +125,7 @@ def mapped_column( unique: Optional[bool] = None, info: Optional[_InfoType] = None, onupdate: Optional[Any] = None, + insert_default: Optional[Any] = _NoArg.NO_ARG, server_default: Optional[_ServerDefaultType] = None, server_onupdate: Optional[FetchedValue] = None, quote: Optional[bool] = None, @@ -292,6 +293,17 @@ def mapped_column( ORM declarative process, and is not part of the :class:`_schema.Column` itself; instead, it indicates that this column should be "deferred" for loading as though mapped by :func:`_orm.deferred`. + :param default: This keyword argument, if present, is passed along to the + :class:`_schema.Column` constructor as the value of the + :paramref:`_schema.Column.default` parameter. However, as + :paramref:`_orm.mapped_column.default` is also consumed as a dataclasses + directive, the :paramref:`_orm.mapped_column.insert_default` parameter + should be used instead in a dataclasses context. + :param insert_default: Passed directly to the + :paramref:`_schema.Column.default` parameter; will supersede the value + of :paramref:`_orm.mapped_column.default` when present, however + :paramref:`_orm.mapped_column.default` will always apply to the + constructor default for a dataclasses mapping. :param \**kw: All remaining keyword argments are passed through to the constructor for the :class:`_schema.Column`. @@ -304,7 +316,11 @@ def mapped_column( name=name, type_=type_, autoincrement=autoincrement, - default=default, + insert_default=insert_default + if insert_default is not _NoArg.NO_ARG + else default + if default is not _NoArg.NO_ARG + else None, attribute_options=_AttributeOptions( init, repr, diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index d1faff1d9..7308b8fb1 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -505,18 +505,14 @@ class MappedColumn( if attr_opts is not None and attr_opts != _DEFAULT_ATTRIBUTE_OPTIONS: if attr_opts.dataclasses_default_factory is not _NoArg.NO_ARG: self._has_dataclass_arguments = True - kw["default"] = attr_opts.dataclasses_default_factory - elif attr_opts.dataclasses_default is not _NoArg.NO_ARG: - kw["default"] = attr_opts.dataclasses_default - if ( + elif ( attr_opts.dataclasses_init is not _NoArg.NO_ARG or attr_opts.dataclasses_repr is not _NoArg.NO_ARG ): self._has_dataclass_arguments = True - if "default" in kw and kw["default"] is _NoArg.NO_ARG: - kw.pop("default") + kw["default"] = kw.pop("insert_default", None) self.deferred = kw.pop("deferred", False) self.column = cast("Column[_T]", Column(*arg, **kw)) @@ -525,6 +521,7 @@ class MappedColumn( None, SchemaConst.NULL_UNSPECIFIED, ) + util.set_creation_order(self) def _copy(self: Self, **kw: Any) -> Self: @@ -630,14 +627,47 @@ class MappedColumn( if not self._has_nullable: self.column.nullable = nullable + our_type = de_optionalize_union_types(argument) + if is_fwd_ref(our_type): + our_type = de_stringify_annotation(cls, our_type) + + use_args_from = None + if is_pep593(our_type): + our_type_is_pep593 = True + for elem in typing_get_args(our_type): + if isinstance(elem, MappedColumn): + use_args_from = elem + break + else: + our_type_is_pep593 = False + + if use_args_from is not None: + if use_args_from.column.primary_key: + self.column.primary_key = True + if use_args_from.column.default is not None: + self.column.default = use_args_from.column.default + if ( + use_args_from.column.server_default + and self.column.server_default is None + ): + self.column.server_default = ( + use_args_from.column.server_default + ) + + for const in use_args_from.column.constraints: + if not const._type_bound: + new_const = const._copy() + new_const._set_parent(self.column) + + for fk in use_args_from.column.foreign_keys: + if not fk.constraint: + new_fk = fk._copy() + new_fk._set_parent(self.column) + if sqltype._isnull and not self.column.foreign_keys: new_sqltype = None - our_type = de_optionalize_union_types(argument) - - if is_fwd_ref(our_type): - our_type = de_stringify_annotation(cls, our_type) - if is_pep593(our_type): + if our_type_is_pep593: checks = (our_type,) + typing_get_args(our_type) else: checks = (our_type,) |
