pending.rst 3.73 KB
Newer Older
Barry Warsaw's avatar
Barry Warsaw committed
1
====================
2 3 4 5 6 7 8 9
The pending database
====================

The pending database is where various types of events which need confirmation
are stored.  These can include email address registration events, held
messages (but only for user confirmation), auto-approvals, and probe bounces.
This is not where messages held for administrator approval are kept.

Barry Warsaw's avatar
Barry Warsaw committed
10
In order to pend an event, you first need a pending database.
11

12
    >>> from mailman.interfaces.pending import IPendings
13 14
    >>> from zope.component import getUtility
    >>> pendingdb = getUtility(IPendings)
15

16 17
There are nothing in the pendings database.

18
    >>> pendingdb.count()
19 20
    0

21 22
The pending database can add any ``IPendable`` to the database, returning a
token that can be used in urls and such.
Barry Warsaw's avatar
Barry Warsaw committed
23
::
24

Barry Warsaw's avatar
Barry Warsaw committed
25
    >>> from zope.interface import implementer
26
    >>> from mailman.interfaces.pending import IPendable
Barry Warsaw's avatar
Barry Warsaw committed
27 28
    >>> @implementer(IPendable)
    ... class SimplePendable(dict):
29
    ...     PEND_TYPE = 'subscription'
Barry Warsaw's avatar
Barry Warsaw committed
30

31 32
    >>> subscription = SimplePendable(
    ...     address='aperson@example.com',
33
    ...     display_name='Anne Person',
34 35 36 37 38 39
    ...     language='en',
    ...     password='xyz')
    >>> token = pendingdb.add(subscription)
    >>> len(token)
    40

40 41
There's exactly one entry in the pendings database now.

42
    >>> pendingdb.count()
43 44
    1

Barry Warsaw's avatar
Barry Warsaw committed
45
You can *confirm* the pending, which means returning the `IPendable` structure
46 47
(as a dictionary) from the database that matches the token.

Barry Warsaw's avatar
Barry Warsaw committed
48 49 50 51
All `IPendable` classes have a `PEND_TYPE` attribute which must be a string.
It is used to identify and query pendables in the database, and will be
returned as the `type` key in the dictionary.  Thus `type` is a reserved key
and pendables may not otherwise set it.
52 53

If the token isn't in the database, None is returned.
54

Barry Warsaw's avatar
Barry Warsaw committed
55
    >>> pendable = pendingdb.confirm(b'missing')
56
    >>> print(pendable)
57 58
    None
    >>> pendable = pendingdb.confirm(token)
59
    >>> from mailman.testing.documentation import dump_msgdata    
Barry Warsaw's avatar
Barry Warsaw committed
60
    >>> dump_msgdata(pendable)
61 62 63 64 65
    address     : aperson@example.com
    display_name: Anne Person
    language    : en
    password    : xyz
    type        : subscription
66 67 68

After confirmation, the token is no longer in the database.

69
    >>> print(pendingdb.confirm(token))
70 71 72
    None

There are a few other things you can do with the pending database.  When you
73
confirm a token, you can leave it in the database, or in other words, not
74 75 76 77 78 79 80 81 82
expunge it.

    >>> event_1 = SimplePendable(type='one')
    >>> token_1 = pendingdb.add(event_1)
    >>> event_2 = SimplePendable(type='two')
    >>> token_2 = pendingdb.add(event_2)
    >>> event_3 = SimplePendable(type='three')
    >>> token_3 = pendingdb.add(event_3)
    >>> pendable = pendingdb.confirm(token_1, expunge=False)
Barry Warsaw's avatar
Barry Warsaw committed
83 84
    >>> dump_msgdata(pendable)
    type: one
85
    >>> pendable = pendingdb.confirm(token_1, expunge=True)
Barry Warsaw's avatar
Barry Warsaw committed
86 87
    >>> dump_msgdata(pendable)
    type: one
88
    >>> print(pendingdb.confirm(token_1))
89 90
    None

Barry Warsaw's avatar
Barry Warsaw committed
91 92 93 94 95 96 97 98 99 100 101 102
You can iterate over all the pendings in the database.

    >>> pendables = list(pendingdb)
    >>> def sort_key(item):
    ...     token, pendable = item
    ...     return pendable['type']
    >>> sorted_pendables = sorted(pendables, key=sort_key)
    >>> for token, pendable in sorted_pendables:
    ...     print(pendable['type'])
    three
    two

103 104 105 106 107 108 109 110 111 112 113
An event can be given a lifetime when it is pended, otherwise it just uses a
default lifetime.

    >>> from datetime import timedelta
    >>> yesterday = timedelta(days=-1)
    >>> event_4 = SimplePendable(type='four')
    >>> token_4 = pendingdb.add(event_4, lifetime=yesterday)

Every once in a while the pending database is cleared of old records.

    >>> pendingdb.evict()
114
    >>> print(pendingdb.confirm(token_4))
115 116
    None
    >>> pendable = pendingdb.confirm(token_2)
Barry Warsaw's avatar
Barry Warsaw committed
117 118
    >>> dump_msgdata(pendable)
    type: two