arxiv.submission.domain.event.base module

Provides the base event class.

class arxiv.submission.domain.event.base.Event(creator, created=None, proxy=None, client=None, submission_id=None, committed=False, before=None, after=None, event_type=<factory>, event_version=<factory>)[source]

Bases: object

Base class for submission-related events/commands.

An event represents a change to a domain.submission.Submission. Rather than changing submissions directly, an application should create (and store) events. Each event class must inherit from this base class, extend it with whatever data is needed for the event, and define methods for validation and projection (changing a submission):

  • validate(self, submission: Submission) -> None should raise InvalidEvent if the event instance has invalid data.

  • project(self, submission: Submission) -> Submission should perform changes to the domain.submission.Submission and return it.

An event class also provides a hook for doing things automatically when the submission changes. To register a function that gets called when an event is committed, use the bind() method.

after = None

The state of the submission after the event.

apply(submission=None)[source]

Apply the projection for this Event instance.

Return type

Submission

before = None

The state of the submission prior to the event.

classmethod bind(condition=None)[source]

Generate a decorator to bind a callback to an event type.

To register a function that will be called whenever an event is committed, decorate it like so:

@MyEvent.bind()
def say_hello(event: MyEvent, before: Submission,
              after: Submission, creator: Agent) -> Iterable[Event]:
    yield SomeOtherEvent(...)

The callback function will be passed the event that triggered it, the state of the submission before and after the triggering event was applied, and a System agent that can be used as the creator of subsequent events. It should return an iterable of other Event instances, either by yielding them, or by returning an iterable object of some kind.

By default, callbacks will only be called if the creator of the trigger event is not a System instance. This makes it less easy to define infinite chains of callbacks. You can pass a custom condition to the decorator, for example:

def jill_created_an_event(event: MyEvent, before: Submission,
                          after: Submission) -> bool:
    return event.creator.username == 'jill'


@MyEvent.bind(jill_created_an_event)
def say_hi(event: MyEvent, before: Submission,
           after: Submission, creator: Agent) -> Iterable[Event]:
    yield SomeOtherEvent(...)

Note that the condition signature is (event: MyEvent, before: Submission, after: Submission) -> bool.

Parameters

condition (Callable) – A callable with the signature (event: Event, before: Submission, after: Submission) -> bool. If this callable returns True, the callback will be triggered when the event to which it is bound is saved. The default condition is that the event was not created by System

Return type

Callable[[Callable], Callable]

Returns

Callable – Decorator for a callback function, with signature (event: Event, before: Submission, after: Submission, creator: Agent = System(...)) -> Iterable[Event].

client = None

The client through which the creator performed the operation.

If the creator was directly involved in the operation, this property should be the client that facilitated the operation.

commit(store)[source]

Persist this event instance using an injected store method.

Parameters

save (Callable) – Should have signature (*Event, submission_id: int) -> Tuple[Event, Submission].

Return type

Tuple[Submission, Iterable[Event]]

Returns

  • Submission – State of the submission after storage. Some changes may have been made to ensure consistency with the underlying datastore.

  • list – Items are Event instances.

committed = False

Indicates whether the event has been committed to the database.

This should generally not be set from outside this package.

created = None

The timestamp when the event was originally committed.

creator = None

The agent responsible for the operation represented by this event.

This is not necessarily the creator of the submission.

event_id

Unique ID for this event.

Return type

str

classmethod get_event_type()[source]

Get the name of the event type.

Return type

str

static get_event_version()[source]
Return type

str

static get_id(created, event_type, creator)[source]
Return type

str

proxy = None

The agent who facilitated the operation on behalf of the creator.

This may be an API client, or another user who has been designated as a proxy. Note that proxy implies that the creator was not directly involved.

submission_id = None

The primary identifier of the submission being operated upon.

This is defined as optional to support creation events, and to facilitate chaining of events with creation events in the same transaction.

class arxiv.submission.domain.event.base.EventType[source]

Bases: type

Metaclass for Event.

arxiv.submission.domain.event.base.event_factory(**data)[source]

Generate an Event instance from raw EventData.

Parameters
  • event_type (str) – Should be the name of a Event subclass.

  • data (kwargs) – Keyword parameters passed to the event constructor.

Return type

Event

Returns

Event – An instance of an Event subclass.