AsyncAPY’s package

The AsyncAProto Client

Warning

This is the client used to connect to AsyncAPY server and is different from the internal object passed to handlers located here

class asyncapy.client.Client(byteorder: Optional[str] = 'big', header_size: Optional[int] = 4, tls: Optional[bool] = True, encoding: Optional[str] = 'json', timeout: Optional[int] = 60)

Bases: object

Basic Python implementation of an AsyncAProto client

Parameters:
  • byteorder (str) – The client’s byteorder, can either be "big" or "little". Defaults to "big" (standard)
  • header_size (int) – The size in bytes of the Content-Length header for packets, defaults to 4 (standard)
  • tls (optional, bool) – Instructs the client to use the Transport Layer Security encryption standard for the underlying TCP connection, defaults to True. Recommended for production servers
  • encoding – The session’s payload type, used to encode and decode packets. Defaults to "json", but another valid option is "ziproto" (a custom encoding which is more compact, but less flexible and not human-readable, recommended for when the information is not meant to be seen by the general public)
  • timeout (int, optional) – The max. duration in seconds to read the socket before timing out, defaults to 60
connect(hostname: str, port: int)

Connects to the given hostname and port

Parameters:
  • hostname (str) – The address of the server to connect to
  • port (int) – The port of the server to connect to
disconnect()

Closes the underlying TCP socket. No further action is needed client-side as the server will automatically drop its end of the pipe when it notices that the client is gone

receive() → Dict[Any, Any]

Receives a complete AsyncAproto packet and returns the decoded payload

receive_raw() → bytes

Reads the internal socket until an entire AsyncAproto packet is complete and returns the raw packet (including headers). An empty byte string is returned if the socket gets closed abruptly

send(payload: Union[str, Dict[Any, Any]])

Sends the given payload across the underlying TCP connection as a proper AsyncAproto packet

Parameters:payload (dict or str, optional) – The payload to send to the server. Pass either a dictionary object or a valid JSON string

AsyncAPY core modules and resources

class asyncapy.core.Client(address: str, server, stream: trio.SocketStream, session: str, encoding: str)

Bases: object

High-level wrapper around AsyncAproto clients

Parameters:
  • address (str) – The client’s IP address
  • server (Server) – The server object (created internally), needed to send back packets
  • stream – The trio socket object associated with the client
  • session (str) – The session_id of the client, defaults to None. Note that, internally, this parameter is replaced with a Session object
  • encoding (str) – The client’s encoding (which can’t change across the session). It can either ‘json’ or ‘ziproto’
close()

Closes the client connection

get_sessions()

Returns all the active sessions associated with the client’s IP address

send(packet, close: bool = False)

Sends the given packet to the client

Parameters:
  • packet (Packet) – A Packet object
  • close (bool, optional) – If True, the connection will be closed right after the packet is sent. Set this to False to take full advantage of packet propagation, defaults to False
class asyncapy.core.Handler(function: function, filters: Optional[List[asyncapy.filters.Filter]] = None)

Bases: object

An object meant for internal use. Every function is wrapped inside a Handler object together with its filters

Parameters:
  • function (FunctionType) – The asynchronous function, accepting two positional parameters (a Client and a Packet object)
  • filters (Optional[List[Filter]], optional) – An optional list of Filter objects, defaults to None
call(*args)

Calls self.function asynchronously, passing *args as parameters

check(client: asyncapy.core.Client, packet: asyncapy.core.Packet)

Iteratively calls the check method on self.filters. Returns True if all filters pass, False otherwise

Parameters:
  • client – The client to check for
  • packet – The packet object to check for
Returns:

True if the handler matches all filters, False otherwise

Return type:

bool

class asyncapy.core.Packet(fields: Union[dict, str, bytes], encoding: str, sender: Optional[asyncapy.core.Client] = None)

Bases: object

High-level wrapper around AsyncAProto packets. Packet objects behave mostly like Python dictionaries and can be iterated over, used with the in operator and support getitem expressions with []

