kotti.events

This module includes a simple events system that allows users to subscribe to specific events, and more particularly to object events of specific object types.

See also: Events.

Inheritance Diagram

Inheritance diagram of kotti.events

class kotti.events.Dispatcher(*args, **kwargs)[source]

Dispatches based on event type.

>>> class BaseEvent(object): pass
>>> class SubEvent(BaseEvent): pass
>>> class UnrelatedEvent(object): pass
>>> def base_listener(event):
...     print 'Called base listener'
>>> def sub_listener(event):
...     print 'Called sub listener'
>>> def unrelated_listener(event):
...     print 'Called unrelated listener'
...     return 1
>>> dispatcher = Dispatcher()
>>> dispatcher[BaseEvent].append(base_listener)
>>> dispatcher[SubEvent].append(sub_listener)
>>> dispatcher[UnrelatedEvent].append(unrelated_listener)
>>> dispatcher(BaseEvent())
Called base listener
[None]
>>> dispatcher(SubEvent())
Called base listener
Called sub listener
[None, None]
>>> dispatcher(UnrelatedEvent())
Called unrelated listener
[1]
class kotti.events.DispatcherDict(*args, **kwargs)[source]

Base class for dispatchers

class kotti.events.ObjectAfterDelete(object, request=None)[source]

This event is emitted after an object has been deleted from the DB.

Deprecated since version 0.9.

class kotti.events.ObjectDelete(object, request=None)[source]

This event is emitted when an object is deleted from the DB.

class kotti.events.ObjectEvent(object, request=None)[source]

Event related to an object.

class kotti.events.ObjectEventDispatcher(*args, **kwargs)[source]

Dispatches based on both event type and object type.

>>> class BaseObject(object): pass
>>> class SubObject(BaseObject): pass
>>> def base_listener(event):
...     return 'base'
>>> def subobj_insert_listener(event):
...     return 'sub'
>>> def all_listener(event):
...     return 'all'
>>> dispatcher = ObjectEventDispatcher()
>>> dispatcher[(ObjectEvent, BaseObject)].append(base_listener)
>>> dispatcher[(ObjectInsert, SubObject)].append(subobj_insert_listener)
>>> dispatcher[(ObjectEvent, None)].append(all_listener)
>>> dispatcher(ObjectEvent(BaseObject()))
['base', 'all']
>>> dispatcher(ObjectInsert(BaseObject()))
['base', 'all']
>>> dispatcher(ObjectEvent(SubObject()))
['base', 'all']
>>> dispatcher(ObjectInsert(SubObject()))
['base', 'sub', 'all']
class kotti.events.ObjectInsert(object, request=None)[source]

This event is emitted when an object is inserted into the DB.

class kotti.events.ObjectUpdate(object, request=None)[source]

This event is emitted when an object in the DB is updated.

class kotti.events.UserDeleted(object, request=None)[source]

This event is emitted when an user object is deleted from the DB.

kotti.events.cleanup_user_groups(event)[source]

Remove a deleted group from the groups of a user/group and remove all local group entries of it.

Parameters:event (UserDeleted) – event that trigerred this handler.
kotti.events.delete_from_blobstore_providers(event)[source]

This functions checks if a filestore provider is registered and calls its delete method with the corresponding id. This is needed to make sure, that there are no orphans left on the provider’s storage when the corresponding kotti.resources.File, kotti.resources.Image, or any descendants are deleted.

Parameters:event (ObjectDelete) – The event that triggered this handler
kotti.events.delete_orphaned_tags(event)[source]

Delete Tag instances / records when they are not associated with any content.

Parameters:event (ObjectAfterDelete) – event that trigerred this handler.
kotti.events.includeme(config)[source]

Pyramid includeme hook.

Parameters:config (pyramid.config.Configurator) – app config
kotti.events.mapper(class_, local_table=None, properties=None, primary_key=None, non_primary=False, inherits=None, inherit_condition=None, inherit_foreign_keys=None, extension=None, order_by=False, always_refresh=False, version_id_col=None, version_id_generator=None, polymorphic_on=None, _polymorphic_map=None, polymorphic_identity=None, concrete=False, with_polymorphic=None, allow_partial_pks=True, batch=True, column_prefix=None, include_properties=None, exclude_properties=None, passive_updates=True, confirm_deleted_rows=True, eager_defaults=False, legacy_is_orphan=False, _compiled_cache_size=100)

