Changelog

Version 0.13

New XEP implementations

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 from aioxmpp.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 in aioxmpp.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 in aioxmpp.im.

    Issue #360 reported by @zak333, thanks.

Version 0.12.2

  • Fix incorrect use of aioxmpp.muc.service.Room.on_exit() in aioxmpp.muc.service.Room.leave() which causes the future to not work correctly.

    Again 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 to muc_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 the aioxmpp.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 suppressing aioxmpp.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

New examples

Breaking changes

  • The undocumented and unused descriptors aioxmpp.Message.ext and aioxmpp.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 to aioxmpp.security_layer.default_ssl_context(). This means that you can not monkey-patch aioxmpp.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 to xso_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 enter DISCONNECTED state instead of SENT_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() and aioxmpp.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 to aioxmpp.utils.AlivenessMonitor for easier reuse.

  • Extract aioxmpp.ping.ping() from aioxmpp.PingService.ping().

  • aioxmpp.utils.proxy_property for easier use of composed classes over inherited classes.

  • aioxmpp.xso.ChildValue as a natural extension of aioxmpp.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 (see aioxmpp.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 in aioxmpp.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

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 within aioxmpp.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:

  • Consistent Member Argument for on_message(): The aioxmpp.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, the Room will assume a buggy server and transition to ACTIVE 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:

    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. See aioxmpp.muc.RoomState.

  • Recognizability of Occupants across Rejoins/Reboots: The aioxmpp.im.conversation.AbstractConversationMember.uid attribute holds a (reasonably) unique string identifying the occupant. If the uid 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 as aioxmpp.Client.send() and aioxmpp.Client.enqueue(). In addition, send()-ing a stanza will block until the client has a valid stream. Attempting to enqueue() a stanza while the client does not have a valid stream raises a ConnectionError.

    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 (via aioxmpp.muc.Room.invite()) and receiving invitations (via aioxmpp.MUCClient.on_muc_invitation()). The interface for aioxmpp.im.conversation.AbstractConversation.invite() has been reworked.

  • Service Members: aioxmpp.im.conversation.AbstractConversations can now have a aioxmpp.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 at service_member.

  • Better Child Element Enumerations: The aioxmpp.xso.XSOEnumMixin is a mixin which can be used with enum.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 (as condition_obj) exceptions and aioxmpp.stanza.Error payloads (as condition_obj).

    For this change, the following subchanges are relevant:

    Please see the breaking changes below for how to handle the transition from namespace-name tuples to enumeration members.

New examples

  • upload.py: uses aioxmpp.httpupload and aiohttp 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

Minor features and bug fixes

Deprecations

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 in aioxmpp.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

Minor features and bug fixes

Deprecations

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 a str argument instead of bytes for the domain name. Passing a bytes 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 returns bytes for hostnames instead of str.

  • 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 see aioxmpp.e2etest and the End-to-end tests (or integration tests) section in the Developer Guide. The aioxmpp.e2etest API is still highly experimental and should not be used outside of aioxmpp.

New examples

  • adhoc_browser: A graphical tool to browse and execute Ad-Hoc Commands. Requires PyQt5. Run make in the examples directory and start with python3 -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:

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 the aioxmpp.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 to CLOSED.

  • aioxmpp.disco.Node.iter_items(), iter_features() and iter_identities() now get the request stanza passed as first argument.

  • aioxmpp.Presence.show now uses the aioxmpp.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 to DND now order highest (before, DND ordered lowest). The rationale is that if a user indicates DND 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 into aioxmpp.DiscoClient and aioxmpp.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 any Text, ChildText, Attr and other scalar descriptor to be assigned None, 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 the type_.

    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 a default other than None (which includes an unset default).

Minor features and bug fixes

Deprecations

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:

  • Often-used names have now been moved to the aioxmpp namespace:

  • 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:

    1. 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.

    2. 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).

    3. 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

Version 0.6.1

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(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:

  • 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 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 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()

    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 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 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 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 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. 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.