From 7bbabb2988f9a97294694ae0b78767bee794a4ed Mon Sep 17 00:00:00 2001 From: friedkeenan Date: Tue, 31 Dec 2024 09:35:13 -0600 Subject: [PATCH] Increment version, add changelog --- docs/source/changelog.rst | 9 +++ docs/source/changelog/v1.0.0.rst | 9 +++ docs/source/changelog/v1.1.0.rst | 63 +++++++++++++++++++ docs/source/index.rst | 3 +- .../tutorials/protocol_matching/basic.rst | 2 +- .../tutorials/protocol_matching/handle.rst | 2 +- pak/packets/packet.py | 8 +-- pak/packets/packet_handler.py | 4 +- pak/types/deferring.py | 2 +- pak/types/misc.py | 2 +- pyproject.toml | 2 +- 11 files changed, 95 insertions(+), 11 deletions(-) create mode 100644 docs/source/changelog.rst create mode 100644 docs/source/changelog/v1.0.0.rst create mode 100644 docs/source/changelog/v1.1.0.rst diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst new file mode 100644 index 0000000..c539e2d --- /dev/null +++ b/docs/source/changelog.rst @@ -0,0 +1,9 @@ +Changelog +========= + +See what's new in each version of Pak: + +.. toctree:: + + changelog/v1.1.0 + changelog/v1.0.0 diff --git a/docs/source/changelog/v1.0.0.rst b/docs/source/changelog/v1.0.0.rst new file mode 100644 index 0000000..1dcb397 --- /dev/null +++ b/docs/source/changelog/v1.0.0.rst @@ -0,0 +1,9 @@ +v1.0.0 +====== + +:Date: June 16, 2023 + +Changes +******* + +The initial release of Pak. No changes to report! diff --git a/docs/source/changelog/v1.1.0.rst b/docs/source/changelog/v1.1.0.rst new file mode 100644 index 0000000..ce46414 --- /dev/null +++ b/docs/source/changelog/v1.1.0.rst @@ -0,0 +1,63 @@ +v1.1.0 +====== + +:Date: TODO + +Changes +******* + +- Drop support for Python 3.7. + +- Implement an asynchronous unpacking API. + - This allows users to unpack asynchronously using coroutines and the ``await`` syntax, which may in certain cases be necessary or otherwise desirable. + - Where there is something that involves unpacking, there will be an asynchronous version of it suffixed with ``_async``, including the following: + - The :meth:`.Type.unpack_async` method. + - The :meth:`.Packet.unpack_async` method. + - The new functions in the :mod:`.test` module. + - All :class:`.Type`\s in Pak provide both the synchronous and asynchronous unpacking APIs, however custom :class:`.Type`\s are empowered to only provide one or the other, as often only one will be relevant to a certain usecase. + +- Add :class:`.DeferringType`. + - This allows a :class:`.Type` to defer its behavior to another :class:`.Type` of its choosing depending on the relevant :class:`.Type.Context`. This is useful, for instance, if you are supporting multiple versions of a protocol which might have different fields act like different :class:`.Type`\s depending on the protocol version. + +- Improve customizing the endianness of :class:`.StructType`. + - The following methods were added to be able to tersely specify the desired endianness of a :class:`.StructType`: + - :meth:`.StructType.little_endian` + - :meth:`.StructType.big_endian` + - :meth:`.StructType.native_endian` + - This allows users to, for instance, call ``pak.UInt16.big_endian()`` in order to use a big-endian :class:`.UInt16`, instead of the default little-endian version. + +- Add :class:`.LEB128.Limited` and :class:`.ULEB128.Limited`. + - These allow users to limit the maximum number of bytes that a :class:`.LEB128` or :class:`.ULEB128` may have, which may be useful to prevent malicious actors from always setting the top bit of each byte to cause unpacking to never end. + +- Reorder the bases of the returned class of :meth:`.Packet.GenericWithID` to have more intuitive behavior. + - The ``data`` field from :class:`.GenericPacket` is now situated at the end of the :class:`.Packet`, so that it will capture any remaining uncaptured data after the rest of the fields. + +- Give :class:`.EmptyType` an alignment of ``1``. + - This better allows fields to be effectively "disabled" in an aligned context, such as when using :class:`.AlignedPacket`. + +- Give :class:`.RawByte` an alignment of ``1``. + +- Refactor :class:`.Array` to use specialized subclasses. + - These specialized subclasses are: + - :class:`.Array.FixedSize` + - :class:`.Array.SizePrefixed` + - :class:`.Array.Unbounded` + - :class:`.Array.FunctionSized` + +- Refactor :class:`.Optional` to use specialized subclasses. + - These specialized subclasses are: + - :class:`.Optional.PrefixChecked` + - :class:`.Optional.Unchecked` + - :class:`.Optional.FunctionChecked` + +- Add :exc:`.Type.UnsuppressedError`. + - Exceptions which inherit from :exc:`.Type.UnsuppressedError` indicate unambiguous errors in logic, which should not be suppressed by certain :class:`.Type` facilities like :class:`.Array.Unbounded` and :class:`.Optional.Unchecked`. + +- :class:`.Type`\s in Pak now more consistently raise errors if they are unable to read enough data when unpacking. + +- Make the :meth:`.Type.prepare_types` decorator remove all parameter annotations of :class:`.Type` from its decorated function. + - This prevents potentially confusing annotations of :class:`.Type` from leaking out into documentation or other tools where those annotations may be misinterpreted. For instance, they could be mistaken as type hints. Parameter annotations of :class:`.Type` when using :meth:`.Type.prepare_types` are only internally relevant, and should not be shown externally. + +- Restrict certain function parameters to being positional-only in order to better enforce caching. + +- Fix typo in the name of :meth:`.PacketHandler.unregister_packet_listener`, which was previously named ``unregsiter_packet_listener``. diff --git a/docs/source/index.rst b/docs/source/index.rst index 87b3b6a..d26118e 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,5 +1,5 @@ Pak: A General Purpose Packet Marshaling Library -=========================================================== +================================================ **Pak** is a simple, yet powerful and extendable Python library for translating between raw data and usable, meaningful values. @@ -64,6 +64,7 @@ Table of Contents tutorials reference + changelog Indices and Tables diff --git a/docs/source/tutorials/protocol_matching/basic.rst b/docs/source/tutorials/protocol_matching/basic.rst index 8c4657c..855eb22 100644 --- a/docs/source/tutorials/protocol_matching/basic.rst +++ b/docs/source/tutorials/protocol_matching/basic.rst @@ -151,7 +151,7 @@ This code is *much* more readable. It could even be made more readable with ``ma ---- -But let's say somehow, when we, the server, try to read the ``CatPicturesRequest`` packet, the data we get is ``b"\x03"``, corresponding to an unsigned byte value of ``3``. This could happen for instance if the client is using a newer version of the protocol that uses the value ``3`` to ask for the number of *hairless* cat pictures, or perhaps we're communicating with a malicious client who's trying to expose flaws in our code by sending unexpected values. Let's see what happens: +But let's say somehow, when we, the server, try to read the ``CatPicturesRequest`` packet, the data we get is ``b"\x03"``, corresponding to an unsigned byte value of ``3``. This could happen, for instance, if the client is using a newer version of the protocol that uses the value ``3`` to ask for the number of *hairless* cat pictures, or perhaps we're communicating with a malicious client who's trying to expose flaws in our code by sending unexpected values. Let's see what happens: .. testcode:: diff --git a/docs/source/tutorials/protocol_matching/handle.rst b/docs/source/tutorials/protocol_matching/handle.rst index c54bf64..fe738b2 100644 --- a/docs/source/tutorials/protocol_matching/handle.rst +++ b/docs/source/tutorials/protocol_matching/handle.rst @@ -165,7 +165,7 @@ Packet listeners can also be associated with certain "flags" that must match wit def on_info_request(self, packet): self.write_packet(CatInfoResponse(...)) -This would then let us leverage our packet listening infrastructure for packets we send too, which could for instance be used for debugging purposes to print all the packets we send or to otherwise have special logic for whenever we send a certain packet. Here our listeners would only be called when receiving packets, because they have the ``outgoing`` flag set to ``False``. Since it's annoying and error-prone to always specify the ``outgoing`` flag, we can make it default to ``False`` (or make specifying it required if we wanted to) by overriding the :meth:`.PacketHandler.register_packet_listener` method, like so:: +This would then let us leverage our packet listening infrastructure for packets we send too, which could, for instance, be used for debugging purposes to print all the packets we send or to otherwise have special logic for whenever we send a certain packet. Here our listeners would only be called when receiving packets, because they have the ``outgoing`` flag set to ``False``. Since it's annoying and error-prone to always specify the ``outgoing`` flag, we can make it default to ``False`` (or make specifying it required if we wanted to) by overriding the :meth:`.PacketHandler.register_packet_listener` method, like so:: class FelinePacketHandler(pak.PacketHandler): def register_packet_listener(self, listener, *packet_types, outgoing=False, **flags): diff --git a/pak/packets/packet.py b/pak/packets/packet.py index 457a4fb..69708c7 100644 --- a/pak/packets/packet.py +++ b/pak/packets/packet.py @@ -359,12 +359,12 @@ def GenericWithID(cls, id, /): Parameters ---------- id - The ID of the generated :class:`GenericPacket`. + The ID of the generated :class:`Packet`. Returns ------- - :class:`GenericPacket` - The generated :class:`GenericPacket`. + subclass of :class:`Packet` + The generated :class:`Packet`. Examples -------- @@ -414,7 +414,7 @@ def EmptyWithID(cls, id, /): Returns ------- - :class:`Packet` + subclass of :class:`Packet` The generated :class:`Packet`. Examples diff --git a/pak/packets/packet_handler.py b/pak/packets/packet_handler.py index 7ba768b..e473335 100644 --- a/pak/packets/packet_handler.py +++ b/pak/packets/packet_handler.py @@ -386,12 +386,14 @@ def has_packet_listener(self, packet, **flags): >>> ex = Example() >>> ex.has_packet_listener(MyPacket()) True - >>> ex.has_packet_listener(pak.Packet) + >>> ex.has_packet_listener(pak.Packet()) False >>> >>> # You can also get whether a 'Packet' class has a listener: >>> ex.has_packet_listener(MyPacket) True + >>> ex.has_packet_listener(pak.Packet) + False """ for packet_types, listener_flags in self._packet_listeners.values(): diff --git a/pak/types/deferring.py b/pak/types/deferring.py index 52e8172..65714d6 100644 --- a/pak/types/deferring.py +++ b/pak/types/deferring.py @@ -13,7 +13,7 @@ class DeferringType(Type): to a certain :class:`.Type` depending on what it decides to return from its :meth:`_defer_to` method. - This deferring of behavior is useful for instance in + This deferring of behavior is useful, for instance, in protocols with multiple versions, where you may want to have a :class:`.Packet` field act like a different :class:`.Type` between different protocol versions. diff --git a/pak/types/misc.py b/pak/types/misc.py index 67bbad8..93a8e8e 100644 --- a/pak/types/misc.py +++ b/pak/types/misc.py @@ -17,7 +17,7 @@ class EmptyType(Type): It always unpacks to ``None`` and always packs to ``b""``. It is useful in certain cases when you - would want to "disable" a packet field for instance. + would want to "disable" a packet field, for instance. ``None`` is a typelike value that translates to :class:`EmptyType`. diff --git a/pyproject.toml b/pyproject.toml index 00a112d..8eb3a29 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "pak" -version = "1.0.0" +version = "1.1.0" description = "A general purpose packet marshaling library" readme = "README.md" requires-python = ">=3.8"