Parameters:
  • fields (Union[dict, str, bytes]) – The packet’s payload: it can either be a dictionary or valid JSON string (it can also be encoded as bytes)
  • encoding (str) – The payload desired encoding, it can either be "json" or "ziproto"
  • sender (Client, optional) – This parameter is meant to be initialized internally, and points to the Client object that sent the associated payload, defaults to None
stop_propagation()

Stops a packet from being propagated, see StopPropagation

Raises:StopPropagation
class asyncapy.core.Session(session_id: uuid.uuid4, client: asyncapy.core.Client, date: float)

Bases: object

A client session

Parameters:
  • session_id – The UUID of the session
  • client – The client object associated with the current session
  • date (float) – The UNIX Epoch timestamp of when the session was created
close()

Closes the associated client connection

get_client()

Returns the associated client object

Exceptions

exception asyncapy.errors.StopPropagation

Bases: Exception

This exception is meant to be raised when Packet’s stop_propagation method gets called to prevent the dispatcher forwarding the packet to the next handler in the queue.

This is useful when using groups, to learn more click here and scroll down to “Groups”

Filters

class asyncapy.filters.Filter

Bases: abc.ABC

The standard base for all filters

check(c, p)

Dummy check method

class asyncapy.filters.Filters

Bases: asyncapy.filters.Filter

This class implements all the filters in AsyncAPY

class APIFactory(factory: asyncapy.util.APIKeyFactory, field_name: str)

Bases: asyncapy.filters.Filter

A class that wraps around the APIKeyFactory class and its children, but as a filter. This filter passes if the provided field name is in the incoming packet and its value is a valid API key inside self.factory

Parameters:
  • factory (APIKeyFactory) – The APIKeyFactory object
  • field_name (str) – The name of the field to lookup into incoming packets, if the field is not present the filter won’t pass
check(_, p)

Implements the method to check if a filter matches a given packet/client pair

Parameters:
  • _ (Client) – A client object
  • p – A packet object
Returns:

True if the filter passed, False otherwise

Return type:

bool

class Fields(**kwargs)

Bases: asyncapy.filters.Filter

Filters fields inside packets. This filter accepts an unlimited number of keyword arguments, that can either be None, or a valid regex. In the first case, the filter will match if the payload contains the specified field name, while in the other case the field’s value will also be validated against re.match(), using the provided parameter as pattern.

Parameters:kwargs – A list of key-word arguments, which reflects the desired key-value structure of a payload
check(_, p)

Implements the method to check if a filter matches a given packet/client pair

Parameters:
  • _ (Client) – A client object
  • p (Client) – A packet object
Returns:

True if the packet’s payload follows the given structure, False otherwise

Return type:

bool

class Ip(ips: Union[List[str], str])

Bases: asyncapy.filters.Filter

Filters one or more IP addresses, allowing only the ones inside the filter to pass

Note: This filter is dynamic, it can be updated at runtime if assigned to a variable

Parameters:ips (Union[List[str], str]) – An ip or a list of ip addresses
Raises:ValueError – If the provided ip, or ips, isn’t a valid IP address
check(c, _)

Implements the method to check if a filter matches a given packet/client pair

Parameters:
  • c (Client) – A client object
  • _ (Packet) – A packet object
Returns:

True if the client’s IP is in the filters, False otherwise

Return type:

bool

check(c, p)

Dummy check method

The AsyncAPY Server

class asyncapy.server.Server(addr: Optional[str] = '127.0.0.1', port: Optional[int] = 8081, buf: Optional[int] = 1024, logging_level: int = 20, console_format: Optional[str] = '[%(levelname)s] %(asctime)s %(message)s', datefmt: Optional[str] = '%d/%m/%Y %H:%M:%S %p', timeout: Optional[int] = 60, header_size: int = 4, byteorder: str = 'big', config: str = None, cfg_parser=None, session_limit: int = 0)

Bases: object

AsyncAPY server class

