### Install aioxmpp via pip Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/installation.md Installs the aioxmpp library and its dependencies from PyPI using pip3. This is the recommended method for general use. ```bash pip3 install aioxmpp ``` -------------------------------- ### Anonymous provisioner configuration Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/dev-guide/index.md Example configuration for using the AnonymousProvisioner with the e2etest framework. ```ini [global] provisioner=aioxmpp.e2etest.provision.AnonymousProvisioner [aioxmpp.e2etest.provision.AnonymousProvisioner] domain=localhost pin_store=pinstore.json pin_type=0 ``` -------------------------------- ### Example XML for Book Library Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/an-introduction-to-xso.md An example XML file conforming to the book library structure defined by the XSO classes. It includes multiple books with localized titles and chapters. ```xml The Amazing Life of Foo Das Faszinierende Leben des Foo F. Nord 2099-01-01 23 The Birth of Foo Die Geburt des Foo The Death of Foo Der Tod des Foo The Relevance of Pink Flamingos to Computer Science Die Relevanz von rosa Flamingos für die Informatik O. L. Bilderrahmen 2007-01-01 42 ``` -------------------------------- ### Install aioxmpp in editable mode Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/installation.md Installs aioxmpp in editable mode from a local source repository. This is recommended for developers who want to modify the library's code. Ensure dependencies are installed first. ```bash git clone https://github.com/horazont/aioxmpp cd aioxmpp git checkout devel # make sure to use the devel branch pip3 install -e . ``` -------------------------------- ### Install Dependencies on Debian 8 (Jessie) via apt Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/installation.md Installs essential build and Python dependencies for aioxmpp on Debian 8 using apt. Includes packages like python3-dnspython, python3-openssl, and build-essential. ```bash apt install --no-install-recommends python3-dnspython python3-openssl \ python3-pyasn1 python3-pyasn1-modules build-essential libxml2-dev \ libxslt1-dev python3-dev libz-dev python3-pip ``` -------------------------------- ### Install Dependencies on Debian 9 (Stretch) via apt Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/installation.md Installs essential build and Python dependencies for aioxmpp on Debian 9 using apt. Includes packages like python3-dnspython, python3-openssl, and python3-multidict. ```bash apt install --no-install-recommends python3-dnspython python3-openssl \ python3-pyasn1 python3-pyasn1-modules python3-multidict \ python3-tzlocal python3-lxml python3-babel python3-pip ``` -------------------------------- ### PubSub Node Configuration Methods Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/api/changelog.md Methods for managing PubSub node configuration, including getting and setting node configurations. ```python aioxmpp.PubSubClient.get_node_config() aioxmpp.PubSubClient.set_node_config() ``` -------------------------------- ### Install Build Dependencies on Debian 8/9 via apt Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/installation.md Installs C build dependencies required for some Python packages like lxml and PyOpenSSL on Debian 8 and 9. This command should be run before installing other dependencies via pip. ```bash apt install --no-install-recommends build-essential libssl-dev \ libxml2-dev libxslt1-dev python3-dev python3-openssl libz-dev \ python3-pip ``` -------------------------------- ### Manage Roster with RosterClient Source: https://context7.com/jssfr/aioxmpp/llms.txt Utilize RosterClient to access and manage the contact list. This example demonstrates waiting for the initial roster, iterating through contacts and groups, adding new entries, requesting subscriptions, approving requests, and removing contacts. Ensure aioxmpp and asyncio are imported. ```python import asyncio import aioxmpp async def roster_example(client): # Summon the roster service roster = client.summon(aioxmpp.RosterClient) # Wait for initial roster to be received initial_roster_received = asyncio.Event() def on_initial_roster(): initial_roster_received.set() roster.on_initial_roster_received.connect(on_initial_roster) async with client.connected(): await initial_roster_received.wait() # Access all roster items for jid, item in roster.items.items(): print(f"Contact: {jid}") print(f" Name: {item.name}") print(f" Subscription: {item.subscription}") print(f" Groups: {item.groups}") # Access by group for group_name, items in roster.groups.items(): print(f"Group '{group_name}':") for item in items: print(f" - {item.jid} ({item.name})") # Add a new contact await roster.set_entry( aioxmpp.JID.fromstr("newcontact@example.org"), name="New Contact", groups=["Friends", "Work"] ) # Request subscription await roster.subscribe(aioxmpp.JID.fromstr("newcontact@example.org")) # Approve subscription request await roster.approve(aioxmpp.JID.fromstr("requester@example.org")) # Remove contact await roster.remove_entry(aioxmpp.JID.fromstr("oldcontact@example.org")) # Event handlers for roster changes: # roster.on_entry_added(item) # roster.on_entry_name_changed(item) # roster.on_entry_subscription_changed(item) # roster.on_entry_removed(item) ``` -------------------------------- ### Traceback for DNS NXDOMAIN error Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/pitfalls.md Example of the traceback encountered when attempting to connect to a bare IP address. ```default Traceback (most recent call last): File "/home/horazont/aioxmpp/aioxmpp/network.py", line 272, in repeated_query raise_on_no_answer=False File "/usr/lib/python3.4/asyncio/futures.py", line 388, in __iter__ yield self # This tells Task to wait for completion. File "/usr/lib/python3.4/asyncio/tasks.py", line 286, in _wakeup value = future.result() File "/usr/lib/python3.4/asyncio/futures.py", line 277, in result raise self._exception File "/usr/lib/python3.4/concurrent/futures/thread.py", line 54, in run result = self.fn(*self.args, **self.kwargs) File "/home/horazont/.local/lib/python3.4/site-packages/dns/resolver.py", line 1051, in query raise NXDOMAIN(qnames=qnames_to_try, responses=nxdomain_responses) dns.resolver.NXDOMAIN: None of DNS query names exist: _xmpp-client._tcp.192.168.122.1., _xmpp-client._tcp.192.168.122.1. During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/home/horazont/aioxmpp/aioxmpp/node.py", line 710, in _on_main_done task.result() File "/usr/lib/python3.4/asyncio/futures.py", line 277, in result raise self._exception File "/usr/lib/python3.4/asyncio/tasks.py", line 233, in _step result = coro.throw(exc) File "/home/horazont/aioxmpp/aioxmpp/node.py", line 868, in _main yield from self._main_impl() File "/home/horazont/aioxmpp/aioxmpp/node.py", line 830, in _main_impl logger=self.logger) File "/home/horazont/aioxmpp/aioxmpp/node.py", line 337, in connect_xmlstream logger=logger, File "/home/horazont/aioxmpp/aioxmpp/node.py", line 142, in discover_connectors "xmpp-client", File "/home/horazont/aioxmpp/aioxmpp/network.py", line 318, in lookup_srv **kwargs) File "/home/horazont/aioxmpp/aioxmpp/network.py", line 280, in repeated_query "nameserver error, most likely DNSSEC validation failed", aioxmpp.network.ValidationError: nameserver error, most likely DNSSEC validation failed ``` -------------------------------- ### Implement an echo bot callback Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/quickstart.md An example of a message callback that echoes the body of received messages back to the sender. ```python def message_received(msg): if not msg.body: # do not reflect anything without a body return reply = msg.make_reply() reply.body.update(msg.body) client.enqueue(reply) ``` -------------------------------- ### Receive and Echo Messages with SimpleMessageDispatcher Source: https://context7.com/jssfr/aioxmpp/llms.txt Register callbacks for incoming CHAT and NORMAL messages using SimpleMessageDispatcher. This example sets up an echo bot that prints received messages and sends them back to the sender. Ensure aioxmpp and asyncio are imported. ```python import asyncio import aioxmpp import aioxmpp.dispatcher async def echo_bot(jid, password): client = aioxmpp.PresenceManagedClient( jid, aioxmpp.make_security_layer(password) ) def on_chat_message(msg): if not msg.body: return # Ignore empty messages print(f"Received from {msg.from_}: {msg.body.any()}") # Echo back reply = aioxmpp.Message( type_=msg.type_, to=msg.from_ ) reply.body.update(msg.body) client.enqueue(reply) # Summon the message dispatcher service dispatcher = client.summon(aioxmpp.dispatcher.SimpleMessageDispatcher) # Register callback for CHAT messages from any sender (None = any) dispatcher.register_callback( aioxmpp.MessageType.CHAT, None, # from_jid filter (None accepts all) on_chat_message ) # Also handle normal messages dispatcher.register_callback( aioxmpp.MessageType.NORMAL, None, on_chat_message ) async with client.connected(): print("Echo bot running... Press Ctrl+C to stop") while True: await asyncio.sleep(1) # Run: asyncio.run(echo_bot(aioxmpp.JID.fromstr("bot@example.org"), "password")) ``` -------------------------------- ### Register Handler for Software Version IQ Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/quickstart.md This snippet shows how to register an asynchronous handler for incoming IQ requests of type 'GET' that carry a `Query` payload. The handler constructs and returns a `Query` object with software details. Ensure the client is connected before registering handlers. ```python from aioxmpp.version.xso import Query async def handler(iq): print("software version request from {!r}".format(iq.from_)) result = Query() result.name = "aioxmpp Quick Start Pro" result.version = "23.42" result.os = "MFHBμKOS (My Fancy HomeBrew Micro Kernel Operating System)" return result client.stream.register_iq_request_handler( aioxmpp.IQType.GET, Query, handler, ) async with client.connected(): await asyncio.sleep(30) ``` -------------------------------- ### Define Book Library XSO Structures Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/an-introduction-to-xso.md Define Python classes that map to XML elements for a book library. This includes nested structures like chapters within a book, and attributes like chapter start page. ```python import aioxmpp.xso namespace = "urn:uuid:39ba7586-fb65-4ec8-80ce-f3a9f2890490" class Chapter(aioxmpp.xso.XSO): TAG = namespace, "chapter" title = aioxmpp.xso.ChildTextMap((namespace, "title")) start_page = aioxmpp.xso.Attr( "start-page", type_=aioxmpp.xso.Integer() ) class TableOfContents(aioxmpp.xso.XSO): TAG = namespace, "toc" chapters = aioxmpp.xso.ChildList([Chapter]) class Book(aioxmpp.xso.XSO): TAG = namespace, "book" id_ = aioxmpp.xso.Attr("id") author = aioxmpp.xso.ChildText((namespace, "author")) npages = aioxmpp.xso.ChildText( (namespace, "pages"), type_=aioxmpp.xso.Integer(), ) published = aioxmpp.xso.ChildText( (namespace, "published"), type_=aioxmpp.xso.Date(), ) title = aioxmpp.xso.ChildTextMap((namespace, "title")) toc = aioxmpp.xso.Child([TableOfContents]) class Library(aioxmpp.xso.XSO): TAG = namespace, "library" books = aioxmpp.xso.ChildList([Book]) ``` -------------------------------- ### Build documentation Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/README.md Generates the HTML documentation files in the local build directory. ```makefile make docs-html ``` -------------------------------- ### Build and view documentation Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/README.md Generates the HTML documentation and automatically opens it in the default web browser. ```makefile make docs-view-html ``` -------------------------------- ### Initialize and Connect XMPP Client Source: https://context7.com/jssfr/aioxmpp/llms.txt Demonstrates different ways to initialize and connect an aioxmpp client, including basic client, PresenceManagedClient, and context manager usage. Ensure you have a valid JID and security layer (password or other authentication). ```python import asyncio import aioxmpp async def connect_example(): # Create a JID from string jid = aioxmpp.JID.fromstr("user@example.org") # Create security layer with password security = aioxmpp.make_security_layer("your_password") # Option 1: Basic client (manual start/stop) client = aioxmpp.Client(jid, security) client.start() await client.established_event.wait() print(f"Connected as: {client.local_jid}") client.stop() # Option 2: PresenceManagedClient (auto-connects when presence is available) pmc = aioxmpp.PresenceManagedClient(jid, security) pmc.presence = aioxmpp.PresenceState(True) # Sets available, starts connection # Option 3: Context manager approach async with pmc.connected() as stream: print(f"Stream established: {pmc.local_jid}") await asyncio.sleep(5) # Automatically disconnects when context exits asyncio.run(connect_example()) ``` -------------------------------- ### Use DiscoClient service Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/quickstart.md Demonstrates summoning and using the DiscoClient service to query entity information. ```python client = aioxmpp.PresenceManagedClient( jid, aioxmpp.make_security_layer(password) ) disco = client.summon(aioxmpp.DiscoClient) async with client.connected() as stream: info = await disco.query_info( target_jid, ) ``` -------------------------------- ### Signal and Callback Patterns Source: https://context7.com/jssfr/aioxmpp/llms.txt Demonstrates various ways to connect to signals, including simple callbacks, manual disconnection, context managers, and future-based waiting. ```python import aioxmpp import aioxmpp.callbacks async def signals_example(client): # Simple function callback def on_established(): print("Stream established!") client.on_stream_established.connect(on_established) # Async callback with disconnect handle = client.on_stream_established.connect(on_established) handle.disconnect() # Remove callback # Context manager for temporary connection with client.on_stream_established.context_connect(on_established): # Callback active within this block pass # Automatically disconnected # Future-based waiting fut = client.on_stream_established.future() await fut # Waits for signal to fire once # Using AUTO_FUTURE for signal result conn_future = asyncio.Future() client.on_stream_established.connect( conn_future, client.on_stream_established.AUTO_FUTURE ) await conn_future ``` -------------------------------- ### Manage Pub/Sub Nodes and Subscriptions Source: https://context7.com/jssfr/aioxmpp/llms.txt Utilize PubSubClient to create, configure, subscribe to, publish to, and delete pub/sub nodes. Requires connection to a pub/sub service. ```python import asyncio import aioxmpp import aioxmpp.pubsub import aioxmpp.pubsub.xso as pubsub_xso async def pubsub_example(client): pubsub = client.summon(aioxmpp.PubSubClient) service_jid = aioxmpp.JID.fromstr("pubsub.example.org") node_name = "my_node" async with client.connected(): # Create a node await pubsub.create(service_jid, node_name) # Configure node (get current config first) config = await pubsub.get_node_config(service_jid, node_name) # Modify config.data as needed, then: # await pubsub.set_node_config(service_jid, node_name, config.data) # Subscribe to notifications def on_item_published(jid, node, item, **kwargs): print(f"New item on {jid}/{node}: {item.id_}") if item.registered_payload: print(f" Payload: {item.registered_payload}") def on_item_retracted(jid, node, id_, **kwargs): print(f"Item {id_} retracted from {jid}/{node}") pubsub.on_item_published.connect(on_item_published) pubsub.on_item_retracted.connect(on_item_retracted) # Subscribe to node subscription = await pubsub.subscribe(service_jid, node=node_name) subid = subscription.payload.subid print(f"Subscribed with ID: {subid}") # Publish an item from aioxmpp.pubsub.xso import Item item = Item(id_="item1") # item.registered_payload = your_custom_xso await pubsub.publish(service_jid, node_name, item) # Get items from node items_result = await pubsub.get_items(service_jid, node=node_name, max_items=10) for item in items_result.payload.items: print(f"Item: {item.id_}") # Retract an item await pubsub.retract(service_jid, node_name, id_="item1") # Unsubscribe await pubsub.unsubscribe(service_jid, node=node_name, subid=subid) # Delete node await pubsub.delete(service_jid, node_name) ``` -------------------------------- ### Connect to XMPP Server Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/quickstart.md Establishes a connection using PresenceManagedClient and a security layer. ```python client = aioxmpp.PresenceManagedClient( jid, aioxmpp.make_security_layer(password) ) async with client.connected() as stream: ... ``` -------------------------------- ### Declare Message Dispatcher Dependency in aioxmpp Service Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/api/changelog.md Classes using aioxmpp.service.message_handler() must declare a message dispatcher in their dependencies. This example shows a backward-compatible way to conditionally declare SimpleMessageDispatcher. ```python class FooService(aioxmpp.service.Service): ORDER_AFTER = [] try: import aioxmpp.dispatcher except ImportError: pass else: ORDER_AFTER.append( aioxmpp.dispatcher.SimpleMessageDispatcher ) ``` -------------------------------- ### Using aioxmpp.xso.Date and aioxmpp.xso.Time Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/api/changelog.md Demonstrates the availability of aioxmpp.xso.Date and aioxmpp.xso.Time for XEP-0082 compliance, and aioxmpp.xso.DateTime for legacy formats. ```python aioxmpp.xso.Date aioxmpp.xso.Time aioxmpp.xso.DateTime ``` -------------------------------- ### Run aioxmpp unittests Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/installation.md Executes the unit tests for the aioxmpp library using the nosetests3 runner. Navigate to the source directory before running this command. ```bash cd path/to/source/of/aioxmpp nosetests3 tests ``` -------------------------------- ### Verify e2etest configuration Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/dev-guide/index.md Run a specific test case to validate that the e2etest configuration is correctly set up. ```console $ python3 -m aioxmpp.e2etest tests/test_e2e.py:TestConnect ``` -------------------------------- ### Upgrade pip on Debian Jessie Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/installation.md Upgrades setuptools and pip to their latest versions on Debian Jessie. This is necessary because the default pip version on Jessie does not support the '~=' version comparison operator required by aioxmpp. ```bash pip3 install --upgrade setuptools ``` ```bash pip3 install --upgrade pip ``` -------------------------------- ### Maintain compatibility for Disco service split Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/api/changelog.md Use this pattern to handle the transition from a single Service class to separate DiscoClient and DiscoServer classes. ```python try: from aioxmpp import DiscoClient, DiscoServer except ImportError: import aioxmpp.disco DiscoClient = aioxmpp.disco.Service DiscoServer = aioxmpp.disco.Service ``` -------------------------------- ### Run unit tests with Nose Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/dev-guide/index.md Execute the standard test suite using the nosetests3 runner from the repository root. ```console $ nosetests3 tests ``` -------------------------------- ### Manage Peer Presence with PresenceClient Source: https://context7.com/jssfr/aioxmpp/llms.txt Use PresenceClient to track peer presence and PresenceServer to manage outgoing presence broadcasts. Set presence state with available and show values, and connect event handlers for presence changes. ```python import asyncio import aioxmpp async def presence_example(client): # Track peer presence presence_client = client.summon(aioxmpp.PresenceClient) # Manage own presence presence_server = client.summon(aioxmpp.PresenceServer) # Set presence state with show value presence_server.set_presence( aioxmpp.PresenceState(available=True, show=aioxmpp.PresenceShow.CHAT), status="Ready to chat!" ) # Available show values: # PresenceShow.NONE (default available) # PresenceShow.AWAY # PresenceShow.XA (extended away) # PresenceShow.DND (do not disturb) # PresenceShow.CHAT (free for chat) # Presence event handlers def on_peer_available(full_jid, stanza): state = aioxmpp.PresenceState.from_stanza(stanza) print(f"{full_jid} is now available: {state.show}") def on_peer_unavailable(full_jid, stanza): print(f"{full_jid} went offline") def on_peer_changed(full_jid, stanza): print(f"{full_jid} presence changed") presence_client.on_available.connect(on_peer_available) presence_client.on_unavailable.connect(on_peer_unavailable) presence_client.on_changed.connect(on_peer_changed) async with client.connected(): # Query presence for a specific JID peer = aioxmpp.JID.fromstr("friend@example.org") # Get all available resources for a bare JID resources = presence_client.get_peer_resources(peer) for resource, stanza in resources.items(): print(f"Resource {resource}: {stanza.show}") # Get most available resource best = presence_client.get_most_available_stanza(peer) if best: print(f"Most available: {best.from_}") await asyncio.sleep(300) ``` -------------------------------- ### Query Entity Capabilities with DiscoClient Source: https://context7.com/jssfr/aioxmpp/llms.txt Use DiscoClient to query an entity's capabilities and features. Requires an active client connection. ```python import asyncio import aioxmpp import aioxmpp.disco async def disco_example(client): disco = client.summon(aioxmpp.DiscoClient) disco_server = client.summon(aioxmpp.DiscoServer) async with client.connected(): target = aioxmpp.JID.fromstr("example.org") # Query server info info = await disco.query_info(target) print(f"Identities for {target}:") for identity in info.identities: print(f" {identity.category}/{identity.type_}: {identity.name}") print(f"Features:") for feature in info.features: print(f" {feature}") # Query items (e.g., chat rooms, services) items = await disco.query_items(target) for item in items.items: print(f"Item: {item.jid} - {item.name} (node: {item.node})") # Query a specific node node_info = await disco.query_info( target, node="http://jabber.org/protocol/commands" ) # Register custom identity on our client disco_server.register_identity( category="client", type_="bot", name="My XMPP Bot" ) # Register supported feature disco_server.register_feature("http://example.org/custom-feature") ``` -------------------------------- ### Obtain JID and Password Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/quickstart.md Collects user credentials for XMPP authentication. ```python jid = aioxmpp.JID.fromstr(input("JID: ")) password = getpass.getpass() ``` -------------------------------- ### PubSub Node Configuration Form Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/api/changelog.md Represents the configuration form for a PubSub node. ```python aioxmpp.pubsub.NodeConfigForm ``` -------------------------------- ### Configure SPHINXBUILD environment variable Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/README.md Sets the SPHINXBUILD variable to point to the correct sphinx-build executable if the default is not found. ```bash export SPHINXBUILD=sphinx-build ``` -------------------------------- ### PubSub Publish Options Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/api/changelog.md The publish_options argument for aioxmpp.PubSubClient.publish() allows specifying options when publishing to a node. ```python aioxmpp.PubSubClient.publish() ``` -------------------------------- ### Run end-to-end tests Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/dev-guide/index.md Execute integration tests against an XMPP server using the specialized aioxmpp.e2etest runner. ```console $ python3 -m aioxmpp.e2etest tests ``` -------------------------------- ### Capturing Raw XML Events with CapturingXSO Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/api/changelog.md Illustrates the use of aioxmpp.xso.CapturingXSO to capture raw XML events for creating XSO instances. This is useful for re-creating XML transcripts. ```python aioxmpp.xso.events_to_sax() ``` -------------------------------- ### Use PresenceClient service Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/quickstart.md Uses the PresenceClient service to monitor peer availability via signal connections. ```python client = aioxmpp.PresenceManagedClient( jid, aioxmpp.make_security_layer(password) ) def peer_available(jid): print("{} came online".format(jid)) def peer_unavailable(jid): print("{} went offline".format(jid)) presence = client.summon(aioxmpp.PresenceClient) presence.on_bare_available.connect(peer_available) presence.on_bare_unavailable.connect(peer_unavailable) async with client.connected() as stream: await asyncio.sleep(10) ``` -------------------------------- ### XSO Query Language Syntax Draft Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/xso-query.md Demonstrates the basic syntax for filtering events using the XSO Query Language, including direct property comparisons and the '@' operator for object extraction. ```default Message.from_ == "fnord", pubsub_xso.Event @ Message.xep0060_event, pubsub_xso.EventItems @ pubsub_xso.Event.payload, pubsub_xso.EventItems.node == "foo", ``` -------------------------------- ### Use `connected()` Context Manager for Clean Shutdown Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/pitfalls.md Use the `aioxmpp.Client.connected()` asynchronous context manager to ensure the client connection is closed cleanly when exiting the block, preventing lingering online states. ```python client = aioxmpp.Client() with client.connected() as stream: # stream is the aioxmpp.stream.StanzaStream of the client # do something ``` -------------------------------- ### Define and parse an XSO object Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/an-introduction-to-xso.md Demonstrates defining a class inheriting from aioxmpp.xso.XSO with attributes and child text descriptors, then parsing XML data into an instance of that class. ```python >>> data = \ ... b"" \ ... b"some text" \ ... b"" >>> namespace = "urn:uuid:203ef66e-4423-49f2-90c9-3cb160986734" >>> class Node(aioxmpp.xso.XSO): ... TAG = namespace, "node" ... attr = aioxmpp.xso.Attr("a1") ... data = aioxmpp.xso.ChildText((namespace, "child")) ... >>> buf = io.BytesIO(data) >>> n = aioxmpp.xml.read_single_xso(buf, Node) >>> isinstance(n, Node) True >>> n.attr 'foo' >>> n.data 'some text' ``` -------------------------------- ### Message Dispatching Transition Path Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/message-dispatching.md Outlines the potential transition paths for integrating the new message dispatching system with the existing StanzaStream methods. ```APIDOC ## Transition path for existing StanzaStream methods ### Option 1: Multiple Message Dispatchers Allow multiple Message Dispatchers. A default dispatcher is provided, and existing methods simply redirect to it. This maintains backward compatibility. ### Option 2: Single Message Dispatcher (Legacy Default) Allow only a single Message Dispatcher. A legacy dispatcher is created by default, and existing methods redirect to it. Changes to the message dispatcher will result in loud failures if callbacks are still registered. ### Option 3: Immediate Deletion Delete the existing StanzaStream methods immediately, requiring all users to migrate to the new dispatcher interface. ``` -------------------------------- ### Global e2etest configuration Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/dev-guide/index.md Define global settings for the e2etest runner in an INI-style configuration file. ```ini [global] timeout=1 provisioner= ``` -------------------------------- ### XSO Query Language Alternative Syntax Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/xso-query.md Presents an alternative syntax for the XSO Query Language using the '/' operator to chain property accesses and perform filtering. ```default Message.from_ == "fnord", (Message.xep0060_event / pubsub_xso.Event.payload / pubsub_xso.EventItems.node == "foo"), ``` -------------------------------- ### Console Output of Library Parsing Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/an-introduction-to-xso.md The expected output when running the `library_load.py` script with the `library_test.xml` file. This shows the parsed book data printed to the console. ```console $ python3 library_load.py library_test.xml book (id = 'foo'): author: F. Nord published: 2099-01-01 npages: 23 title: [en] 'The Amazing Life of Foo' [de] 'Das Faszinierende Leben des Foo' table of contents: 1. (page 1) [en] 'The Birth of Foo' [de] 'Die Geburt des Foo' 2. (page 3) [en] 'The Death of Foo' [de] 'Der Tod des Foo' book (id = 'pink-flamingos'): author: O. L. Bilderrahmen published: 2007-01-01 npages: 42 title: [en] 'The Relevance of Pink Flamingos to Computer Science' [de] 'Die Relevanz von rosa Flamingos für die Informatik' table of contents: ``` -------------------------------- ### Parse XML into Book Library Structure Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/an-introduction-to-xso.md Reads an XML file specified by a command-line argument and parses it into the defined Library XSO structure. Requires the `library_demo.py` file to be available. ```python import sys import aioxmpp.xml import library_demo with open(sys.argv[1], "r") as f: library = aioxmpp.xml.read_single_xso(f, library_demo.Library) for book in library.books: print("book (id = {!r}):".format(book.id_)) print(" author:", book.author) print(" published:", book.published) print(" npages:", book.npages) print(" title:") for lang, title in book.title.items(): print(" [{!s}] {!r}".format(lang, title)) print(" table of contents:") for i, chapter in enumerate(book.toc.chapters, 1): print(" {}. (page {})".format(i, chapter.start_page)) for lang, title in chapter.title.items(): print(" [{!s}] {!r}".format(lang, title)) ``` -------------------------------- ### Manual Client Shutdown with Future Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/pitfalls.md If the `connected()` context manager cannot be used, this snippet shows how to manually ensure `aioxmpp.Client.stop()` is called and the client has time to shut down cleanly by connecting to `on_stopped` and `on_failure` signals. ```python if client.running: fut = asyncio.Future() client.on_stopped.connect(fut, client.on_stopped.AUTO_FUTURE) client.on_failure.connect(fut, client.on_failure.AUTO_FUTURE) try: yield from fut except: # we are shutting down, ignore any exceptions from on_failure pass ``` -------------------------------- ### React to Messages with SimpleMessageDispatcher Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/quickstart.md Registers a callback to handle incoming messages using the SimpleMessageDispatcher service. ```python import aioxmpp.dispatcher def message_received(msg): print(msg) # obtain an instance of the service (we’ll discuss services later) message_dispatcher = client.summon( aioxmpp.dispatcher.SimpleMessageDispatcher ) ``` -------------------------------- ### Send XMPP Messages Source: https://context7.com/jssfr/aioxmpp/llms.txt Illustrates sending different types of XMPP messages using `client.send()` for request-response or `client.enqueue()` for fire-and-forget. Supports multilingual message bodies using `LanguageMap`. Ensure a connected client instance is available. ```python import asyncio import aioxmpp async def send_messages(client): recipient = aioxmpp.JID.fromstr("friend@example.org") # Create a chat message msg = aioxmpp.Message( type_=aioxmpp.MessageType.CHAT, to=recipient ) # Set message body (None key means no language tag) msg.body[None] = "Hello, World!" # Multi-language body msg.body[aioxmpp.structs.LanguageTag.fromstr("en")] = "Hello!" msg.body[aioxmpp.structs.LanguageTag.fromstr("de")] = "Hallo!" # Send and wait for transmission await client.send(msg) # Or use enqueue for non-blocking send (returns StanzaToken) token = client.enqueue(msg) print(f"Message queued with token: {token}") # Create a reply to a received message received_msg = msg # Assume we received this reply = received_msg.make_reply() reply.body[None] = "Got your message!" await client.send(reply) # Message types available: # aioxmpp.MessageType.CHAT - One-to-one chat # aioxmpp.MessageType.GROUPCHAT - Multi-user chat # aioxmpp.MessageType.NORMAL - Standalone message (like email) # aioxmpp.MessageType.HEADLINE - Alerts/notifications # aioxmpp.MessageType.ERROR - Error response ``` -------------------------------- ### Handle JID (Jabber ID) Objects Source: https://context7.com/jssfr/aioxmpp/llms.txt Shows how to create, manipulate, and query JID objects, which represent XMPP addresses. JIDs are immutable and validated upon creation. Use `jid_escape` and `jid_unescape` for special characters in the localpart. ```python import aioxmpp # Create JID from string jid = aioxmpp.JID.fromstr("user@example.org/resource") # Access components print(f"Localpart: {jid.localpart}") # "user" print(f"Domain: {jid.domain}") # "example.org" print(f"Resource: {jid.resource}") # "resource" # Create JID from components jid2 = aioxmpp.JID("user", "example.org", "mobile") # Get bare JID (without resource) bare_jid = jid.bare() print(f"Bare JID: {bare_jid}") # "user@example.org" # Check JID properties print(f"Is bare: {bare_jid.is_bare}") # True print(f"Is domain: {bare_jid.is_domain}") # False # Create modified JID new_jid = jid.replace(resource="new_resource") # JID escaping for special characters in localpart escaped = aioxmpp.jid_escape("user/name@domain") original = aioxmpp.jid_unescape(escaped) ``` -------------------------------- ### Handle presence updates Source: https://github.com/jssfr/aioxmpp/blob/devel/docs/user-guide/quickstart.md Registers a callback to react to available presence stanzas. ```python import aioxmpp.dispatcher def available_presence_received(pres): print(pres) presence_dispatcher = client.summon( aioxmpp.dispatcher.SimplePresenceDispatcher, ) presence_dispatcher.register_callback( aioxmpp.PresenceType.AVAILABLE, None, available_presence_received, ) ```