Changelog¶
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 at COPYING.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 the aioxmpp.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 a enum 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_ and aioxmpp.stanza.Error.type_ now use aioxmpp.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 (or None in the case of Presence.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 (and MessageType.CHAT != "chat" is false).
- register_message_callback(), register_presence_callback(), and register_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 a DeprecationWarning.
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 using warnings.simplefilter("always") at the top of your program, or explore other options as documented in warnings.
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 inspecting DeprecationWarning 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 with aioxmpp.callbacks.AdHocSignal.SPAWN_WITH_LOOP() raise exceptions or return non-None values. See the documentation of SPAWN_WITH_LOOP() for details.
aioxmpp.pubsub.xso.as_payload_class() is a decorator (akin to aioxmpp.IQ.as_payload_class()) to declare that your XSO shall be allowed as pubsub payload.
register_message_callback() and register_presence_callback() now explicitly raise ValueError 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 the 110 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 from aiohttp.
- aioopenssl: This is the former aioxmpp.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 for aioxmpp.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 uses multidict and is used in aioxmpp.shim.
aioxmpp.network was rewritten for 0.5.4
The 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 the aioxmpp.node.AbstractClient.logger of the client instance.
Breaking change: aioxmpp.xso.XSO subclasses (or more specifically, instances of the aioxmpp.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 of aioxmpp.xso.XSO (together with the long-standing reservation of attributes starting with xso_).
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 through aioxmpp.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 the aioxmpp.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 to DISCONNECTED state.
- Coroutines which were spawned due to them being registered with register_iq_request_coro() are asyncio.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 class aioxmpp.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 of aioxmpp.disco.xso.InfoQuery.to_dict(), while it would in fact return the aioxmpp.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() with unittest.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 a aioxmpp.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 by aioxmpp.node.discover_connectors(). See the class documentation for details.
Version 0.6.1¶
- Fix TypeError crashes when using aioxmpp.entitycaps, aioxmpp.presence or aioxmpp.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 to aioxmpp.xso.AbstractType and two new descriptors, aioxmpp.xso.ChildValueMap and aioxmpp.xso.ChildValueList, were implemented.
ChildValueMap A mapping of keys to values, generated by child tags. ChildValueList A list of values, generated by child tags. ChildTextMap A specialised version of ChildValueMap which uses TextChildMap together with structs.LanguageMap to convert the AbstractTextChild 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 through aioxmpp.xso.CapturingXSO. Helper functions to work with these events are also provided, most notably aioxmpp.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 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 This feature is already used in aioxmpp.disco.xso.InfoQuery, which now inherits from CapturingXSO and provides its transcript (if available) at captured_events.
The core SASL implementation has been refactored in its own independent package, aiosasl. Only the XMPP specific parts reside in aioxmpp.sasl and aioxmpp now depends on aiosasl.
aioxmpp.stream.StanzaStream.register_message_callback() is more clearly specified now, a bug in the documentation has been fixed.
aioxmpp.stream_xsos is now called aioxmpp.nonza, in accordance with XEP-0360.
aioxmpp.xso.Date and aioxmpp.xso.Time are now available to for XEP-0082 use. In addition, support for the legacy date time format is now provided in aioxmpp.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 from data_received, which caused a test to fail with a RuntimeError 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 and aioxmpp.nonza are part of the public API now. aioxmpp.nonza has gained the XSOs for SASL (previously in aioxmpp.sasl) and StartTLS (previously in aioxmpp.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 for type_ and relax the unknown child policy.
Possibly breaking change: aioxmpp.xso.XSO.DECLARE_NS is now automatically generated by the meta class aioxmpp.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. See aioxmpp.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 from aioxmpp.stream.StanzaStream.send_iq_and_wait_for_reply() and when registering futures for the response using aioxmpp.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 now DROP and not FAIL. 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 in xso.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 and SERVICE_AFTER have been renamed to ORDER_BEFORE and ORDER_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.