v1.3.5
This commit is contained in:
@@ -0,0 +1,286 @@
|
||||
########################################################################
|
||||
# File name: xso.py
|
||||
# This file is part of: aioxmpp
|
||||
#
|
||||
# LICENSE
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this program. If not, see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
########################################################################
|
||||
import copy
|
||||
|
||||
import aioxmpp.xso as xso
|
||||
|
||||
from aioxmpp.utils import namespaces, magicmethod
|
||||
|
||||
namespaces.xep0059_rsm = "http://jabber.org/protocol/rsm"
|
||||
|
||||
|
||||
class _RangeLimitBase(xso.XSO):
|
||||
value = xso.Text(default=None)
|
||||
|
||||
def __init__(self, value=None):
|
||||
super().__init__()
|
||||
self.value = value
|
||||
|
||||
|
||||
class After(_RangeLimitBase):
|
||||
"""
|
||||
.. attribute:: value
|
||||
|
||||
Identifier of the element which serves as a range limit for the query.
|
||||
"""
|
||||
|
||||
TAG = namespaces.xep0059_rsm, "after"
|
||||
|
||||
|
||||
class Before(_RangeLimitBase):
|
||||
"""
|
||||
.. attribute:: value
|
||||
|
||||
Identifier of the element which serves as a range limit for the query.
|
||||
"""
|
||||
|
||||
TAG = namespaces.xep0059_rsm, "before"
|
||||
|
||||
|
||||
class First(_RangeLimitBase):
|
||||
"""
|
||||
.. attribute:: value
|
||||
|
||||
Identifier of the first element in the result set.
|
||||
|
||||
.. attribute:: index
|
||||
|
||||
Approximate index of the first element in the result set.
|
||||
|
||||
Can be used with :attr:`ResultSetMetadata.index` and
|
||||
:meth:`ResultSetMetadata.fetch_page` to approximately re-retrieve the
|
||||
page.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:meth:`~ResultSetMetadata.fetch_page`
|
||||
for hints on caveats and inaccuracies
|
||||
"""
|
||||
|
||||
TAG = namespaces.xep0059_rsm, "first"
|
||||
|
||||
index = xso.Attr(
|
||||
"index",
|
||||
type_=xso.Integer(),
|
||||
default=None,
|
||||
)
|
||||
|
||||
|
||||
class Last(_RangeLimitBase):
|
||||
"""
|
||||
.. attribute:: value
|
||||
|
||||
Identifier of the last element in the result set.
|
||||
|
||||
"""
|
||||
|
||||
TAG = namespaces.xep0059_rsm, "last"
|
||||
|
||||
|
||||
class ResultSetMetadata(xso.XSO):
|
||||
"""
|
||||
Represent the result set or query metadata.
|
||||
|
||||
For requests, the following attributes are relevant:
|
||||
|
||||
.. attribute:: after
|
||||
|
||||
Either :data:`None` or a :class:`After` object.
|
||||
|
||||
Generally mutually exclusive with :attr:`index`.
|
||||
|
||||
.. attribute:: before
|
||||
|
||||
Either :data:`None` or a :class:`Before` object.
|
||||
|
||||
Generally mutually exclusive with :attr:`index`.
|
||||
|
||||
.. attribute:: index
|
||||
|
||||
The index of the first result to return, or :data:`None`.
|
||||
|
||||
Generally mutually exclusive with :attr:`after` and :attr:`before`.
|
||||
|
||||
.. attribute:: max
|
||||
|
||||
The maximum number of items to return or :data:`None`.
|
||||
|
||||
Setting :attr:`max` to zero will make the peer return a
|
||||
:class:`ResultSetMetadata` with the total number of items in the
|
||||
:attr:`count` field.
|
||||
|
||||
These methods are useful when constructing queries:
|
||||
|
||||
.. automethod:: fetch_page
|
||||
|
||||
.. automethod:: limit
|
||||
|
||||
.. automethod:: last_page
|
||||
|
||||
For responses, the following attributes are relevant:
|
||||
|
||||
.. attribute:: first
|
||||
|
||||
Either :data:`None` or a :class:`First` object.
|
||||
|
||||
.. attribute:: last
|
||||
|
||||
Either :data:`None` or a :class:`Last` object.
|
||||
|
||||
.. attribute:: count
|
||||
|
||||
Either :data:`None` or the number of elements in the result set.
|
||||
|
||||
If this is a response to a query with :attr:`max` set to zero, this is
|
||||
the total number of elements in the queried data.
|
||||
|
||||
These methods are useful to construct a new request from a previous
|
||||
response:
|
||||
|
||||
.. automethod:: next_page
|
||||
|
||||
.. automethod:: previous_page
|
||||
"""
|
||||
|
||||
TAG = namespaces.xep0059_rsm, "set"
|
||||
|
||||
after = xso.Child([After])
|
||||
|
||||
before = xso.Child([Before])
|
||||
|
||||
first = xso.Child([First])
|
||||
|
||||
last = xso.Child([Last])
|
||||
|
||||
count = xso.ChildText(
|
||||
(namespaces.xep0059_rsm, "count"),
|
||||
type_=xso.Integer(),
|
||||
default=None,
|
||||
)
|
||||
|
||||
max_ = xso.ChildText(
|
||||
(namespaces.xep0059_rsm, "max"),
|
||||
type_=xso.Integer(),
|
||||
default=None,
|
||||
)
|
||||
|
||||
index = xso.ChildText(
|
||||
(namespaces.xep0059_rsm, "index"),
|
||||
type_=xso.Integer(),
|
||||
default=None,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def fetch_page(cls, index, max_=None):
|
||||
"""
|
||||
Return a query set which requests a specific page.
|
||||
|
||||
:param index: Index of the first element of the page to fetch.
|
||||
:type index: :class:`int`
|
||||
:param max_: Maximum number of elements to fetch
|
||||
:type max_: :class:`int` or :data:`None`
|
||||
:rtype: :class:`ResultSetMetadata`
|
||||
:return: A new request set up to request a page starting with the
|
||||
element indexed by `index`.
|
||||
|
||||
.. note::
|
||||
|
||||
This way of retrieving items may be approximate. See :xep:`59` and
|
||||
the embedding protocol for which RSM is used for specifics.
|
||||
"""
|
||||
|
||||
result = cls()
|
||||
result.index = index
|
||||
result.max_ = max_
|
||||
return result
|
||||
|
||||
@magicmethod
|
||||
def limit(self, max_):
|
||||
"""
|
||||
Limit the result set to a given number of items.
|
||||
|
||||
:param max_: Maximum number of items to return.
|
||||
:type max_: :class:`int` or :data:`None`
|
||||
:rtype: :class:`ResultSetMetadata`
|
||||
:return: A new request set up to request at most `max_` items.
|
||||
|
||||
This method can be called on the class and on objects. When called on
|
||||
objects, it returns a copy of the object with :attr:`max_` set
|
||||
accordingly. When called on the class, it creates a fresh object with
|
||||
:attr:`max_` set accordingly.
|
||||
"""
|
||||
|
||||
if isinstance(self, type):
|
||||
result = self()
|
||||
else:
|
||||
result = copy.deepcopy(self)
|
||||
result.max_ = max_
|
||||
return result
|
||||
|
||||
def next_page(self, max_=None):
|
||||
"""
|
||||
Return a query set which requests the page after this response.
|
||||
|
||||
:param max_: Maximum number of items to return.
|
||||
:type max_: :class:`int` or :data:`None`
|
||||
:rtype: :class:`ResultSetMetadata`
|
||||
:return: A new request set up to request the next page.
|
||||
|
||||
Must be called on a result set which has :attr:`last` set.
|
||||
"""
|
||||
|
||||
result = type(self)()
|
||||
result.after = After(self.last.value)
|
||||
result.max_ = max_
|
||||
return result
|
||||
|
||||
def previous_page(self, max_=None):
|
||||
"""
|
||||
Return a query set which requests the page before this response.
|
||||
|
||||
:param max_: Maximum number of items to return.
|
||||
:type max_: :class:`int` or :data:`None`
|
||||
:rtype: :class:`ResultSetMetadata`
|
||||
:return: A new request set up to request the previous page.
|
||||
|
||||
Must be called on a result set which has :attr:`first` set.
|
||||
"""
|
||||
|
||||
result = type(self)()
|
||||
result.before = Before(self.first.value)
|
||||
result.max_ = max_
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def last_page(self_or_cls, max_=None):
|
||||
"""
|
||||
Return a query set which requests the last page.
|
||||
|
||||
:param max_: Maximum number of items to return.
|
||||
:type max_: :class:`int` or :data:`None`
|
||||
:rtype: :class:`ResultSetMetadata`
|
||||
:return: A new request set up to request the last page.
|
||||
"""
|
||||
result = self_or_cls()
|
||||
result.before = Before()
|
||||
result.max_ = max_
|
||||
return result
|
||||
Reference in New Issue
Block a user