Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
events.py456 linesDownload Raw Back to sql
1# sql/events.py
2# Copyright (C) 2005-2024 the SQLAlchemy authors and contributors
3# <see AUTHORS file>
4#
5# This module is part of SQLAlchemy and is released under
6# the MIT License: https://www.opensource.org/licenses/mit-license.php
7
8from __future__ import annotations
9
10from typing import Any
11from typing import TYPE_CHECKING
12
13from .base import SchemaEventTarget
14from .. import event
15
16if TYPE_CHECKING:
17    from .schema import Column
18    from .schema import Constraint
19    from .schema import SchemaItem
20    from .schema import Table
21    from ..engine.base import Connection
22    from ..engine.interfaces import ReflectedColumn
23    from ..engine.reflection import Inspector
24
25
26class DDLEvents(event.Events[SchemaEventTarget]):
27    """
28    Define event listeners for schema objects,
29    that is, :class:`.SchemaItem` and other :class:`.SchemaEventTarget`
30    subclasses, including :class:`_schema.MetaData`, :class:`_schema.Table`,
31    :class:`_schema.Column`, etc.
32
33    **Create / Drop Events**
34
35    Events emitted when CREATE and DROP commands are emitted to the database.
36    The event hooks in this category include :meth:`.DDLEvents.before_create`,
37    :meth:`.DDLEvents.after_create`, :meth:`.DDLEvents.before_drop`, and
38    :meth:`.DDLEvents.after_drop`.
39
40    These events are emitted when using schema-level methods such as
41    :meth:`.MetaData.create_all` and :meth:`.MetaData.drop_all`. Per-object
42    create/drop methods such as :meth:`.Table.create`, :meth:`.Table.drop`,
43    :meth:`.Index.create` are also included, as well as dialect-specific
44    methods such as :meth:`_postgresql.ENUM.create`.
45
46    .. versionadded:: 2.0 :class:`.DDLEvents` event hooks now take place
47       for non-table objects including constraints, indexes, and
48       dialect-specific schema types.
49
50    Event hooks may be attached directly to a :class:`_schema.Table` object or
51    to a :class:`_schema.MetaData` collection, as well as to any
52    :class:`.SchemaItem` class or object that can be individually created and
53    dropped using a distinct SQL command. Such classes include :class:`.Index`,
54    :class:`.Sequence`, and dialect-specific classes such as
55    :class:`_postgresql.ENUM`.
56
57    Example using the :meth:`.DDLEvents.after_create` event, where a custom
58    event hook will emit an ``ALTER TABLE`` command on the current connection,
59    after ``CREATE TABLE`` is emitted::
60
61        from sqlalchemy import create_engine
62        from sqlalchemy import event
63        from sqlalchemy import Table, Column, Metadata, Integer
64
65        m = MetaData()
66        some_table = Table('some_table', m, Column('data', Integer))
67
68        @event.listens_for(some_table, "after_create")
69        def after_create(target, connection, **kw):
70            connection.execute(text(
71                "ALTER TABLE %s SET name=foo_%s" % (target.name, target.name)
72            ))
73
74
75        some_engine = create_engine("postgresql://scott:tiger@host/test")
76
77        # will emit "CREATE TABLE some_table" as well as the above
78        # "ALTER TABLE" statement afterwards
79        m.create_all(some_engine)
80
81    Constraint objects such as :class:`.ForeignKeyConstraint`,
82    :class:`.UniqueConstraint`, :class:`.CheckConstraint` may also be
83    subscribed to these events, however they will **not** normally produce
84    events as these objects are usually rendered inline within an
85    enclosing ``CREATE TABLE`` statement and implicitly dropped from a
86    ``DROP TABLE`` statement.
87
88    For the :class:`.Index` construct, the event hook will be emitted
89    for ``CREATE INDEX``, however SQLAlchemy does not normally emit
90    ``DROP INDEX`` when dropping tables as this is again implicit within the
91    ``DROP TABLE`` statement.
92
93    .. versionadded:: 2.0 Support for :class:`.SchemaItem` objects
94       for create/drop events was expanded from its previous support for
95       :class:`.MetaData` and :class:`.Table` to also include
96       :class:`.Constraint` and all subclasses, :class:`.Index`,
97       :class:`.Sequence` and some type-related constructs such as
98       :class:`_postgresql.ENUM`.
99
100    .. note:: These event hooks are only emitted within the scope of
101       SQLAlchemy's create/drop methods; they are not necessarily supported
102       by tools such as `alembic <https://alembic.sqlalchemy.org>`_.
103
104
105    **Attachment Events**
106
107    Attachment events are provided to customize
108    behavior whenever a child schema element is associated
109    with a parent, such as when a :class:`_schema.Column` is associated
110    with its :class:`_schema.Table`, when a
111    :class:`_schema.ForeignKeyConstraint`
112    is associated with a :class:`_schema.Table`, etc.  These events include
113    :meth:`.DDLEvents.before_parent_attach` and
114    :meth:`.DDLEvents.after_parent_attach`.
115
116    **Reflection Events**
117
118    The :meth:`.DDLEvents.column_reflect` event is used to intercept
119    and modify the in-Python definition of database columns when
120    :term:`reflection` of database tables proceeds.
121
122    **Use with Generic DDL**
123
124    DDL events integrate closely with the
125    :class:`.DDL` class and the :class:`.ExecutableDDLElement` hierarchy
126    of DDL clause constructs, which are themselves appropriate
127    as listener callables::
128
129        from sqlalchemy import DDL
130        event.listen(
131            some_table,
132            "after_create",
133            DDL("ALTER TABLE %(table)s SET name=foo_%(table)s")
134        )
135
136    **Event Propagation to MetaData Copies**
137
138    For all :class:`.DDLEvent` events, the ``propagate=True`` keyword argument
139    will ensure that a given event handler is propagated to copies of the
140    object, which are made when using the :meth:`_schema.Table.to_metadata`
141    method::
142
143        from sqlalchemy import DDL
144
145        metadata = MetaData()
146        some_table = Table("some_table", metadata, Column("data", Integer))
147
148        event.listen(
149            some_table,
150            "after_create",
151            DDL("ALTER TABLE %(table)s SET name=foo_%(table)s"),
152            propagate=True
153        )
154
155        new_metadata = MetaData()
156        new_table = some_table.to_metadata(new_metadata)
157
158    The above :class:`.DDL` object will be associated with the
159    :meth:`.DDLEvents.after_create` event for both the ``some_table`` and
160    the ``new_table`` :class:`.Table` objects.
161
162    .. seealso::
163
164        :ref:`event_toplevel`
165
166        :class:`.ExecutableDDLElement`
167
168        :class:`.DDL`
169
170        :ref:`schema_ddl_sequences`
171
172    """
173
174    _target_class_doc = "SomeSchemaClassOrObject"
175    _dispatch_target = SchemaEventTarget
176
177    def before_create(
178        self, target: SchemaEventTarget, connection: Connection, **kw: Any
179    ) -> None:
180        r"""Called before CREATE statements are emitted.
181
182        :param target: the :class:`.SchemaObject`, such as a
183         :class:`_schema.MetaData` or :class:`_schema.Table`
184         but also including all create/drop objects such as
185         :class:`.Index`, :class:`.Sequence`, etc.,
186         object which is the target of the event.
187
188         .. versionadded:: 2.0 Support for all :class:`.SchemaItem` objects
189            was added.
190
191        :param connection: the :class:`_engine.Connection` where the
192         CREATE statement or statements will be emitted.
193        :param \**kw: additional keyword arguments relevant
194         to the event.  The contents of this dictionary
195         may vary across releases, and include the
196         list of tables being generated for a metadata-level
197         event, the checkfirst flag, and other
198         elements used by internal events.
199
200        :func:`.event.listen` accepts the ``propagate=True``
201        modifier for this event; when True, the listener function will
202        be established for any copies made of the target object,
203        i.e. those copies that are generated when
204        :meth:`_schema.Table.to_metadata` is used.
205
206        :func:`.event.listen` accepts the ``insert=True``
207        modifier for this event; when True, the listener function will
208        be prepended to the internal list of events upon discovery, and execute
209        before registered listener functions that do not pass this argument.
210
211        """
212
213    def after_create(
214        self, target: SchemaEventTarget, connection: Connection, **kw: Any
215    ) -> None:
216        r"""Called after CREATE statements are emitted.
217
218        :param target: the :class:`.SchemaObject`, such as a
219         :class:`_schema.MetaData` or :class:`_schema.Table`
220         but also including all create/drop objects such as
221         :class:`.Index`, :class:`.Sequence`, etc.,
222         object which is the target of the event.
223
224         .. versionadded:: 2.0 Support for all :class:`.SchemaItem` objects
225            was added.
226
227        :param connection: the :class:`_engine.Connection` where the
228         CREATE statement or statements have been emitted.
229        :param \**kw: additional keyword arguments relevant
230         to the event.  The contents of this dictionary
231         may vary across releases, and include the
232         list of tables being generated for a metadata-level
233         event, the checkfirst flag, and other
234         elements used by internal events.
235
236        :func:`.event.listen` also accepts the ``propagate=True``
237        modifier for this event; when True, the listener function will
238        be established for any copies made of the target object,
239        i.e. those copies that are generated when
240        :meth:`_schema.Table.to_metadata` is used.
241
242        """
243
244    def before_drop(
245        self, target: SchemaEventTarget, connection: Connection, **kw: Any
246    ) -> None:
247        r"""Called before DROP statements are emitted.
248
249        :param target: the :class:`.SchemaObject`, such as a
250         :class:`_schema.MetaData` or :class:`_schema.Table`
251         but also including all create/drop objects such as
252         :class:`.Index`, :class:`.Sequence`, etc.,
253         object which is the target of the event.
254
255         .. versionadded:: 2.0 Support for all :class:`.SchemaItem` objects
256            was added.
257
258        :param connection: the :class:`_engine.Connection` where the
259         DROP statement or statements will be emitted.
260        :param \**kw: additional keyword arguments relevant
261         to the event.  The contents of this dictionary
262         may vary across releases, and include the
263         list of tables being generated for a metadata-level
264         event, the checkfirst flag, and other
265         elements used by internal events.
266
267        :func:`.event.listen` also accepts the ``propagate=True``
268        modifier for this event; when True, the listener function will
269        be established for any copies made of the target object,
270        i.e. those copies that are generated when
271        :meth:`_schema.Table.to_metadata` is used.
272
273        """
274
275    def after_drop(
276        self, target: SchemaEventTarget, connection: Connection, **kw: Any
277    ) -> None:
278        r"""Called after DROP statements are emitted.
279
280        :param target: the :class:`.SchemaObject`, such as a
281         :class:`_schema.MetaData` or :class:`_schema.Table`
282         but also including all create/drop objects such as
283         :class:`.Index`, :class:`.Sequence`, etc.,
284         object which is the target of the event.
285
286         .. versionadded:: 2.0 Support for all :class:`.SchemaItem` objects
287            was added.
288
289        :param connection: the :class:`_engine.Connection` where the
290         DROP statement or statements have been emitted.
291        :param \**kw: additional keyword arguments relevant
292         to the event.  The contents of this dictionary
293         may vary across releases, and include the
294         list of tables being generated for a metadata-level
295         event, the checkfirst flag, and other
296         elements used by internal events.
297
298        :func:`.event.listen` also accepts the ``propagate=True``
299        modifier for this event; when True, the listener function will
300        be established for any copies made of the target object,
301        i.e. those copies that are generated when
302        :meth:`_schema.Table.to_metadata` is used.
303
304        """
305
306    def before_parent_attach(
307        self, target: SchemaEventTarget, parent: SchemaItem
308    ) -> None:
309        """Called before a :class:`.SchemaItem` is associated with
310        a parent :class:`.SchemaItem`.
311
312        :param target: the target object
313        :param parent: the parent to which the target is being attached.
314
315        :func:`.event.listen` also accepts the ``propagate=True``
316        modifier for this event; when True, the listener function will
317        be established for any copies made of the target object,
318        i.e. those copies that are generated when
319        :meth:`_schema.Table.to_metadata` is used.
320
321        """
322
323    def after_parent_attach(
324        self, target: SchemaEventTarget, parent: SchemaItem
325    ) -> None:
326        """Called after a :class:`.SchemaItem` is associated with
327        a parent :class:`.SchemaItem`.
328
329        :param target: the target object
330        :param parent: the parent to which the target is being attached.
331
332        :func:`.event.listen` also accepts the ``propagate=True``
333        modifier for this event; when True, the listener function will
334        be established for any copies made of the target object,
335        i.e. those copies that are generated when
336        :meth:`_schema.Table.to_metadata` is used.
337
338        """
339
340    def _sa_event_column_added_to_pk_constraint(
341        self, const: Constraint, col: Column[Any]
342    ) -> None:
343        """internal event hook used for primary key naming convention
344        updates.
345
346        """
347
348    def column_reflect(
349        self, inspector: Inspector, table: Table, column_info: ReflectedColumn
350    ) -> None:
351        """Called for each unit of 'column info' retrieved when
352        a :class:`_schema.Table` is being reflected.
353
354        This event is most easily used by applying it to a specific
355        :class:`_schema.MetaData` instance, where it will take effect for
356        all :class:`_schema.Table` objects within that
357        :class:`_schema.MetaData` that undergo reflection::
358
359            metadata = MetaData()
360
361            @event.listens_for(metadata, 'column_reflect')
362            def receive_column_reflect(inspector, table, column_info):
363                # receives for all Table objects that are reflected
364                # under this MetaData
365
366
367            # will use the above event hook
368            my_table = Table("my_table", metadata, autoload_with=some_engine)
369
370
371        .. versionadded:: 1.4.0b2 The :meth:`_events.DDLEvents.column_reflect`
372           hook may now be applied to a :class:`_schema.MetaData` object as
373           well as the :class:`_schema.MetaData` class itself where it will
374           take place for all :class:`_schema.Table` objects associated with
375           the targeted :class:`_schema.MetaData`.
376
377        It may also be applied to the :class:`_schema.Table` class across
378        the board::
379
380            from sqlalchemy import Table
381
382            @event.listens_for(Table, 'column_reflect')
383            def receive_column_reflect(inspector, table, column_info):
384                # receives for all Table objects that are reflected
385
386        It can also be applied to a specific :class:`_schema.Table` at the
387        point that one is being reflected using the
388        :paramref:`_schema.Table.listeners` parameter::
389
390            t1 = Table(
391                "my_table",
392                autoload_with=some_engine,
393                listeners=[
394                    ('column_reflect', receive_column_reflect)
395                ]
396            )
397
398        The dictionary of column information as returned by the
399        dialect is passed, and can be modified.  The dictionary
400        is that returned in each element of the list returned
401        by :meth:`.reflection.Inspector.get_columns`:
402
403            * ``name`` - the column's name, is applied to the
404              :paramref:`_schema.Column.name` parameter
405
406            * ``type`` - the type of this column, which should be an instance
407              of :class:`~sqlalchemy.types.TypeEngine`, is applied to the
408              :paramref:`_schema.Column.type` parameter
409
410            * ``nullable`` - boolean flag if the column is NULL or NOT NULL,
411              is applied to the :paramref:`_schema.Column.nullable` parameter
412
413            * ``default`` - the column's server default value.  This is
414              normally specified as a plain string SQL expression, however the
415              event can pass a :class:`.FetchedValue`, :class:`.DefaultClause`,
416              or :func:`_expression.text` object as well.  Is applied to the
417              :paramref:`_schema.Column.server_default` parameter
418
419        The event is called before any action is taken against
420        this dictionary, and the contents can be modified; the following
421        additional keys may be added to the dictionary to further modify
422        how the :class:`_schema.Column` is constructed:
423
424
425            * ``key`` - the string key that will be used to access this
426              :class:`_schema.Column` in the ``.c`` collection; will be applied
427              to the :paramref:`_schema.Column.key` parameter. Is also used
428              for ORM mapping.  See the section
429              :ref:`mapper_automated_reflection_schemes` for an example.
430
431            * ``quote`` - force or un-force quoting on the column name;
432              is applied to the :paramref:`_schema.Column.quote` parameter.
433
434            * ``info`` - a dictionary of arbitrary data to follow along with
435              the :class:`_schema.Column`, is applied to the
436              :paramref:`_schema.Column.info` parameter.
437
438        :func:`.event.listen` also accepts the ``propagate=True``
439        modifier for this event; when True, the listener function will
440        be established for any copies made of the target object,
441        i.e. those copies that are generated when
442        :meth:`_schema.Table.to_metadata` is used.
443
444        .. seealso::
445
446            :ref:`mapper_automated_reflection_schemes` -
447            in the ORM mapping documentation
448
449            :ref:`automap_intercepting_columns` -
450            in the :ref:`automap_toplevel` documentation
451
452            :ref:`metadata_reflection_dbagnostic_types` - in
453            the :ref:`metadata_reflection_toplevel` documentation
454
455        """
456 
codekingpro/portable-devtools · Team Ai