Migrating from katcp-python =========================== While aiokatcp is loosely inspired by the katcp-python API, it does not strictly follow it. There are a number of changes that you will need to make to port code from katcp-python to aiokatcp. This section tries to list some of the most important: Messages -------- - The message arguments are pass to :class:`~aiokatcp.core.Message` as a `*args`, rather than a single list argument. - The `mid` (message ID) argument is keyword-only. - The message types are an enum, :class:`.Message.Type`. Types ----- - The kattypes types (:class:`Int` etc) have been replaced by plain Python types and a type registration system. The discrete type has been replaced by enums. - In katcp-python, addresses were represented as a tuple of a string and an integer. In aiokatcp, it is a full-blown class (:class:`~aiokatcp.core.Address`) and the host part uses the :mod:`ipaddress` module. - :class:`~.TimestampOrNow` is not a real type. Instead, it is an alias for ``Union[Timestamp, Now]``. The actual value received on decoding is either a :class:`~.Timestamp` or is :const:`.Now.NOW`. Device server ------------- - :attr:`VERSION_INFO` and :attr:`BUILD_INFO` tuples are replaced by :attr:`~.DeviceServer.VERSION` and :attr:`~.DeviceServer.BUILD_STATE` (to match the terminology in the specification) and they are strings (to give greater freedom in version format). - The ``@request`` and ``@return_reply`` decorators no longer exist, as they are effectively the defaults, and the type information is provided by Python type annotations. - The return code (``ok``, ``fail`` or ``invalid``) no longer forms part of the handler return value. Returning a value implies ``ok`` while raising an exception implies ``fail``. It's now also acceptable to return nothing, which will send an ``ok`` without further arguments if no reply has been sent. - :exc:`AsyncReply` is gone. All request handlers are asynchronous now. If you need to serialise access to the device, use asyncio locks. - Instead of :meth:`add_sensor` and so on, there is a :attr:`.DeviceServer.sensors` attribute that behaves like either a dictionary or a set. Sensors ------- - The status is now an enum type, :class:`.Sensor.Status`. - There is no Observer class: just pass a callable. General ------- - Because it is required for Python 3, there is now careful separation between strings (Unicode) and bytes. See :doc:`unicode` for more details. - There is no direct support for Tornado, as everything runs on the asyncio event loop. Refer to Tornado documentation for how to bridge Tornado and asyncio code. - None of the code is thread-safe, including sensor updates. It is recommended that code using aiokatcp is single-threaded, but where that is not possible it needs to use asyncio primitives (such as :meth:`AbstractEventLoop.call_soon_threadsafe`) to ensure that aiokatcp structures are touched only by the thread running the event loop. - None of the functions have timeout parameters. Instead, you can cancel coroutines, for example, using `async_timeout`_. .. _async_timeout: https://github.com/aio-libs/async-timeout