Changelog¶
Version 0.10¶
New XEP implementations¶
aioxmpp.version
(XEP-0092): Support for publishing the software version of the client and accessing version information of other entities.aioxmpp.mdr
(XEP-0184): A tracking implementation (seeaioxmpp.tracking
) which uses XEP-0184 Message Delivery Receipts.aioxmpp.ibr
(XEP-0077): Support for registering new accounts, changing the password and deleting an account (via the non-data-form flow). Contributed by Sergio Alemany.aioxmpp.httpupload
(XEP-0363): Support for requesting an upload slot (the actual uploading via HTTP is out of scope for this project, but look at theupload.py
example which usesaiohttp
).aioxmpp.misc
gained support for:- Be robust against invalid IQ stanzas.
New major features¶
Improved timeout handling: Before 0.10, there was an extremely simple timeout logic: the
aioxmpp.stream.StanzaStream
would send a ping of some kind and expect a reply to that ping back within a certain timeframe. If no reply to that ping was received within that timeframe, the stream would be considered dead and it would be aborted.The new timeout handling does not require that a reply is received; instead, the stream is considered live as long as data is coming in, irrespective of the latency. Only if no data has been received for a configurable time (
aioxmpp.streams.StanzaStream.soft_timeout
), a ping is sent. New data has to be received withinaioxmpp.streams.StanzaStream.round_trip_time
after the ping has been sent (but it does not need to necessarily be a reply to that ping).Strict Ordering of Stanzas: It is now possible to make use of the ordering guarantee on XMPP XML streams for IQ handling. For this to work, normal functions returning an awaitable are used instead of coroutines. This is needed to prevent any possible ambiguity as to when coroutines handling IQ requests are scheduled with respect to other IQ handler coroutines and other stanza processing.
The following changes make this possible:
- Support for passing a function returning an awaitable as callback to
aioxmpp.stream.StanzaStream.register_iq_request_coro()
. In contrast to coroutines, a callback function can exploit the strong ordering guarantee of the XMPP XML Stream. - Support for passing a callback function to
aioxmpp.stream.StanzaStream.send()
which is invoked on responses to an IQ request sent throughsend()
. In contrast to awaiting the result ofsend()
, the callback can exploit the strong ordering guarantee of the XMPP XML Stream. - The
aioxmpp.service.iq_handler()
decorator function now allows normal functions to be decorated (in addition to coroutine functions). - Add cb argument to
aioxmpp.protocol.send_and_wait_for()
to allow to act synchronously on the response. This is needed for transactional things like stream management.
- Support for passing a function returning an awaitable as callback to
Consistent Member Argument for
on_message()
: Theaioxmpp.muc.Room.on_message()
now always have a non-None
member argument.Please see the documentation of the event for some caveats of this member argument as well as the rationale.
Note
Prosody ≤ 0.9.12 (for the 0.9 branch) and ≤ 0.10.0 (for the 0.10 branch) are affected by Prosody issue #1053.
This means that by itself,
aioxmpp.muc.Room
cannot detect that history replay is over and will stay in the history replay state forever. However, two workarounds help with that: once the first live message is or the first presence update is received, theRoom
will assume a buggy server and transition toACTIVE
state.These workarounds are not perfect; in particular it is possible that the first message workaround is defeated if a client includes a
<delay/>
into that message.Until either a fixed version of Prosody is used or the workarounds take effect, the following issues will be observed:
aioxmpp.muc.Occupant.uid
will not be useful in any way (but also not harmful, security-wise).aioxmpp.muc.Room.on_message()
may receive member arguments which are not part of theaioxmpp.muc.Room.members
and which may also lack other information (such as bare JIDs).aioxmpp.muc.Room.muc_state
will not reach theaioxmpp.muc.RoomState.ACTIVE
state.
Applications which support e.g. XEP-0085 (Chat State Notifications) may use a chat state notification (for example, active or inactive) to cause a message to be received from the MUC, forcing the transition to
ACTIVE
state.This comes together with the new
aioxmpp.muc.Room.muc_state
attribute which indicates the current local state of the room. Seeaioxmpp.muc.RoomState
.Recognizability of Occupants across Rejoins/Reboots: The
aioxmpp.im.conversation.AbstractConversationMember.uid
attribute holds a (reasonably) unique string indentifying the occupant. If theuid
of two member objects compares equal, an application can be reasonably sure that the two members refer to the same identity. If the UIDs of two members are not equal, the application can be sure that the two members do not have the same identity. This can be used for permission checks e.g. in the context of Last Message Correction or similar applications.Improved handling of pre-connection stanzas: The API for sending stanzas now lives at the
aioxmpp.Client
asaioxmpp.Client.send()
andaioxmpp.Client.enqueue()
. In addition,send()
-ing a stanza will block until the client has a valid stream. Attempting toenqueue()
a stanza while the client does not have a valid stream raises aConnectionError
.A valid stream is either an actually connected stream or a suspended stream with support for XEP-0198 resumption.
This prevents attempting to send stanzas over a stream which is not ready yet. In the worst case, this can cause various errors if the stanza is then effectively sent before resource binding has taken place.
Invitations:
aioxmpp.muc
now supports sending invitations (viaaioxmpp.muc.Room.invite()
) and receiving invitations (viaaioxmpp.MUCClient.on_muc_invitation()
). The interface foraioxmpp.im.conversation.AbstractConversation.invite()
has been reworked.Service Members:
aioxmpp.im.conversation.AbstractConversation
s can now have aaioxmpp.im.conversation.AbstractConversationMember
representing the conversation service itself inside that conversation (see Service Member).The primary use is to represent messages originating from a XEP-0045 room itself (on the protocol level, those messages have the bare JID of the room as
from
).The service member of each conversation (if it is defined), is never contained in the
aioxmpp.im.conversation.AbstractConversation.members
and available atservice_member
.Better Child Element Enumerations: The
aioxmpp.xso.XSOEnumMixin
is a mixin which can be used withenum.Enum
to create an enumeration where each enumeration member has its own XSO class.This is useful for e.g. error conditions where a defined set of children exists, but
aioxmpp.xso.ChildTag
with an enumeration isn’t appropriate because the child XSOs may have additional data. Refer to the docs for more details.Error Condition Data: The representation of XMPP error conditions on the XSO level has been reworked. This is to support error conditions which have a data payload (most importantly
aioxmpp.ErrorCondition.GONE
).The entire error condition XSO is now available on both
aioxmpp.errors.XMPPError
(ascondition_obj
) exceptions andaioxmpp.stanza.Error
payloads (ascondition_obj
).For this change, the following subchanges are relevant:
- The constructors of
aioxmpp.stanza.Error
andaioxmpp.errors.XMPPError
(and subclasses) now accept either a member of theaioxmpp.ErrorCondition
enumeration or an instance of the respective XSO. This allows to attach additional data to error conditions which support this, such as theaioxmpp.ErrorCondition.GONE
error. aioxmpp.errors.XMPPError.application_defined_condition
is now attached toaioxmpp.stanza.Error.application_condition
whenaioxmpp.stanza.Error.from_exception()
is used.
Please see the breaking changes below for how to handle the transition from namespace-name tuples to enumeration members.
- The constructors of
New examples¶
upload.py
: usesaioxmpp.httpupload
andaiohttp
to upload any file to an HTTP service offered by the XMPP server, if the server supports the feature.register.py
: Register an account at an XMPP server which offers classic XEP-0077 In-Band Registration.
Breaking changes¶
Converted stanza and stream error conditions to enumerations based on
aioxmpp.xso.XSOEnumMixin
.This is similar to the transition in the 0.7 release. The following attributes, methods and constructors now expect enumeration members instead of tuples:
aioxmpp.stanza.Error
, the condition argumentaioxmpp.stanza.Error.condition
aioxmpp.nonza.StreamError.condition
aioxmpp.errors.XMPPError
(and its subclasses), the condition argumentaioxmpp.errors.XMPPError.condition
To simplify the transition, the enumerations will compare equal to the equivalent tuples until the release of 1.0.
The affected code locations can be found with the
utils/find-v0.10-type-transition.sh
script. It finds all tuples which form error conditions. In addition,DeprecationWarning
type warnings are emitted in the following cases:- Enumeration member compared to tuple
- Tuple assigned to attribute or passed to method where an enumeration member is expected
To make those warnings fatal, use the following code at the start of your application:
import warnings warnings.filterwarnings( # make the warnings fatal "error", # match only deprecation warnings category=DeprecationWarning, # match only warnings concerning the ErrorCondition and # StreamErrorCondition enumerations message=".+(Stream)?ErrorCondition", )
Split
aioxmpp.xso.AbstractType
intoaioxmpp.xso.AbstractCDataType
(for which theaioxmpp.xso.AbstractType
was originally intended) andaioxmpp.xso.AbstractElementType
(which it has become through organic growth). This split serves the maintainability of the code and offers opportunities for better error detection.aioxmpp.BookmarkService.get_bookmarks()
now returns a list instead of aaioxmpp.bookmarks.Storage
andaioxmpp.BookmarkService.set_bookmarks()
now accepts a list. The list returned by the get method and its elements must not be modified.Make
aioxmpp.muc.Room.send_message_tracked()
a normal method instead of a coroutine (it was never intended to be a coroutine).Specify
aioxmpp.im.conversation.AbstractConversation.on_enter()
andon_failure()
events and implement emission of those for the existing conversation implementations.Specify that Conversation Services must provide a non-coroutine method to start a conversation. Asynchronous parts have to happen in the background. To await the completion of the initialisation of the conversation, use
aioxmpp.callbacks.first_signal()
as described inaioxmpp.im.conversation.AbstractConversation.on_enter()
.Make
aioxmpp.im.p2p.Service.get_conversation()
a normal method.aioxmpp.muc.Room.send_message()
is not a coroutine anymore, but it returns an awaitable; this means that in most cases, this should not break.send_message()
was a coroutine by accident; it should never have been that, according to the specification inaioxmpp.im.conversation.AbstractConversation.send_message()
.Since multiple
<delay/>
elements can occur in a stanza,aioxmpp.Message.xep0203_delay
is now a list instead of a singleaioxmpp.misc.Delay
object. Sorry for the inconvenience.The type of the value of
aioxmpp.xso.Collector
descriptors was changed fromlist
tolxml.etree.Element
.Assignment to
aioxmpp.xso.Collector
descriptors is now forbidden. Instead, you should usesome_xso.collector_attr[:] = items
or a similar syntax.aioxmpp.muc.Room.on_enter()
does not receive any arguments anymore to comply with the updatedaioxmpp.im.AbstractConversation
spec. Theaioxmpp.muc.Room.on_muc_enter()
event provides the argumentson_enter()
received before and fires right afteron_enter()
.As a workaround (if you need the arguments), you can test whether the
on_muc_enter()
exists on aRoom
. If it does, connect to it, otherwise connect toon_enter()
.If you don’t need the arguments, make your
on_enter()
handlers accept*args
.aioxmpp.AvatarService.get_avatar_metadata()
now returns a list instead of a mapping from MIME types to lists of descriptors.Replaced the
aioxmpp.stream.StanzaStream.ping_interval
andping_opportunistic_interval
attributes with a new ping implementation.It is described in the Timeouts / Stream Aliveness checks section in
aioxmpp.stream
.aioxmpp.connector.BaseConnector.connect()
implementations are expected to set theaioxmpp.protocol.XMLStream.deadtime_hard_limit
to the value of their negotiation_timeout argument and use this mechanism to handle any stream-level timeouts.aioxmpp.muc.Occupant.direct_jid
is now always a bare jid. This implies that the resource part of a jid passed in by a muc member item now is always ignored. Passing a full jid to the constructor now raises aValueError
.
Minor features and bug fixes¶
Make
aioopenssl
a mandatory dependency.Replace
orderedset
withsortedcollections
.Emit
aioxmpp.im.conversation.AbstractConversation.on_message()
for MUC messages sent viasend_message_tracked()
.Add
tracker
argument toaioxmpp.im.conversation.AbstractConversation.on_message()
. It carries aaioxmpp.tracking.MessageTracker
for sent messages (including those sent by other resources of the account in the same conversation).Fix (harmless) traceback in logs which could occur when using
aioxmpp.muc.Room.send_message_tracked()
.Fix
aioxmpp.service.is_depsignal_handler()
andis_attrsignal_handler()
when used withdefer=True
.You can now register custom bookmark classes with
aioxmpp.bookmarks.as_bookmark_class()
. The bookmark classes must subclass the ABCaioxmpp.bookmarks.Bookmark
.Implement
aioxmpp.callbacks.first_signal()
.Fixed duplicate emission of
on_message()
events for untracked (sent throughaioxmpp.muc.Room.send_message()
) MUC messages.Re-read the nameserver config if
dns.resolver.NoNameservers
is raised during a query using the thread-local global resolver (the default).The resolver config is only reloaded up to once for each query; any further errors are treated as authoritative / related to the zone.
Add
aioxmpp.protocol.XMLStream.mute()
context manager to suppress debug logging of stream contents.Exclude authentication information sent during SASL.
The new
aioxmpp.structs.LanguageMap.any()
method allows to obtain an arbitrary element from the language map.New erroneous_as_absent argument to
aioxmpp.xso.Attr
,Text
andChildText
. See the documentation ofAttr
for details.Treat absent
@type
XML attribute on message stanzas asaioxmpp.MessageType.NORMAL
, as specified in RFC 6121, section 5.2.2.Treat empty
<show/>
XML child on presence stanzas like absent<show/>
. This is not legal as per RFC 6120, but apparently there are some broken implementations out there.Not having this workaround leads to being unable to receive presence stanzas from those entities, which is rather unfortunate.
aioxmpp.service.iq_handler()
now checks that its payload class is in fact registered as IQ payload and raisesValueError
if not.aioxmpp.node.discover_connectors()
will now continue of only one of the two SRV lookups fails with the DNSPythondns.resolver.NoNameservers
exception; this case might still indicate a configuration issue (so we log it), but since we actually got a useful result on the other query, we can still continue.aioxmpp.node.discover_connectors()
now uses a proper fully-qualified domain name (including the trailing dot) for DNS queries to avoid improper fallback to locally configured search domains.Ignore presence stanzas from the bare JID of a joined MUC, even if they contain a MUC user tag. A functional MUC should never emit this.
We now will always attempt STARTTLS negotiation if
aioxmpp.security_layer.SecurityLayer.tls_required
is true, even if the server does not advertise a STARTTLS stream feature. This is because we have nothing to lose, and it may mitigate some types of STARTTLS stripping attacks.Compatibility fixes for ejabberd (cf. ejabberd#2287 and ejabberd#2288).
Harden MUC implementation against incomplete presence stanzas.
Fix a race condition where stream management handlers would be installed too late on the XML stream, leading it to be closed with an
unsupported-stanza-type
becauseaioxmpp
failed to interpret SM requests.Support for escaping additional characters as entities when writing XML, see the additional_escapes argument to
aioxmpp.xml.XMPPXMLGenerator
.Support for the new XEP-0045 1.30 status code for kicks due to errors. See
aioxmpp.muc.LeaveMode.ERROR
.Minor compatibility fixes for XEP-0153 vcard-based avatar support.
Add a global IM
aioxmpp.im.service.Conversation.on_message()
event. This aggregates message events from all conversations.This can be used by applications which want to perform central processing of all IM messages, for example for logging purposes.
aioxmpp.im.service.Conversation
handles the lifecycle of event listeners to the individual conversations, which takes some burden off of the application.Fix a bug where monkey-patched
aioxmpp.xso.ChildFlag
descriptors would not be picked up by the XSO handling code.Make sure that the message ID is set before the
aioxmpp.im.conversation.AbstractConversation.on_message
event is emitted fromaioxmpp.im.p2p.Conversation
objects.Ensure that all
aioxmpp.MessageType.CHAT
/NORMAL
messages are forwarded to the respectiveaioxmpp.im.p2p.Conversation
if it exists.(Previously, only messages with a non-empty
aioxmpp.Message.body
would be forwarded.)This is needed for e.g. Chat Markers.
Ensure that Message Carbons are re-
aioxmpp.carbons.CarbonsClient.enable()
-d after failed stream resumption. Thanks, Ge0rG.Fix RFC 6121 violation: the default of the
@subscription
attribute of roster items is"none"
.aioxmpp
treated an absent attribute as fatal.Pass pre-stream-features exception down to stream feature listeners. This fixes hangs on errors before the stream features are received. This can happen with misconfigured SRV records or lack of ALPN support in a XEP-0368 setting. Thanks to Travis Burtrum for providing a test setup for hunting this down.
Set ALPN to
xmpp-client
by default. This is useful for XEP-0368 deployments.Fix handling of SRV records with equal priority, weight, hostname and port.
Support for
<optional/>
element in RFC 3921<session/>
negotiation feature; the feature is not needed with modern servers, but since legacy clients require it, they still announce it. The feature introduces a new round-trip for no gain. An rfc-draft by Dave Cridland standardises the<optional/>
element which allows a server to tell the client that it doesn’t require the session negotiation step.aioxmpp
now understands this and will skip that step, saving a round-trip with most modern servers.aioxmpp.tracking
now allows some state transitions out of theaioxmpp.tracking.MessageState.ERROR
state. See the documentation there for details.Fix a bug in
aioxmpp.JID.fromstr()
which would incorrectly parse and then reject some valid JIDs.Add
aioxmpp.DiscoClient.flush_cache()
allowing to flush the cached entries.Add
aioxmpp.disco.Node.set_identity_names()
. This is much more convenient than adding a dummy identity, removing the existing identity, re-adding the identity with new names and then removing the dummy identity.Remove restriction on data form types (not to be confused with
FORM_TYPE
) when instantiating a form withaioxmpp.forms.Form.from_xso()
.Fix an issue which prevented single-valued form fields from being rendered into XSOs if no value had been set (but a default was given).
Ensure that forms with
aioxmpp.forms.Form.FORM_TYPE
attribute render a proper :xep:`68`muc ``FORM_TYPE`` field.Allow unset field type in data forms. This may seem weird, but unfortunately it is widespread practice. In some data form types, omitting the field type is common (including it is merely a MAY in the XEP), and even in the most strict case it is only a SHOULD.
Relying on the field type to be present is thus a non-starter.
Some data form classes were added:
Support for answering requests for voice/role change in MUCs (cf. XEP-0045 §8.6 Approving Voice Requests). See
aioxmpp.muc.Room.on_muc_role_request()
for details.Support for unwrapped unknown values in
aioxmpp.xso.EnumCDataType
. This can be used withenum.IntEnum
for fun and profit.The status codes for
aioxmpp.muc
events are now an enumeration (seeaioxmpp.muc.StatusCode
). The status codes are now also available on the following events:aioxmpp.muc.Room.on_muc_enter()
,on_exit()
,on_leave()
,on_join()
,on_muc_role_changed()
, andon_muc_affiliation_changed()
.The
aioxmpp.im.conversation.AbstractConversation.invite()
was overhauled and improved.aioxmpp.PEPClient
now depends onaioxmpp.EntityCapsService
. This prevents a common mistake of loadingPEPClient
withoutEntityCapsService
, which prevents PEP auto-subscription from working.Handle
ValueError
raised byaiosasl
when the credentials are malformed.Fix exception when attempting to leave a
aioxmpp.im.p2p.Conversation
.
Deprecations¶
The above split of
aioxmpp.xso.AbstractType
also caused a split ofaioxmpp.xso.EnumType
intoaioxmpp.xso.EnumCDataType
andaioxmpp.xso.EnumElementType
.aioxmpp.xso.EnumType()
is now a function which transparently creates the correct class. Use of that function is deprecated and you should upgrade your code to use one of the two named classes explicitly.The name
aioxmpp.stream.StanzaStream.register_iq_request_coro()
is deprecated in favour ofregister_iq_request_handler()
. The old alias persists, but will be removed with the release of 1.0. Using the old alias emits a warning.Likewise,
unregister_iq_request_coro()
was renamed tounregister_iq_request_handler()
.aioxmpp.stream.StanzaStream.enqueue()
andaioxmpp.stream.StanzaStream.send()
were moved to the client asaioxmpp.Client.enqueue()
andaioxmpp.Client.send()
.The old names are deprecated, but aliases are provided until version 1.0.
The negotiation_timeout argument for
aioxmpp.security_layer.negotiate_sasl()
has been deprecated in favour ofaioxmpp.protocol.XMLStream
-level handling of timeouts.This means that the respective timeouts need to be configured on the XML stream if they are to be used (the normal connection setup takes care of that).
The use of namespace-name tuples for error conditions has been deprecated (see the breaking changes).
Version 0.10.1¶
Fix handling of IQ stanzas without ID and IQ stanzas of type
aioxmpp.IQType.ERROR
without error payload.Both are now treated like any other unparseable stanza.
Version 0.10.2¶
- Make compatible with Python 3.7.
Version 0.10.3¶
Fix incorrect error handling in
aioxmpp.xso
when a supressingaioxmpp.xso.XSO.xso_error_handler()
is in use.Under certain circumstances, it is possible that the handling of supressed error causes another error later on because the parsing stack mis-counts the depth in which it is inside the XML tree. This makes elements appear in the wrong place, typically leading to further errors.
In the worst case, using a supressing
xso_error_handler()
in specific circumstances can be vulnerable to denial of service and data injection into the XML stream.(A CVE will be allocated for this.)
Version 0.10.4¶
- Fix incorrect parsing of XEP-0198 location specifier. We always required a port number, while the standards allows omit the port number.
Version 0.10.5¶
Fix incorrect serialisation of nested namespace declarations for the same URI. One such occurence is often encountered when using the
<{urn:xmpp:forward:0}forwarded/>
element (seeaioxmpp.misc.Forwarded
). It can host a<{jabber:client}message/>
. Since we declare all namespaces of XSOs as prefixless, the nested message needs to re-declare its prefix. Due to incorrect handling of namespace prefix rebinding inaioxmpp.xml.XMPPXMLGenerator
, that re-declaration is not emitted, leading to incorrect output.This was reported in GitHub Issue #295 by @oxoWrk.
Version 0.9¶
New XEP implementations¶
aioxmpp.bookmarks
(XEP-0048): Support for accessing bookmark storage (currently only from Private XML storage).aioxmpp.private_xml
(XEP-0049): Support for accessing a server-side account-private XML storage.aioxmpp.avatar
(XEP-0084): Support for retrieving avatars, notifications for changed avatars in contacts and setting the avatar of the account itself.aioxmpp.pep
(XEP-0163): Support for making use of the Personal Eventing Protocol, a versatile protocol used to store and publish account-specific information such as Avatars, OMEMO keys, etc. throughout the XMPP network.aioxmpp.blocking
(XEP-0191): Support for blocking contacts on the server-side.aioxmpp.ping
(XEP-0199): XMPP Ping has been used internally since the very beginning (if Stream Management is not supported), but now there’s also a service for applications to use.aioxmpp.carbons
(XEP-0280): Support for receiving carbon-copies of messages sent and received by other resources.aioxmpp.entitycaps
(XEP-0390): Support for the new Entity Capabilities 2.0 protocol was added.
Most of these have been contributed by Sebastian Riese. Thanks for that!
New major features¶
aioxmpp.im
is a new subpackage which provides Instant Messaging services. It is still highly experimental, and feedback on the API is highly appreciated.The idea is to provide a unified interface to the different instant messaging transports, such as direct one-on-one chat, Multi-User Chats (XEP-0045) and the soon-to-come Mediated Information Exchange (XEP-0369).
Applications shall be able to use the interface without knowing the details of the transport; features such as message delivery receipts and message carbons shall work transparently.
In the course of this (see below), some breaking changes had to be made, but we think that the gain is worth the damage.
For an introduction in those features, read the documentation of the
aioxmpp.im
subpackage. The examples using IM features have been updated accordingly.The distribution of received presence and message stanzas has been reworked (to help with
aioxmpp.im
, which needs a very different model of message distribution than the traditional “register a handler for a sender and type”). The classic registration functions have been deprecated (see below) and were replaced by simple dispatcher services provided inaioxmpp.dispatcher
.
New examples¶
carbons_sniffer.py
: Show a log of all messages received and sent by other resources of the same account.set_avatar.py
: Change the avatar of the account.retrieve_avatar.py
: Retrieve the avatar of a member of the XMPP network (sufficient permissions required, normally a roster subscription is enough).
Breaking changes¶
Classes using
aioxmpp.service.message_handler()
oraioxmpp.service.presence_handler()
have to declareaioxmpp.dispatcher.SimpleMessageDispatcher
oraioxmpp.dispatcher.SimplePresenceDispatcher
(respectively) in their dependencies.A backward-compatible way to do so is to declare the dependency conditionally:
class FooService(aioxmpp.service.Service): ORDER_AFTER = [] try: import aioxmpp.dispatcher except ImportError: pass else: ORDER_AFTER.append( aioxmpp.dispatcher.SimpleMessageDispatcher )
aioxmpp.stream.Filter
got renamed toaioxmpp.callbacks.Filter
. This should normally not affect your code.Re-write of
aioxmpp.tracking
foraioxmpp.im
. Sorry. But the new API is more clearly defined and more correct. The (ab-)use ofaioxmpp.statemachine.OrderedStateMachine
never really worked anyways.Re-design of interface to
aioxmpp.muc
. This is unfortunate, but we did not see a way to reasonably provide backward-compatibility while still allowing for a clean integration withaioxmpp.im
.Re-design of
aioxmpp.entitycaps
to support XEP-0390. The interface of theaioxmpp.entitycaps.Cache
class has been redesigned and some internal classes and functions have been renamed.aioxmpp.IQ.payload
,aioxmpp.pubsub.xso.Item.registered_payload
andaioxmpp.pubsub.xso.EventItem.registered_payload
now strictly check the type of objects assigned. The classes of those objects must be registered withaioxmpp.IQ.as_payload_class()
oraioxmpp.pubsub.xso.as_payload_class()
, respectively.Technically, that requirement existed always as soon as one wanted to be able to receive those payloads: otherwise, one would simply not receive the payload, but an exception or empty object instead. By enforcing this requirement also for sending, we hope to improve the debugability of these issues.
The descriptors and decorators for
aioxmpp.service.Service
subclasses are now initialised in the order they are declared.This should normally not affect you, there are only very specific corner-cases where it makes a difference.
Minor features and bug fixes¶
Handle local serialisation issues more gracefully. Instead of sending a half-serialised XSO down the stream and then raising an exception, leaving the stream in an undefined state, XSOs are now serialised into a buffer (which is re-used for performance when possible) and only if serialisation was successful sent down the stream.
Replaced the hack-ish use of generators for
aioxmpp.xml.write_xmlstream()
with a proper class,aioxmpp.xml.XMLStreamWriter
.The generator blew up when we tried to exfiltrate exceptions from it. For the curious and brave, see the
bug/odd-exception-thing
branch. I actually suspect a CPython bug there, but I was unable to isolate a proper test case. It only blows up in the end-to-end tests.aioxmpp.dispatcher
: This is in connection with theaioxmpp.im
packageaioxmpp.misc
provides XSO definitions for two minor XMPP protocol parts (XEP-0203, XEP-0297), which are however reused in some of the protocols implemented in this release.aioxmpp.hashes
(XEP-0300): Friendly interface to the hash functions and hash function names defined in XEP-0300.Stream Management counters now wrap around as unsigned 32 bit integers, as the standard specifies.
aioxmpp.service.depsignal()
now supports connecting toaioxmpp.stream.StanzaStream
andaioxmpp.Client
signals.Unknown and unhandled IQ get/set payloads are now replied to with
<service-unavailable/>
instead of<feature-not-implemented/>
, as the former is actually specified in RFC 6120 section 8.4.The
aioxmpp.protocol.XMLStream
loggers foraioxmpp.Client
objects are now a child of the client logger itself, and not ataioxmpp.XMLStream
.Fix bug in
aioxmpp.EntityCapsService
rendering it useless for providing caps hashes to other entities.Fix
aioxmpp.callbacks.AdHocSignal.future()
, which was entirely unusable before.aioxmpp.service.depfilter()
: A decorator (similar to theaioxmpp.service.depsignal()
decorator) which allows to add aaioxmpp.service.Service
method to aaioxmpp.callbacks.Filter
chain.Fix
aioxmpp.RosterClient.groups
not being updated when items are removed during initial roster update.The two signals
aioxmpp.RosterClient.on_group_added()
,on_group_removed()
were added, which allow to track which groups exist in a roster at all (a group exists if there’s at least one member).Roster pushes are now accepted also if the
from_
is the bare local JID instead of missing/empty (those are semantically equivalent).aioxmpp.disco.RegisteredFeature
and changes toaioxmpp.disco.register_feature
. Effectively, attributes described byregister_feature
now have anenabled
attribute which can be used to temporarily or permanently disable the registration of the feature on a service object.The
aioxmpp.disco.StaticNode.clone()
method allows to copy anotheraioxmpp.disco.Node()
as aaioxmpp.disco.StaticNode
.The
aioxmpp.disco.Node.as_info_xso()
methdo creates aaioxmpp.disco.xso.InfoQuery
object containing the features and identities of the node.The strict argument was added to
aioxmpp.xso.Child
. It allows to enable strict type checking of the objects assigned to the descriptor. Only those objects whose classes have been registered with the descriptor can be assigned.This helps with debugging issues for “extensible” descriptors such as the
aioxmpp.IQ.payload
as described in the Breaking Changes section of this release.aioxmpp.DiscoClient
now usesaioxmpp.cache.LRUDict
for its internal caches to prevent memory exhaustion in long running applications and/or with malicious peers.aioxmpp.DiscoClient.query_info()
now supports a no_cache argument which prevents caching of the request and response.aioxmpp.service.attrsignal()
: A decorator (similar to theaioxmpp.service.depsignal()
decorator) which allows to connect to a signal on a descriptor.The default of XSO descriptors has incorrectly been passed through the validator, despite the documentation saying otherwise. This has been fixed.
aioxmpp.Client.resumption_timeout
: Support for specifying the lifetime of a Stream Management (XEP-0198) session and disabling stream resumption altogether. Thanks to @jomag for bringing up the use-case.Fix serialisation of
aioxmpp.xso.Collector
descriptors.Make
aioxmpp.xml.XMPPXMLGenerator
avoid the use of namespace prefixes if a namespace is undeclared if possible.Attempt to reconnect if generic OpenSSL errors occur. Thanks to @jomag for reporting.
The new
aioxmpp.stream.StanzaStream.on_message_received()
,on_presence_received()
signals unconditionally fire when a message or presence is received. They are used by theaioxmpp.dispatcher
andaioxmpp.im
implementations.
Deprecations¶
The following methods on
aioxmpp.stream.StanzaStream
have been deprecated and will be removed in 1.0:register_message_callback()
unregister_message_callback()
register_presence_callback()
unregister_presence_callback()
The former two are replaced by the
aioxmpp.dispatcher.SimpleMessageDispatcher
service and the latter two should be replaced by proper use of theaioxmpp.PresenceClient
or byaioxmpp.dispatcher.SimplePresenceDispatcher
if thePresenceClient
is not sufficient.aioxmpp.stream.stanza_filter()
got renamed toaioxmpp.callbacks.Filter.context_register()
.
Version 0.9.1¶
Slight Breaking change (yes, I know!) to fix a crucial bug with Python 3.4.6.
aioxmpp.node.discover_connectors()
now takes astr
argument instead ofbytes
for the domain name. Passing abytes
will fail.As this issue prohibited use with Python 3.4.6 under certain circumstances, we had to make a slight breaking change in a minor release. We also consider
discover_connectors()
to be sufficiently rarely useful to warrant breaking compatibility here.For the same reason,
aioxmpp.network.lookup_srv()
now returnsbytes
for hostnames instead ofstr
.Fix issues with different versions of
pyasn1
.
Version 0.8¶
New XEP implementations¶
aioxmpp.adhoc
(XEP-0050): Support for using Ad-Hoc commands; publishing own Ad-Hoc commands for others to use is not supported yet.
New major features¶
Services (see
aioxmpp.service
) are now even easier to write, using the new Decorators and Descriptors. These allow automagically registering methods as handlers or filters for stanzas and other often-used things.Existing services have been ported to this new system, and we recommend to do the same with your own services!
aioxmpp
now supports end-to-end testing using an XMPP server (such as Prosody). For the crude details seeaioxmpp.e2etest
and the End-to-end tests (or integration tests) section in the Developer Guide. Theaioxmpp.e2etest
API is still highly experimental and should not be used outside ofaioxmpp
.
New examples¶
adhoc_browser
: A graphical tool to browse and execute Ad-Hoc Commands. Requires PyQt5. Runmake
in the examples directory and start withpython3 -m adhoc_browser
.entity_items.py
,entity_info.py
: Show service discovery info and items for arbitrary JIDs.list_adhoc_commands.py
: List the Ad-Hoc commands offered by an entity.
Breaking changes¶
Changes to the connection procedure:
- If any of the connection errors encountered in
aioxmpp.node.connect_xmlstream()
is aaioxmpp.errors.TLSFailure
and all other connection options also failed, theTLSFailure
is re-raised instead of aaioxmpp.errors.MultiOSError
instance. This helps to prevent masking of configuration problems. - The change of
aioxmpp.node.connect_xmlstream()
described above also affects the behaviour ofaioxmpp.Client
, asTLSFailure
errors are treated as critical (in contrast toOSError
subclasses).
Changes in aioxmpp.Client
(formerly aioxmpp.AbstractClient
,
see in the deprecations below for the name change)
- The number of connection attempts made before the first connection is successful is now bounded, configurable through the new parameter max_initial_attempts. The default is at 4, which gives (together with the default exponential backoff parameters) a minimum time of attempted connections of about 5 seconds.
on_stream_suspended()
was added (this is not a breaking change, but belongs to theaioxmpp.Client
changes discussed here).on_stream_destroyed()
got a new argument reason which gives the exception which caused the stream to be destroyed.
Other breaking changes:
aioxmpp.tracking.MessageState.UNKNOWN
renamed toCLOSED
.aioxmpp.disco.Node.iter_items()
,iter_features()
anditer_identities()
now get the request stanza passed as first argument.aioxmpp.Presence.show
now uses theaioxmpp.PresenceShow
enumeration. The breakage is similar to the breakage in the 0.7 release; if I had thought of it at that time, I would have made the change back then, but it was overlooked.Again, a utility script (
find-v0.8-type-transitions.sh
) is provided which helps finding locations of code which need changing. See the Version 0.7 for details.Presence states with
show
set toDND
now order highest (before,DND
ordered lowest). The rationale is that if a user indicatesDND
state at one resource, one should probably respect the Do-Not-Disturb request on all resources.
The following changes are not severe, but may still break code depending on how it is used:
aioxmpp.disco.Service
was split intoaioxmpp.DiscoClient
andaioxmpp.DiscoServer
.If you need to be compatible with old versions, use code like this:
try: from aioxmpp import DiscoClient, DiscoServer except ImportError: import aioxmpp.disco DiscoClient = aioxmpp.disco.Service DiscoServer = aioxmpp.disco.Service
Type coercion in XSO descriptors now behaves differently. Previously,
None
was hard-coded to be exempt from type coercion; this allowed anyText
,ChildText
,Attr
and other scalar descriptor to be assignedNone
, unless a validator which explicitly forbade that was installed. The use case was to have a default, absence-indicating value which is outside the valid value range of thetype_
.This is now handled by exempting the
default
of the descriptor from type coercion and thus allowing assignment of that default by default. The change thus only affects descriptors which have adefault
other thanNone
(which includes an unset default).
Minor features and bug fixes¶
aioxmpp.stream.StanzaToken
objects are now awaitable.aioxmpp.stream.StanzaStream.send()
introduced as method which can be used to send arbitrary stanzas. See the docs there to observe the full awesomeness.Improvement and fixes to
aioxmpp.muc
:- Implemented
aioxmpp.muc.Room.request_voice()
. - Fix
aioxmpp.muc.Room.leave_and_wait()
never returning. - Do not emit
aioxmpp.muc.Room.on_join()
when an unavailable presence from an unknown occupant JID is received.
- Implemented
Added context managers for registering a callable as stanza handler or filter temporarily:
The
aioxmpp.service.Service.dependencies
attribute was added.Support for ANONYMOUS SASL mechanism. See
aioxmpp.security_layer.make()
for details (requires aiosasl 0.3+).Get rid of dependency on libxml2 development files. libxml2 itself is still required, both directly and indirectly (through the lxml dependency).
The
aioxmpp.PresenceServer
service was introduced and theaioxmpp.PresenceManagedClient
was re-implemented on top of that.Fix
AttributeError
being raised fromstate > None
(and other comparison operators), withstate
being aaioxmpp.PresenceState
instance.The more correct
TypeError
is now raised.The handling of stanzas with unparseable attributes and stanzas originating from the clients bare JID (i.e. from the clients server on behalf on the account) has improved.
The examples now default to
$XDG_CONFIG_HOME/aioxmpp-examples.ini
for configuration if it exists. (thanks, @mcepl).
Deprecations¶
Several classes were renamed:
aioxmpp.node.AbstractClient
→aioxmpp.Client
aioxmpp.shim.Service
→aioxmpp.SHIMService
aioxmpp.muc.Service
→aioxmpp.MUCClient
aioxmpp.presence.Service
→aioxmpp.PresenceClient
aioxmpp.roster.Service
→aioxmpp.RosterClient
aioxmpp.entitycaps.Service
→aioxmpp.EntityCapsService
aioxmpp.pubsub.Service
→aioxmpp.PubSubClient
The old names are still available until 1.0.
send_and_wait_for_sent()
deprecated in favour ofsend()
.send_iq_and_wait_for_reply()
deprecated in favour ofsend()
.enqueue_stanza()
is now calledenqueue()
.The presence argument to the constructor of and the
presence
andtimeout
attributes onaioxmpp.node.UseConnected
objects are deprecated.See the respective documentation for details on the deprecation procedure.
Version 0.7¶
License change: As of version 0.7,
aioxmpp
is distributed under the terms of the GNU Lesser General Public License version 3 or later (LGPLv3+). The exact terms are, as usual, found by taking a look atCOPYING.LESSER
in the source code repository.New XEP implementations:
aioxmpp.forms
(XEP-0004): An implementation of the Data Forms XEP. Take a look and see where it gets you.
New features in the
aioxmpp.xso
submodule:- The new
aioxmpp.xso.ChildFlag
descriptor is a simplification of theaioxmpp.xso.ChildTag
. It can be used where the presence or absence of a child element only signals a boolean flag. - The new
aioxmpp.xso.EnumType
type allows using aenum
enumeration as XSO descriptor type.
- The new
Often-used names have now been moved to the
aioxmpp
namespace:- The stanza classes
aioxmpp.IQ
,aioxmpp.Message
,aioxmpp.Presence
- The type enumerations (see below)
aioxmpp.IQType
,aioxmpp.MessageType
,aioxmpp.PresenceType
- Commonly used structures:
aioxmpp.JID
,aioxmpp.PresenceState
- Exceptions:
aioxmpp.XMPPCancelError
and its buddies
- The stanza classes
Horribly Breaking Change in the future:
aioxmpp.IQ.type_
,aioxmpp.Message.type_
,aioxmpp.Presence.type_
andaioxmpp.stanza.Error.type_
now useaioxmpp.xso.EnumType
, with corresponding enumerations (see docs of the respective attributes).This will break about every piece of code ever written for aioxmpp, and it is not trivial to fix automatically. This is why the following fallbacks have been implemented:
- The
type_
attributes still accept their string (orNone
in the case ofPresence.type_
) values when being written. When being read, the attributes always return the actual enumeration value. - The relevant enumeration members compare equal (and hash equally) to their
values. Thus,
MessageType.CHAT == "chat"
is still true (andMessageType.CHAT != "chat"
is false). register_message_callback()
,register_presence_callback()
, andregister_iq_request_coro()
, as well as their corresponding un-registration methods, all accept the string variants for their arguments, internally mapping them to the actual enumeration values.
Note
As a matter of fact (good news!), with only the fallbacks and no code fixes, the
aioxmpp
test suite passes. So it is likely that you will not notice any breakage in the 0.7 release, giving you quite some time to react.These fallbacks will be removed with aioxmpp 1.0, making the legacy use raise
TypeError
or fail silently. Each of these fallbacks currently produces aDeprecationWarning
.Note
DeprecationWarning
warnings are not shown by default in Python 3. To enable them, either run the interpreter with the-Wd
option, un-filter them explicitly usingwarnings.simplefilter("always")
at the top of your program, or explore other options as documented inwarnings
.So, now I said I will be breaking all your code, how do you fix it? There are two ways to find affected pieces of code: (1) run it with warnings (see above), which will find all affected pieces of code and (2) use the shell script provided at utils/find-v0.7-type-transitions.sh to find a subset of potentially affected pieces of code automatically. The shell script uses The Silver Searcher (ag) (find it in your distributions package repositories, I know it is there on Fedora, Arch and Debian!) and regular expressions to find common patterns. Example usage:
# find everything in the current subdirectory $ $AIOXMPPPATH/utils/find-v0.7-type-transitions.sh # only search in the foobar/ subdirectory $ $AIOXMPPPATH/utils/find-v0.7-type-transitions.sh foobar/ # only look at the foobar/baz.py file $ $AIOXMPPPATH/utils/find-v0.7-type-transitions.sh foobar/baz.py
The script was built while fixing
aioxmpp
itself after the bug. It has not found all affected pieces of code, but the vast majority. The others can be found by inspectingDeprecationWarning
warnings being emitted.- The
The
aioxmpp.security_layer.make()
makes creating a security layer much less cumbersome than before. It provides a simple interface supporting password authentication, certificate pinning and others.The interface of this function will be extended in the future when more authentication or certificate verification mechanisms come around.
The two methods
aioxmpp.muc.Service.get_room_config()
,aioxmpp.muc.Service.set_room_config()
have been implemented, allowing to manage MUC room configurations.Fix bug in
aioxmpp.xso.ChildValueMultiMap.to_sax()
which rendered XSOs with that descriptor useless.Fix documentation on
aioxmpp.PresenceManagedClient.set_presence()
.aioxmpp.callbacks.AdHocSignal
now logs when coroutines registered withaioxmpp.callbacks.AdHocSignal.SPAWN_WITH_LOOP()
raise exceptions or return non-None
values. See the documentation ofSPAWN_WITH_LOOP()
for details.aioxmpp.pubsub.xso.as_payload_class()
is a decorator (akin toaioxmpp.IQ.as_payload_class()
) to declare that yourXSO
shall be allowed as pubsub payload.register_message_callback()
andregister_presence_callback()
now explicitly raiseValueError
when an attempt to overwrite an existing listener is made, instead of silently replacing the callback.
Version 0.7.2¶
Fix resource leak which would emit:
task: <Task pending coro=<OrderedStateMachine.wait_for() running at /home/horazont/Projects/python/aioxmpp/aioxmpp/statemachine.py:170> wait_for=<Future pending cb=[Task._wakeup()]> cb=[XMLStream._stream_starts_closing()]>
Improve compatibility of
aioxmpp.muc
with Prosody 0.9 and below, which misses sending the110
status code on some presences.Handle inbound message stanzas with empty from attribute. Those are legal as per RFC 6120, but were not handled properly.
Version 0.6¶
New dependencies:
multidict
fromaiohttp
.aioopenssl
: This is the formeraioxmpp.ssl_transport
as a separate package;aioxmpp
still ships with a fallback in case that package is not installed.
New XEP implementations:
- partial
aioxmpp.pubsub
(XEP-0060): Everything which requires forms is not implemented yet. Publish/Subscribe/Retract and creation/deletion of nodes is verified to work (against Prosody at least). aioxmpp.shim
(XEP-0131), used foraioxmpp.pubsub
.- XEP-0368 support was added.
- partial
New features in the
aioxmpp.xso
subpackage:aioxmpp.xso.NumericRange
validator, which can be used to validate the range of any orderable type.aioxmpp.xso.query
, a module which allows for running queries against XSOs. This is still highly experimental.aioxmpp.xso.ChildValueMultiMap
descriptor, which usesmultidict
and is used inaioxmpp.shim
.
aioxmpp.network
was rewritten for 0.5.4The control over the used DNS resolver is now more sophisticated. Most notably,
aioxmpp.network
uses a thread-local resolver which is used for all queries by default.Normally,
aioxmpp.network.repeated_query()
will now re-configure the resolver from system-wide resolver configuration after the first timeout occurs.The resolver can be overridden (disabling the reconfiguration magic) using
aioxmpp.network.set_resolver()
.Breaking change:
aioxmpp.service.Service
does not accept a logger argument anymore; instead, it now accepts a base_logger argument. Refer to the documentation of the class for details.The base_logger is automatically passed by
aioxmpp.node.AbstractClient.summon()
on construction of the service and is theaioxmpp.node.AbstractClient.logger
of the client instance.Breaking change:
aioxmpp.xso.XSO
subclasses (or more specifically, instances of theaioxmpp.xso.model.XMLStreamClass
metaclass) now automatically declare a__slots__
attribute.The mechanics are documented in detail on
aioxmpp.xso.model.XMLStreamClass.__slots__
.Breaking change: The following functions have been removed:
aioxmpp.node.connect_to_xmpp_server()
aioxmpp.node.connect_secured_xmlstream()
aioxmpp.security_layer.negotiate_stream_security()
Use
aioxmpp.node.connect_xmlstream()
instead, but check the docs for the slightly different semantics.The following functions have been deprecated:
Use
aioxmpp.security_layer.SecurityLayer
instead.The existing helper function
aioxmpp.security_layer.tls_with_password_based_authentication()
is still live and has been modified to use the new code.Possibly breaking change: The arguments to
aioxmpp.CertificateVerifier.pre_handshake()
are now completely different. But as this method is not documented, this should not be a problem.Possibly breaking change: Attributes starting with
_xso_
are now also reserved on subclasses ofaioxmpp.xso.XSO
(together with the long-standing reservation of attributes starting withxso_
).Several bugfixes in
aioxmpp.muc
:aioxmpp.muc.Room.on_message()
now receives a proper occupant argument if occupant data is available when the message is received.MUCs now autorejoin correctly after a disconnect.
Fix crash when using
aioxmpp.tracking.MessageTracker
(e.g. indirectly throughaioxmpp.muc.Room.send_tracked_message()
).Thanks to @gudvnir over at github for pointing this out (see issue#7).
Several bugfixes related to
aioxmpp.protocol.XMLStream
:asyncio
errors/warnings about pending tasks being destroyed after disconnects should be gone now (aioxmpp.protocol.XMLStream
now properly cleans up its running coroutines).The
aioxmpp.protocol.XMLStream
is now closed or aborted by theaioxmpp.stream.StanzaStream
if the stream fails. This prevents lingering half-open TCP streams.See
aioxmpp.stream.StanzaStream.on_failure()
for details.
Some behaviour changes in
aioxmpp.stream.StanzaStream
:When the stream is stopped without SM enabled, the following new behaviour has been introduced:
ACTIVE
stanza tokens are set toDISCONNECTED
state.- Coroutines which were spawned due to them being registered with
register_iq_request_coro()
areasyncio.Task.cancel()
-ed.
The same as above holds if the stream is closed, even if SM is enabled (as stream closure is clean and will broadcast unavailable presence server-side).
This provides more fail-safe behaviour while still providing enough feedback.
New method:
aioxmpp.stream.StanzaStream.send_and_wait_for_sent()
.send_iq_and_wait_for_reply()
now also uses this.New method
aioxmpp.PresenceManagedClient.connected()
and new classaioxmpp.node.UseConnected
.The former uses the latter to provide an asynchronous context manager which starts and stops a
aioxmpp.PresenceManagedClient
. Intended for use in situations where an XMPP client is needed in-line. It saves a lot of boiler plate by taking care of properly waiting for the connection to be established etc.Fixed incorrect documentation of
aioxmpp.disco.Service.query_info()
. Previously, the docstring incorrectly claimed that the method would return the result ofaioxmpp.disco.xso.InfoQuery.to_dict()
, while it would in fact return theaioxmpp.disco.xso.InfoQuery
instance.Added strict arguments to
aioxmpp.JID
. See the class docmuentation for details.Added strict argument to
aioxmpp.xso.JID
and made it non-strict by default. See the documentation for rationale and details.Improve robustness against erroneous and malicious stanzas.
All parsing errors on stanzas are now caught and handled by
aioxmpp.stream._process_incoming_erroneous_stanza()
, which at least logs the synopsis of the stanza as parsed. It also makes sure that stream management works correctly, even if some stanzas are not understood.Additionally, a bug in the
aioxmpp.xml.XMPPXMLProcessor
has been fixed which prevented errors in text content from being caught.No visible side-effects: Replaced deprecated
unittest.TestCase.assertRaisesRegexp()
withunittest.TestCase.assertRaisesRegex()
(thanks, Maxim).Fix generation of IDs when sending stanzas. It has been broken for anything but IQ stanzas for some time.
Send SM acknowledgement when closing down stream. This prevents servers from sending error stanzas for the unacked stanzas ☺.
New callback mode
aioxmpp.callbacks.AdHocSignal.SPAWN_WITH_LOOP()
.aioxmpp.connector
added. This module provides classes which connect and return aaioxmpp.protocol.XMLStream
. They also handle TLS negotiation, if any.aioxmpp.node.AbstractClient
now accepts an override_peer argument, which may be a sequence of connection options as returned byaioxmpp.node.discover_connectors()
. See the class documentation for details.
Version 0.6.1¶
- Fix
TypeError
crashes when usingaioxmpp.entitycaps
,aioxmpp.presence
oraioxmpp.roster
, arising from the argument change to service classes.
Version 0.5¶
Support for XEP-0045 multi-user chats is now available in the
aioxmpp.muc
subpackage.Mostly transparent support for XEP-0115 (Entity Capabilities) is now available using the
aioxmpp.entitycaps
subpackage.Support for transparent non-scalar attributes, which get mapped to XSOs. Use cases are dicts mapping language tags to strings (such as for message
body
elements) or sets of values which are represented by discrete XML elements.For this, the method
get_formatted_type()
was added toaioxmpp.xso.AbstractType
and two new descriptors,aioxmpp.xso.ChildValueMap
andaioxmpp.xso.ChildValueList
, were implemented.ChildValueMap
(type_, *[, mapping_type])A mapping of keys to values, generated by child tags. ChildValueList
(type_, *[, container_type])Represents a subset of the child elements as values. ChildTextMap
(xso_type)A specialised version of ChildValueMap
which usesTextChildMap
together withstructs.LanguageMap
to convert theAbstractTextChild
subclass xso_type to and from a language-text mapping.Breaking change: The above descriptors are now used at several places, breaking the way these attributes need to be accessed:
aioxmpp.Message.subject
,aioxmpp.Message.body
,aioxmpp.Presence.status
,aioxmpp.disco.xso.InfoQuery.features
,- and possibly others.
Several stability improvements have been made. A race condition during stream management resumption was fixed and
aioxmpp.node.AbstractClient
instances now stop if non-OSError
exceptions emerge from the stream (as these usually indicate an implementation or user error).aioxmpp.callbacks.AdHocSignal
now provides full exception isolation.Support for capturing the raw XML events used for creating
aioxmpp.xso.XSO
instances from SAX is now provided throughaioxmpp.xso.CapturingXSO
. Helper functions to work with these events are also provided, most notablyaioxmpp.xso.events_to_sax()
, which can be used to re-create the original XML from those events.The main use case is to be able to write out a transcript of received XML data, independent of XSO-level understanding for the data received, provided the parts which are understood are semantically correct (transcripts will be incomplete if parsing fails due to incorrect contents).
CapturingXSO
(*args, **kwargs)The following class methods is provided by the metaclass (which is not publicly available, but a subclass of XMLStreamClass
):capture_events
(receiver, dest)Capture all events sent to receiver in the sequence dest. events_to_sax
(events, dest)Convert an iterable events of XSO events to SAX events by calling the matching SAX methods on dest This feature is already used in
aioxmpp.disco.xso.InfoQuery
, which now inherits fromCapturingXSO
and provides its transcript (if available) atcaptured_events
.The core SASL implementation has been refactored in its own independent package,
aiosasl
. Only the XMPP specific parts reside inaioxmpp.sasl
andaioxmpp
now depends onaiosasl
.aioxmpp.stream.StanzaStream.register_message_callback()
is more clearly specified now, a bug in the documentation has been fixed.aioxmpp.stream_xsos
is now calledaioxmpp.nonza
, in accordance with XEP-0360.aioxmpp.xso.Date
andaioxmpp.xso.Time
are now available to for XEP-0082 use. In addition, support for the legacy date time format is now provided inaioxmpp.xso.DateTime
.Date
Implement the Date type from XEP-0082. Time
Implement the Time type from XEP-0082. DateTime
(*[, legacy])Parse the value as ISO datetime, possibly including microseconds and timezone information. The Python 3.5 compatibility of the test suite has been improved. In a corner-case,
StopIteration
was emitted fromdata_received
, which caused a test to fail with aRuntimeError
due to implementation of PEP 0479 in Python 3.5. See the issue at github.Helper functions for reading and writing single XSOs (and their children) to binary file-like objects have been introduced.
write_single_xso
(x, dest)Write a single XSO x to a binary file-like object dest. read_xso
(src, xsomap)Read a single XSO from a binary file-like input src containing an XML document. read_single_xso
(src, type_)Read a single XSO
of the given type_ from the binary file-like input src and return the instance.In 0.5.4,
aioxmpp.network
was re-written. More details will follow in the 0.6 changelog. The takeaway is that the network stack now automatically reloads the DNS configuration after the first timeout, to accomodate to changing resolvers.
Version 0.4¶
Documentation change: A simple sphinx extension has been added which auto-detects coroutines and adds a directive to mark up signals.
The latter has been added to relevant places and the former automatically improves the documentations quality.
aioxmpp.roster.Service
now implements presence subscription management. To track the presence of peers,aioxmpp.presence
has been added.aioxmpp.stream
andaioxmpp.nonza
are part of the public API now.aioxmpp.nonza
has gained the XSOs for SASL (previously inaioxmpp.sasl
) and StartTLS (previously inaioxmpp.security_layer
).aioxmpp.xso.XSO
subclasses now support copying and deepcopying.aioxmpp.protocol
has been moved into the internal API part.aioxmpp.Message
specification fixed to have"normal"
as default fortype_
and relax the unknown child policy.Possibly breaking change:
aioxmpp.xso.XSO.DECLARE_NS
is now automatically generated by the meta classaioxmpp.xso.model.XMLStreamClass
. See the documentation for the detailed rules.To get the old behaviour for your class, you have to put
DECLARE_NS = {}
in its declaration.aioxmpp.stream.StanzaStream
has a positional, optional argument (local_jid) for ejabberd compatiblity.Several fixes and workarounds, finally providing ejabberd compatibility:
aioxmpp.nonza.StartTLS
declares its namespace prefixless. Otherwise, connections to some versions of ejabberd fail in a very humorous way: client says “I want to start TLS”, server says “You have to use TLS” and closes the stream with a policy-violation stream error.- Most XSOs now declare their namespace prefixless, too.
- Support for legacy (RFC 3921) XMPP session negotiation implemented in
aioxmpp.node.AbstractClient
. Seeaioxmpp.rfc3921
. aioxmpp.stream.StanzaStream
now supports incoming IQs with the bare JID of the local entity as sender, taking them as coming from the server.
Allow pinning of certificates for which no issuer certificate is available, because it is missing in the server-provided chain and not available in the local certificate store. This is, with respect to trust, treated equivalent to a self-signed cert.
Fix stream management state going out-of-sync when an erroneous stanza (unknown payload, type or validator errors on the payload) was received. In addition, IQ replies which cannot be processed raise
aioxmpp.errors.ErroneousStanza
fromaioxmpp.stream.StanzaStream.send_iq_and_wait_for_reply()
and when registering futures for the response usingaioxmpp.stream.StanzaStream.register_iq_response_future()
. See the latter for details on the semantics.Fixed a bug in
aioxmpp.xml.XMPPXMLGenerator
which would emit elements in the wrong namespace if the meaning of a XML namespace prefix was being changed at the same time an element was emitted using that namespace.The defaults for unknown child and attribute policies on
aioxmpp.xso.XSO
are nowDROP
and notFAIL
. This is for better compatibility with old implementations and future features.
Version 0.3¶
Breaking change: The required keyword argument on most
aioxmpp.xso
descriptors has been removed. The semantics of the default keyword argument have been changed.Before 0.3, the XML elements represented by descriptors were not required by default and had to be marked as required e.g. by setting
required=True
inxso.Attr
constructor.Since 0.3, the descriptors are generally required by default. However, the interface on how to change that is different. Attributes and text have a default keyword argument which may be set to a value (which may also be
None
). In that case, that value indicates that the attribute or text is absent: it is used if the attribute or text is missing in the source XML and if the attribute or text is set to the default value, it will not be emitted in XML.Children do not support default values other than
None
; thus, they are simply controlled by a boolean flag required which needs to be passed to the constructor.The class attributes
SERVICE_BEFORE
andSERVICE_AFTER
have been renamed toORDER_BEFORE
andORDER_AFTER
respectively.The
aioxmpp.service.Service
class has additional support to handle the old attributes, but will emit a DeprecationWarning if they are used on a class declaration.See
aioxmpp.service.Meta.SERVICE_AFTER
for more information on the deprecation cycle of these attributes.