Return a new Mapper object.

This function is typically used behind the scenes via the Declarative extension. When using Declarative, many of the usual mapper() arguments are handled by the Declarative extension itself, including class_, local_table, properties, and inherits. Other options are passed to mapper() using the __mapper_args__ class variable:

class MyClass(Base):
    __tablename__ = 'my_table'
    id = Column(Integer, primary_key=True)
    type = Column(String(50))
    alt = Column("some_alt", Integer)

    __mapper_args__ = {
        'polymorphic_on' : type
    }

Explicit use of mapper() is often referred to as classical mapping. The above declarative example is equivalent in classical form to:

my_table = Table("my_table", metadata,
    Column('id', Integer, primary_key=True),
    Column('type', String(50)),
    Column("some_alt", Integer)
)

class MyClass(object):
    pass

mapper(MyClass, my_table,
    polymorphic_on=my_table.c.type,
    properties={
        'alt':my_table.c.some_alt
    })

See also

Classical Mappings - discussion of direct usage of mapper()

Parameters:
  • class_ – The class to be mapped. When using Declarative, this argument is automatically passed as the declared class itself.
  • local_table – The Table or other selectable to which the class is mapped. May be None if this mapper inherits from another mapper using single-table inheritance. When using Declarative, this argument is automatically passed by the extension, based on what is configured via the __table__ argument or via the Table produced as a result of the __tablename__ and Column arguments present.
  • always_refresh – If True, all query operations for this mapped class will overwrite all data within object instances that already exist within the session, erasing any in-memory changes with whatever information was loaded from the database. Usage of this flag is highly discouraged; as an alternative, see the method Query.populate_existing().
  • allow_partial_pks – Defaults to True. Indicates that a composite primary key with some NULL values should be considered as possibly existing within the database. This affects whether a mapper will assign an incoming row to an existing identity, as well as if Session.merge() will check the database first for a particular primary key value. A “partial primary key” can occur if one has mapped to an OUTER JOIN, for example.
  • batch – Defaults to True, indicating that save operations of multiple entities can be batched together for efficiency. Setting to False indicates that an instance will be fully saved before saving the next instance. This is used in the extremely rare case that a MapperEvents listener requires being called in between individual row persistence operations.
  • column_prefix

    A string which will be prepended to the mapped attribute name when Column objects are automatically assigned as attributes to the mapped class. Does not affect explicitly specified column-based properties.

    See the section Naming All Columns with a Prefix for an example.

  • concrete

    If True, indicates this mapper should use concrete table inheritance with its parent mapper.

    See the section Concrete Table Inheritance for an example.

  • confirm_deleted_rows

    defaults to True; when a DELETE occurs of one more more rows based on specific primary keys, a warning is emitted when the number of rows matched does not equal the number of rows expected. This parameter may be set to False to handle the case where database ON DELETE CASCADE rules may be deleting some of those rows automatically. The warning may be changed to an exception in a future release.

    New in version 0.9.4: - added :paramref:`.mapper.confirm_deleted_rows` as well as conditional matched row checking on delete.

  • eager_defaults

    if True, the ORM will immediately fetch the value of server-generated default values after an INSERT or UPDATE, rather than leaving them as expired to be fetched on next access. This can be used for event schemes where the server-generated values are needed immediately before the flush completes. By default, this scheme will emit an individual SELECT statement per row inserted or updated, which note can add significant performance overhead. However, if the target database supports RETURNING, the default values will be returned inline with the INSERT or UPDATE statement, which can greatly enhance performance for an application that needs frequent access to just-generated server defaults.

    Changed in version 0.9.0: The eager_defaults option can now make use of RETURNING for backends which support it.

  • exclude_properties

    A list or set of string column names to be excluded from mapping.

    See Mapping a Subset of Table Columns for an example.

  • extension – A MapperExtension instance or list of MapperExtension instances which will be applied to all operations by this Mapper. Deprecated. Please see MapperEvents.
  • include_properties

    An inclusive list or set of string column names to map.

    See Mapping a Subset of Table Columns for an example.

  • inherits

    A mapped class or the corresponding Mapper of one indicating a superclass to which this Mapper should inherit from. The mapped class here must be a subclass of the other mapper’s class. When using Declarative, this argument is passed automatically as a result of the natural class hierarchy of the declared classes.

  • inherit_condition – For joined table inheritance, a SQL expression which will define how the two tables are joined; defaults to a natural join between the two tables.
  • inherit_foreign_keys – When inherit_condition is used and the columns present are missing a ForeignKey configuration, this parameter can be used to specify which columns are “foreign”. In most cases can be left as None.
  • legacy_is_orphan

    Boolean, defaults to False. When True, specifies that “legacy” orphan consideration is to be applied to objects mapped by this mapper, which means that a pending (that is, not persistent) object is auto-expunged from an owning Session only when it is de-associated from all parents that specify a delete-orphan cascade towards this mapper. The new default behavior is that the object is auto-expunged when it is de-associated with any of its parents that specify delete-orphan cascade. This behavior is more consistent with that of a persistent object, and allows behavior to be consistent in more scenarios independently of whether or not an orphanable object has been flushed yet or not.

    See the change note and example at The consideration of a “pending” object as an “orphan” has been made more aggressive for more detail on this change.

    New in version 0.8: - the consideration of a pending object as an “orphan” has been modified to more closely match the behavior as that of persistent objects, which is that the object is expunged from the Session as soon as it is de-associated from any of its orphan-enabled parents. Previously, the pending object would be expunged only if de-associated from all of its orphan-enabled parents. The new flag legacy_is_orphan is added to orm.mapper() which re-establishes the legacy behavior.

  • non_primary

    Specify that this Mapper is in addition to the “primary” mapper, that is, the one used for persistence. The Mapper created here may be used for ad-hoc mapping of the class to an alternate selectable, for loading only.

    :paramref:`.Mapper.non_primary` is not an often used option, but is useful in some specific relationship() cases.

  • order_by – A single Column or list of Column objects for which selection operations should use as the default ordering for entities. By default mappers have no pre-defined ordering.
  • passive_updates

    Indicates UPDATE behavior of foreign key columns when a primary key column changes on a joined-table inheritance mapping. Defaults to True.

    When True, it is assumed that ON UPDATE CASCADE is configured on the foreign key in the database, and that the database will handle propagation of an UPDATE from a source column to dependent columns on joined-table rows.

    When False, it is assumed that the database does not enforce referential integrity and will not be issuing its own CASCADE operation for an update. The unit of work process will emit an UPDATE statement for the dependent columns during a primary key change.

    See also

    Mutable Primary Keys / Update Cascades - description of a similar feature as used with relationship()

  • polymorphic_on

    Specifies the column, attribute, or SQL expression used to determine the target class for an incoming row, when inheriting classes are present.

    This value is commonly a Column object that’s present in the mapped Table:

    class Employee(Base):
        __tablename__ = 'employee'
    
        id = Column(Integer, primary_key=True)
        discriminator = Column(String(50))
    
        __mapper_args__ = {
            "polymorphic_on":discriminator,
            "polymorphic_identity":"employee"
        }
    

    It may also be specified as a SQL expression, as in this example where we use the case() construct to provide a conditional approach:

    class Employee(Base):
        __tablename__ = 'employee'
    
        id = Column(Integer, primary_key=True)
        discriminator = Column(String(50))
    
        __mapper_args__ = {
            "polymorphic_on":case([
                (discriminator == "EN", "engineer"),
                (discriminator == "MA", "manager"),
            ], else_="employee"),
            "polymorphic_identity":"employee"
        }
    

    It may also refer to any attribute configured with column_property(), or to the string name of one:

    class Employee(Base):
        __tablename__ = 'employee'
    
        id = Column(Integer, primary_key=True)
        discriminator = Column(String(50))
        employee_type = column_property(
            case([
                (discriminator == "EN", "engineer"),
                (discriminator == "MA", "manager"),
            ], else_="employee")
        )
    
        __mapper_args__ = {
            "polymorphic_on":employee_type,
            "polymorphic_identity":"employee"
        }
    

    Changed in version 0.7.4: polymorphic_on may be specified as a SQL expression, or refer to any attribute configured with column_property(), or to the string name of one.

    When setting polymorphic_on to reference an attribute or expression that’s not present in the locally mapped Table, yet the value of the discriminator should be persisted to the database, the value of the discriminator is not automatically set on new instances; this must be handled by the user, either through manual means or via event listeners. A typical approach to establishing such a listener looks like:

    from sqlalchemy import event
    from sqlalchemy.orm import object_mapper
    
    @event.listens_for(Employee, "init", propagate=True)
    def set_identity(instance, *arg, **kw):
        mapper = object_mapper(instance)
        instance.discriminator = mapper.polymorphic_identity
    

    Where above, we assign the value of polymorphic_identity for the mapped class to the discriminator attribute, thus persisting the value to the discriminator column in the database.

  • polymorphic_identity – Specifies the value which identifies this particular class as returned by the column expression referred to by the polymorphic_on setting. As rows are received, the value corresponding to the polymorphic_on column expression is compared to this value, indicating which subclass should be used for the newly reconstructed object.
  • properties – A dictionary mapping the string names of object attributes to MapperProperty instances, which define the persistence behavior of that attribute. Note that Column objects present in the mapped Table are automatically placed into ColumnProperty instances upon mapping, unless overridden. When using Declarative, this argument is passed automatically, based on all those MapperProperty instances declared in the declared class body.
  • primary_key – A list of Column objects which define the primary key to be used against this mapper’s selectable unit. This is normally simply the primary key of the local_table, but can be overridden here.
  • version_id_col

    A Column that will be used to keep a running version id of rows in the table. This is used to detect concurrent updates or the presence of stale data in a flush. The methodology is to detect if an UPDATE statement does not match the last known version id, a StaleDataError exception is thrown. By default, the column must be of Integer type, unless version_id_generator specifies an alternative version generator.

    See also

    Configuring a Version Counter - discussion of version counting and rationale.

  • version_id_generator

    Define how new version ids should be generated. Defaults to None, which indicates that a simple integer counting scheme be employed. To provide a custom versioning scheme, provide a callable function of the form:

    def generate_version(version):
        return next_version
    

    Alternatively, server-side versioning functions such as triggers, or programmatic versioning schemes outside of the version id generator may be used, by specifying the value False. Please see Server Side Version Counters for a discussion of important points when using this option.

    New in version 0.9.0: version_id_generator supports server-side version number generation.

  • with_polymorphic

    A tuple in the form (<classes>, <selectable>) indicating the default style of “polymorphic” loading, that is, which tables are queried at once. <classes> is any single or list of mappers and/or classes indicating the inherited classes that should be loaded at once. The special value '*' may be used to indicate all descending classes should be loaded immediately. The second tuple argument <selectable> indicates a selectable that will be used to query for multiple classes.

    See also

    Basic Control of Which Tables are Queried - discussion of polymorphic querying techniques.