Parameters:
  • addr (str, optional) – The address to which the server will bind to, defaults to '127.0.0.1'
  • port (int, optional) – The port to which the server will bind to, defaults to 8081
  • buf (int, optional) – The size of the TCP buffer, defaults to 1024
  • logging_level (int, optional) – The logging level for the logging module, defaults to 10 (DEBUG)
  • console_format (str, optional) – The output formatting string for the logging module, defaults to '[%(levelname)s] %(asctime)s %(message)s'
  • datefmt (str, optional) – A string for the logging module to format date and time, see the logging module for more info, defaults to '%d/%m/%Y %H:%M:%S %p'
  • timeout (int, optional) – The timeout (in seconds) that the server will wait before considering a connection as dead and close it, defaults to 60
  • header_size (int, optional) – The size of the Content-Length header can be customized. In an environment with small payloads a 2-byte header may be used to reduce overhead, defaults to 4
  • byteorder (str, optional) – The order that the server will follow to read packets. It can either be 'little' or 'big', defaults to 'big'
  • config (str, None, optional) – The path to the configuration file, defaults to None (no config)
  • cfg_parser (class: configparser.ConfigParser()) – If you want to use a custom configparser object, you can specify it here
  • session_limit (int, optional) – Defines how many concurrent sessions a client can instantiate, defaults to 0 (no limit)
add_handler(*filters, **kwargs)

Registers an handler, as a decorator. This does the same of register_handler, but in a cleaner way.

Parameters:
  • handler (FunctionType) – A function object
  • filters (Filter, optional) – Pass one or more filters to allow only a subset of client/packet pair to reach your handler
  • group (int, optional) – The group id, default to 0
register_handler(handler, *filters, **kwargs)

Registers an handler

Parameters:
  • handler (FunctionType) – A function object
  • filters (Filter, optional) – Pass one or more filters to allow only a subset of client/packet pair to reach your handler
  • group (int, optional) – The group id, default to 0
run_sync_task(sync_fn, *args, cancellable=False, limiter=None)

Convert a blocking operation into an async operation using a thread.

This is just a shorthand for trio.to_thread.run_sync(), check trio’s documentation to learn more

setup()

This method is called when the server is started and it has been thought to be overridden by a custom user defined class to perform pre-startup operations

shutdown()

This method is called when the server shuts down and it has been thought to be overridden by a custom user defined class to perform post-shutdown operations

Note that this method is called only after a proper KeyboardInterrupt exception is raised

start()

Starts serving asynchronously on self.addr:self.port

Extra utilities

class asyncapy.util.APIKeyFactory(size: int = 32)

Bases: object

Generic class to manage a basic storage of API subscriptions and implementing functionality to issue, revoke and reissue keys. This is a sort of dummy class (keys are stored in memory) and should be subclassed by user-defined classes to implement different storage solutions

Parameters:size (int, optional) – The desired size of the API key. By default it’s just a random string, defaults to 32
get(key: str) → dict

Returns the associated metadata with the given key, raises KeyError if the key doesn’t exist

Parameters:key (str) – The API key
Returns:The associated metadata with the given API key
Return type:str
Raises:KeyError – If the given key does not exist
issue(metadata: dict = None)

Returns a new random API key of self.size length, saves it and attaches to it the given metadata

Parameters:metadata (dict, optional) – A dictionary object containing meaningful information that is returned with the get method. Defaults to None
Returns key:The generated API key
Return type:str
reissue(key: str) → str

Reissues an API key, replacing the old key with a new one, keeping the old metadata

Parameters:key (str) – The API key to reissue
Raises:KeyError – If the given key does not exist
Returns:The new API key
revoke(key: str)

Revokes an API key, removing its associated data from the internal dictionary

Parameters:key (str) – The API key to revoke
Raises:KeyError – If the given key does not exist
update(key: str, metadata: dict)

Updates the associated metadata for the given key with the provided value

Parameters:
  • key (str) – The API key to update data for
  • metadata (dict) – A dictionary object containing meaningful information that is returned with the get method
Raises:

KeyError – If the given key does not exist