diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-07-15 12:53:37 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-07-16 16:28:11 -0400 |
| commit | 9a37ebdf99d0e3fcca53ca8f00f101fe475a1b01 (patch) | |
| tree | 112107d938b959316253b3988132a2109947889f /lib/sqlalchemy/ext | |
| parent | 6104c163eb58e35e46b0bb6a237e824ec1ee1d15 (diff) | |
| download | sqlalchemy-9a37ebdf99d0e3fcca53ca8f00f101fe475a1b01.tar.gz | |
update ORM declarative docs for new features
I screwed up a rebase or something so this was
temporarily in Ic51a12de3358f3a451bd7cf3542b375569499fc1
Change-Id: I847ee1336381221c0112b67854df022edf596b25
Diffstat (limited to 'lib/sqlalchemy/ext')
| -rw-r--r-- | lib/sqlalchemy/ext/mutable.py | 80 |
1 files changed, 40 insertions, 40 deletions
diff --git a/lib/sqlalchemy/ext/mutable.py b/lib/sqlalchemy/ext/mutable.py index 6c26c9266..1d6cf8a85 100644 --- a/lib/sqlalchemy/ext/mutable.py +++ b/lib/sqlalchemy/ext/mutable.py @@ -236,19 +236,19 @@ a geometric "point", and is introduced in :ref:`mapper_composite`. As is the case with :class:`.Mutable`, the user-defined composite class subclasses :class:`.MutableComposite` as a mixin, and detects and delivers change events to its parents via the :meth:`.MutableComposite.changed` method. -In the case of a composite class, the detection is usually via the usage of -Python descriptors (i.e. ``@property``), or alternatively via the special -Python method ``__setattr__()``. Below we expand upon the ``Point`` class -introduced in :ref:`mapper_composite` to subclass :class:`.MutableComposite` -and to also route attribute set events via ``__setattr__`` to the -:meth:`.MutableComposite.changed` method:: +In the case of a composite class, the detection is usually via the usage of the +special Python method ``__setattr__()``. In the example below, we expand upon the ``Point`` +class introduced in :ref:`mapper_composite` to include +:class:`.MutableComposite` in its bases and to route attribute set events via +``__setattr__`` to the :meth:`.MutableComposite.changed` method:: + import dataclasses from sqlalchemy.ext.mutable import MutableComposite + @dataclasses.dataclass class Point(MutableComposite): - def __init__(self, x, y): - self.x = x - self.y = y + x: int + y: int def __setattr__(self, key, value): "Intercept set events" @@ -259,16 +259,6 @@ and to also route attribute set events via ``__setattr__`` to the # alert all parents to the change self.changed() - def __composite_values__(self): - return self.x, self.y - - def __eq__(self, other): - return isinstance(other, Point) and \ - other.x == self.x and \ - other.y == self.y - - def __ne__(self, other): - return not self.__eq__(other) The :class:`.MutableComposite` class makes use of class mapping events to automatically establish listeners for any usage of :func:`_orm.composite` that @@ -276,38 +266,45 @@ specifies our ``Point`` type. Below, when ``Point`` is mapped to the ``Vertex`` class, listeners are established which will route change events from ``Point`` objects to each of the ``Vertex.start`` and ``Vertex.end`` attributes:: - from sqlalchemy.orm import composite, mapper - from sqlalchemy import Table, Column - - vertices = Table('vertices', metadata, - Column('id', Integer, primary_key=True), - Column('x1', Integer), - Column('y1', Integer), - Column('x2', Integer), - Column('y2', Integer), - ) + from sqlalchemy.orm import DeclarativeBase, Mapped + from sqlalchemy.orm import composite, mapped_column - class Vertex: + class Base(DeclarativeBase): pass - mapper(Vertex, vertices, properties={ - 'start': composite(Point, vertices.c.x1, vertices.c.y1), - 'end': composite(Point, vertices.c.x2, vertices.c.y2) - }) + + class Vertex(Base): + __tablename__ = "vertices" + + id: Mapped[int] = mapped_column(primary_key=True) + + start: Mapped[Point] = composite(mapped_column("x1"), mapped_column("y1")) + end: Mapped[Point] = composite(mapped_column("x2"), mapped_column("y2")) + + def __repr__(self): + return f"Vertex(start={self.start}, end={self.end})" Any in-place changes to the ``Vertex.start`` or ``Vertex.end`` members -will flag the attribute as "dirty" on the parent object:: +will flag the attribute as "dirty" on the parent object: - >>> from sqlalchemy.orm import Session +.. sourcecode:: python+sql - >>> sess = Session() + >>> from sqlalchemy.orm import Session + >>> sess = Session(engine) >>> v1 = Vertex(start=Point(3, 4), end=Point(12, 15)) >>> sess.add(v1) - >>> sess.commit() + {sql}>>> sess.flush() + BEGIN (implicit) + INSERT INTO vertices (x1, y1, x2, y2) VALUES (?, ?, ?, ?) + [...] (3, 4, 12, 15) - >>> v1.end.x = 8 + {stop}>>> v1.end.x = 8 >>> assert v1 in sess.dirty True + {sql}>>> sess.commit() + UPDATE vertices SET x2=? WHERE vertices.id = ? + [...] (8, 1) + COMMIT Coercing Mutable Composites --------------------------- @@ -319,6 +316,7 @@ Overriding the :meth:`.MutableBase.coerce` method is essentially equivalent to using a :func:`.validates` validation routine for all attributes which make use of the custom composite type:: + @dataclasses.dataclass class Point(MutableComposite): # other Point methods # ... @@ -341,6 +339,7 @@ to define a ``__getstate__`` that doesn't include the ``_parents`` dictionary. Below we define both a ``__getstate__`` and a ``__setstate__`` that package up the minimal form of our ``Point`` class:: + @dataclasses.dataclass class Point(MutableComposite): # ... @@ -354,7 +353,8 @@ As with :class:`.Mutable`, the :class:`.MutableComposite` augments the pickling process of the parent's object-relational state so that the :meth:`MutableBase._parents` collection is restored to all ``Point`` objects. -""" +""" # noqa: E501 + from collections import defaultdict import weakref |