kotti.events.reset_content_owner(event)[source]

Reset the owner of the content from the deleted owner.

Parameters:event (UserDeleted) – event that trigerred this handler.
kotti.events.set_creation_date(event)[source]

Set creation_date of the object that triggered the event.

Parameters:event (ObjectInsert) – event that trigerred this handler.
kotti.events.set_modification_date(event)[source]

Update modification_date of the object that triggered the event.

Parameters:event (ObjectUpdate) – event that trigerred this handler.
kotti.events.set_owner(event)[source]

Set owner of the object that triggered the event.

Parameters:event (ObjectInsert) – event that trigerred this handler.
class kotti.events.subscribe(evttype=<type 'object'>, objtype=None)[source]

Function decorator to attach the decorated function as a handler for a Kotti event. Example:

from kotti.events import ObjectInsert
from kotti.events import subscribe
from kotti.resurces import Document

@subscribe()
def on_all_events(event):
    # this will be executed on *every* event
    print "Some kind of event occured"

@subscribe(ObjectInsert)
def on_insert(event):
    # this will be executed on every object insert
    context = event.object
    request = event.request
    print "Object insert"

@subscribe(ObjectInsert, Document)
def on_document_insert(event):
    # this will only be executed on object inserts if the object is
    # is an instance of Document
    context = event.object
    request = event.request
    print "Document insert"
kotti.events.wire_sqlalchemy()[source]

Connect SQLAlchemy events to their respective handler function (that fires the corresponding Kotti event).