bookmarks – Bookmark support (XEP-0048)

This module provides support for storing and retrieving bookmarks on the server as per Bookmarks.

Service

class aioxmpp.BookmarkClient(client, **kwargs)[source]

Supports retrieval and storage of bookmarks on the server. It currently only supports Private XML Storage as backend.

There is the general rule never to modify the bookmark instances retrieved from this class (either by get_bookmarks() or as an argument to one of the signals). If you need to modify a bookmark for use with update_bookmark() use copy.copy() to create a copy.

async sync()[source]

Sync the bookmarks between the local representation and the server.

This must be called periodically to assure that the signals are fired.

async get_bookmarks()[source]

Get the stored bookmarks from the server. Causes signals to be fired to reflect the changes.

Returns

a list of bookmarks

async set_bookmarks(bookmarks)[source]

Store the sequence of bookmarks bookmarks.

Causes signals to be fired to reflect the changes.

Note

This should normally not be used. It does not mitigate the race condition between clients concurrently modifying the bookmarks and may lead to data loss. Use add_bookmark(), discard_bookmark() and update_bookmark() instead. This method still has use-cases (modifying the bookmarklist at large, e.g. by syncing the remote store with local data).

The following methods change the bookmark list in a get-modify-set pattern, to mitigate the danger of race conditions and should be used in most circumstances:

async add_bookmark(new_bookmark, *, max_retries=3)[source]

Add a bookmark and check whether it was successfully added to the bookmark list. Already existent bookmarks are not added twice.

Parameters
  • new_bookmark (an instance of Bookmark) – the bookmark to add

  • max_retries (int) – the number of retries if setting the bookmark fails

Raises

RuntimeError – if the bookmark is not in the bookmark list after max_retries retries.

After setting the bookmark it is checked, whether the bookmark is in the online storage, if it is not it is tried again at most max_retries times to add the bookmark. A RuntimeError is raised if the bookmark could not be added successfully after max_retries.

async discard_bookmark(bookmark_to_remove, *, max_retries=3)[source]

Remove a bookmark and check it has been removed.

Parameters
  • bookmark_to_remove (a Bookmark subclass.) – the bookmark to remove

  • max_retries (int) – the number of retries of removing the bookmark fails.

Raises

RuntimeError – if the bookmark is not removed from bookmark list after max_retries retries.

If there are multiple occurrences of the same bookmark exactly one is removed.

This does nothing if the bookmarks does not match an existing bookmark according to bookmark-equality.

After setting the bookmark it is checked, whether the bookmark is removed in the online storage, if it is not it is tried again at most max_retries times to remove the bookmark. A RuntimeError is raised if the bookmark could not be removed successfully after max_retries.

async update_bookmark(old, new, *, max_retries=3)[source]

Update a bookmark and check it was successful.

The bookmark matches an existing bookmark old according to bookmark equalitiy and replaces it by new. The bookmark new is added if no bookmark matching old exists.

Parameters
  • old – the bookmark to replace

  • new – the replacement bookmark

  • max_retries (int) – the number of retries of removing the bookmark fails.

Raises

RuntimeError – if the bookmark is not in the bookmark list after max_retries retries.

After replacing the bookmark it is checked, whether the bookmark new is in the online storage, if it is not it is tried again at most max_retries times to replace the bookmark. A RuntimeError is raised if the bookmark could not be replaced successfully after max_retries.

Note

Do not modify a bookmark retrieved from the signals or from get_bookmarks() to obtain the bookmark new, this will lead to data corruption as they are passed by reference. Instead use copy.copy() and modify the copy.

The following signals are provided that allow tracking the changes to the bookmark list:

signal on_bookmark_added(added_bookmark)

Fires when a new bookmark is added.

signal on_bookmark_removed(removed_bookmark)

Fires when a bookmark is removed.

signal on_bookmark_changed(old_bookmark, new_bookmark)

Fires when a bookmark is changed.

Note

A heuristic is used to determine the change of bookmarks and the reported changes may not directly reflect the used methods, but it will always be possible to construct the list of bookmarks from the events. For example, when using update_bookmark() to change the JID of a Conference bookmark a removed and a added signal will fire.

Note

The bookmark protocol is prone to race conditions if several clients access it concurrently. Be careful to use a get-modify-set pattern or the provided highlevel interface.

Note

Some other clients extend the bookmark format. For now those extensions are silently dropped by our XSOs, and therefore are lost, when changing the bookmarks with aioxmpp. This is considered a bug to be fixed in the future.

XSOs

All bookmark types must adhere to the following ABC:

class aioxmpp.bookmarks.Bookmark(*args, **kwargs)[source]

A bookmark XSO abstract base class.

Every XSO class registered as child of Storage must be a Bookmark subclass.

Bookmarks must provide the following interface:

primary

Return the primary category of the bookmark.

The internal structure of the category is opaque to the code using it; only equality and hashing must be provided and operate by value. It is recommended that this be either a single datum (e.g. a string or JID) or a tuple of data items.

Together with the type and secondary this must fully determine the value of the bookmark.

This is used in the computation of the change signals. Bookmarks with different type or primary keys cannot be identified as changed from/to one another.

secondary

Return the tuple of secondary categories of the bookmark.

Together with the type and primary they must fully determine the value of the bookmark.

This is used in the computation of the change signals. The categories in the tuple are ordered in decreasing precedence, when calculating which bookmarks have changed the ones which mismatch in the category with the lowest precedence are grouped together.

The length of the tuple must be the same for all bookmarks of a type.

name

The human-readable label or description of the bookmark.

Equality is defined in terms of those properties:

__eq__(other)[source]

Compare for equality by value and type.

The value of a bookmark must be fully determined by the values of the primary and secondary properties.

This is used for generating the bookmark list change signals and for the get-modify-set methods.

It is highly recommended not to redefine __eq__() in a subclass, if you do so make sure that the following axiom relating __eq__(), primary and secondary holds:

(type(a) == type(b) and
 a.primary == b.primary and
 a.secondary == b.secondary)

if and only if:

a == b

Otherwise the generation of bookmark change signals is not guaranteed to be correct.

The following XSOs are used to represent an manipulate bookmark lists.

class aioxmpp.bookmarks.Conference(*args, **kwargs)[source]

An bookmark for a groupchat.

name

The name of the bookmark.

jid

The jid under which the groupchat is accessible.

autojoin

Whether to join automatically, when the client starts.

nick

The nick to use in the groupchat.

password

The password used to access the groupchat.

class aioxmpp.bookmarks.URL(*args, **kwargs)[source]

An URL bookmark.

name

The name of the bookmark.

url

The URL the bookmark saves.

To register custom bookmark classes use:

aioxmpp.bookmarks.as_bookmark_class(xso_class)[source]

Decorator to register xso_class as a custom bookmark class.

This is necessary to store and retrieve such bookmarks. The registered class must be a subclass of the abstract base class Bookmark.

Raises

TypeError – if xso_class is not a subclass of Bookmark.

The following is used internally as the XSO container for bookmarks.

class aioxmpp.bookmarks.Storage(*args, **kwargs)[source]

The container for storing bookmarks.

bookmarks

A XSOList of bookmarks.

Notes on usage

It is highly recommended to interact with the bookmark client via the provided signals and the get-modify-set methods add_bookmark(), discard_bookmark() and update_bookmark(). Using set_bookmarks() directly is error prone and might cause data loss due to race conditions.