Changelog¶
Version 0.13¶
New XEP implementations¶
Support for the XEP-0359 (Unique and Stable Stanza IDs) schema in
aioxmpp.misc
.
New examples¶
muc_moderate_message.py to remove a message (using a makeshift implementation of XEP-0425) from a MUC.
get_muc_affiliations.py to query affiliated JIDs from a given MUC.
get_external_services.py to query external services exposed via XEP-0215. This is useful in the context of testing STUN/TURN configuration.
ping.py, to send XEP-0199 to one or more remote JIDs.
roster_watch.py: Stay connected and watch for roster changes.
set_muc_avatar.py: Set the avatar of a MUC.
New major features¶
Breaking changes¶
Potentially breaking change:
aioxmpp.muc.Room.on_presence_changed()
now emits for all normal (non-unavailable, non-roster-management) presence stanzas received from an occupant.Previously, the signal would only emit for cases where the presence show or the status text had changed. This, however, made it impossible for user code to stay up-to-date with the contents of custom extensions transmitted via presence stanzas.
This was reported on GitHub as issue #341 by @raj2569.
The dependencies and compatibility has been improved, potentially breaking some setups. aioxmpp now supports Python 3.10 and is better prepared for Python 3.11, has bumped some of its dependencies and requires a more modern version of Sphinx to build the docs.
This is probably the last release to support Python 3.5.
Minor features and bug fixes¶
aioxmpp.muc.Service.get_affiliated()
added to query affiliations of a MUC.aioxmpp.vcard.Service.set_vcard()
now supports an optional jid argument to set vCards of foreign entities (e.g. to set a MUC avatar).
Version 0.12¶
Drop support for Python 3.4. This includes migrating to using
async def
instead of@asyncio.coroutine
consistently. Future changes will include using type annotations.Add
--e2etest-only
flag to the e2etest nose plugin. This flag will skip any test case not derived fromaioxmpp.e2etest.TestCase
. The use case for this is to use the aioxmpp test suite to test other servers in their CI.aioxmpp.e2etest.provision.StaticPasswordProvisioner
Fix
aioxmpp.jid_escape()
double escaping sequences in some circumstances.Support for Python 3.9.
Make the stream header customizable for users of
aioxmpp.protocol.XMLStream
.
Version 0.12.1¶
Fix leaking
asyncio.Future
instances from internal functions inaioxmpp.protocol
, causing annoying (but harmless) error log messages from asyncio.Issue #358 reported by @pszafer, thanks.
Allow keyword arguments being passed to
AUTO_FUTURE
callback listeners. This is to support use cases where callbacks are extended with keyword arguments in subclasses, as extensively used inaioxmpp.im
.Issue #360 reported by @zak333, thanks.
Version 0.11¶
New XEP implementations¶
Support for the XEP-0027 (Current Jabber OpenPGP Usage) schema in
aioxmpp.misc
.XEP-0047 (In-Band Bytestreams), see
aioxmpp.ibb
.The XEP-0106 (JID Escaping) encoding can now be used via
aioxmpp.jid_escape()
,aioxmpp.jid_unescape()
.@LukeMarlin contributed support for the XEP-0308 schema in
aioxmpp.misc
.The XEP-0335 (JSON Containers) schema is available for use via
aioxmpp.misc.JSONContainer
.Implement support for XEP-0410 (MUC Self-Ping (Schrödinger’s Chat)).
This introduces two new signals to
aioxmpp.muc.Room
objects:on_muc_stale()
: Emits when a possible connectivity issue with the MUC is detected, but it is unclear whether the user is still joined or not and/or whether messages are being lost.on_muc_fresh()
: Emits when a possible connectivity issue with the MUC is detected as resolved and the user is still joined. Presence may be out-of-sync and messages may have been lost, however.
If a connectivity issue which has caused the user to be removed from the MUC is detected, the appropriate signals (with
aioxmpp.muc.LeaveMode.DISCONNECTED
) are emitted, or the room is automatically re-joined if it is set tomuc_autorejoin
(no history is requested on this rejoin).In addition to that, the
aioxmpp.MUCClient.cycle()
method has been introduced. It allows an application to leave and join a MUC in quick succession using without discarding theaioxmpp.muc.Room
object (just like a stream disconnect would). This is useful to deal with stale situations by forcing a resync.
Security Fixes¶
CVE-2019-1000007: Fix incorrect error handling in
aioxmpp.xso
when a suppressingaioxmpp.xso.XSO.xso_error_handler()
is in use.Under certain circumstances, it is possible that the handling of suppressed 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 suppressing
xso_error_handler()
in specific circumstances can be vulnerable to denial of service and data injection into the XML stream.(The fix was also backported to 0.10.3.)
New major features¶
The
aioxmpp.pubsub
implementation gained support for node configuration and the related publish-options. This is vital for proper operation of private storage in PEP.Relevant additions are:
The new
publish_options
argument toaioxmpp.PubSubClient.publish()
The new
access_model
argument toaioxmpp.PEPClient.publish()
The new
aioxmpp.Client.on_stream_resumed()
event allows services and application code to learn when the stream was resumed after it suspended due to loss of connectivity. This is the counterpart toaioxmpp.Client.on_stream_suspended()
.This allows services and application code to defer actions until the stream is alive again. While this is generally not necessary, it can be good to delay periodic tasks or bulk operations in order to not overload the newly established stream with queued messages.
New examples¶
Breaking changes¶
The undocumented and unused descriptors
aioxmpp.Message.ext
andaioxmpp.Presence.ext
were removed. If your code relies on them you can instead patch a descriptor to the class (with a prefix that uniquely identifies your extension).A good example is how aioxmpp itself makes use of that feature in
aioxmpp.misc
.aioxmpp.stringprep
now uses the Unicode database in version 3.2.0 as specified in RFC 3454.The way the topological sort of service dependencies is handled was simplified: We no longer keep a toposort of all service classes. This implies that :class:`Service` subclasses are no longer ordered objects. However, we still guarantee a runtime error when a dependency loop is declared—if a class uses only one of ORDER_BEFORE respective ORDER_AFTER it cannot introduce a dependency loop; only when a class uses both we have to do an exhaustive search of the dependent nodes. This search touches only a few nodes instead of the whole graph and is only triggered for very few service classes.
Summon has been creating an independent toposort of only the required classes anyway, so we use this for deriving ordering indices for filter chains from now on—this also allows simpler extension, modification of the filter order (e.g.
-index
orders in reverse).Methods for determining transitive dependency (and independency) have been added to the service classes:
aioxmpp.Service.orders_after()
,aioxmpp.Service.orders_after_any()
,aioxmpp.Service.independent_from()
.
These search the class graph and are therefore not efficient (and the results may change when new classes are defined).
Tests should always prefer to test the declared attributes when checking for correct dependencies.
aioxmpp.make_security_layer()
now binds the default for the ssl context factory early toaioxmpp.security_layer.default_ssl_context()
. This means that you can not monkey-patchaioxmpp.security_layer.default_ssl_context()
and have your changes apply to all security layers anymore. Since this behaviour was never documented or intended, there is no transition period for this.aioxmpp.xso.XSO.unparse_to_sax()
was renamed toxso_serialise_to_sax()
.
Minor features and bug fixes¶
Support for servers which send a XEP-0198 Stream Management counter in resumption errors. This allows us to know precisely which stanzas were (not) received by the server and thus improves accuracy of the stanza token state.
Stanzas which are acknowledged in this way by a server enter the
ACKED
state as normal. Stanzas which are not covered by the counter enterDISCONNECTED
state instead ofSENT_WITHOUT_SM
, since the stream knows for sure that the stanza has not been received by the server.This only works if the server provides a counter value on failure; if the counter value is not provided, sent stanzas which were not acked during the previous connection will enter
SENT_WITHOUT_SM
state as previously.aioxmpp.forms
will not complain anymore if multiple<option/>
elements in a list-single/list-multi are lacking a label. It is recommended that you default the label to the option value in such a case.(Note that it already has been possible that one label was absent (i.e.
None
). This just allows more than one label to be absent.)aioxmpp.xso.ChildTextMap
can now also be constructed from a tag, an appropriate XSO is then constructed on the fly.aioxmpp.stream.StanzaStream.register_iq_request_handler()
andaioxmpp.service.iq_handler()
now support a keyword argument with_send_reply which makes them pass an additional argument to the handler, which is a function that can be used to enqueue the reply to the IQ before the handler has returned. This allows sequencing other actions after the reply has been sent.aioxmpp.hashes
now supports the hashes-used element and has a service that handles registering the disco features and can determine which hash functions are supported by us and another entity.Moved
aioxmpp.protocol.AlivenessMonitor
toaioxmpp.utils.AlivenessMonitor
for easier reuse.Extract
aioxmpp.ping.ping()
fromaioxmpp.PingService.ping()
.aioxmpp.utils.proxy_property
for easier use of composed classes over inherited classes.aioxmpp.xso.ChildValue
as a natural extension ofaioxmpp.xso.ChildValueList
and others.aioxmpp.make_security_layer()
now supports the ssl_context_factory argument which is already known from the (deprecated)aioxmpp.security_layer.tls_with_password_based_authentication()
.It allows application code to pass a factory to create the SSL context instead of defaulting to the SSL context provided by aioxmpp.
Fix incorrect parsing of XEP-0198 location specifier. We always required a port number, while the standards allows omit the port number.
Fix incorrect serialisation of nested namespace declarations for the same URI. One such occurrence 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.
Fix assignment of enumeration members to descriptors using
aioxmpp.xso.EnumCDataType
with allow_coerce set to true but deprecate_coerce set to false.
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.
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 identifying 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.
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.errors.XMPPError
(and its subclasses), the condition argument
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-0068FORM_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.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: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.
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 unparsable 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:
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.
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
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
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.
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])Dictiorary of child elements parsed using the given Element Type.
ChildValueList
(type_, *[, container_type])List of child elements parsed using the given Element Type.
ChildTextMap
(xso_type)Dictionary of character data in child elements keyed by the language attribute.
Breaking change: The above descriptors are now used at several places, breaking the way these attributes need to be accessed:
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
()ISO date Character Data Type.
Time
()ISO time Character Data Type.
DateTime
(*[, legacy])ISO datetime Character Data Type.
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 accommodate 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 compatibility.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.