Skip to content

Allow for easier construction of serializable objects#309

Closed
LivInTheLookingGlass wants to merge 17 commits intomsgpack:masterfrom
LivInTheLookingGlass:patch-1
Closed

Allow for easier construction of serializable objects#309
LivInTheLookingGlass wants to merge 17 commits intomsgpack:masterfrom
LivInTheLookingGlass:patch-1

Conversation

@LivInTheLookingGlass
Copy link
Copy Markdown

@LivInTheLookingGlass LivInTheLookingGlass commented Sep 4, 2018

This pull request is similar to vsergeev/u-msgpack-python#37 and has a fully compatible API.

This PR adds the ability to usefully inherit from ExtType. It changes three things:

  1. Make Ext an alias for ExtType, to increase compatibility between this and umsgpack
  2. Ensures that Ext inherits from object, so that we can detect its subclasses
  3. Detects subclasses of Ext at unpack time, so that these classes do not need ext_handlers

In python3, you can have the pretty NamedTuple version by inheriting from an initially defined class. In python2, you can inherit from a function call to namedtuple(). In both cases, all that needs to happen is for the class to define a type/code variable, to define a data variable/property, and to define an _unpackb method for msgpack to hook onto.

This PR enables the following in Python 3

from typing import NamedTuple
from msgpack import Ext, packb, unpackb
# Note that Ext is now an alias for ExtType, allowing 1 char
# change between libraries


class _Serializable3(NamedTuple):
    foo: str
    bar: int


class Serializable3(Ext, _Serializable3):
    type = 1

    def __init__(self, *args, **kwargs):
        super().__init__(Serializable3.type, packb(self[:]))

    @classmethod
    def _unpackb(cls, ext: Ext) -> 'Serializable3':
        return cls(*unpackb(ext.data))


class Serializable3Alt(Ext, NamedTuple('_Serializable3Alt', [('foo', str), ('bar', int)])):
    code = 2  # code works as well, if you'd like

    def __init__(self, *args, **kwargs):
        super().__init__(Serializable3Alt.type, packb(self[:]))

    @classmethod
    def _unpackb(cls, ext: Ext) -> 'Serializable3Alt':
        return cls(*unpackb(ext.data))

And the following in Python 2 or 3:

from collections import namedtuple
from msgpack import Ext, packb, unpackb


class Serializable2(Ext, namedtuple('_Serializable2', ['foo', 'bar'])):
    type = 3

    def __init__(self, *args, **kwargs):
        super(Serializable2, self).__init__(Serializable2.type, packb(self[:]))

    @classmethod
    def _unpackb(cls, ext):
        return cls(*unpackb(ext.data))

This also enables for more flexible serialization through the use of dynamically calculated data:

from msgpack import Ext, packb, unpackb


class SerializableStub(Ext):
    type = 4

    def __init__(self, foo):
        self.foo = foo
        # note that Ext is not initialized for this style

    @property
    def data(self):
        return packb((self.foo, ))

    @classmethod
    def _unpackb(cls, ext):
        return cls(*unpackb(ext.data))

LivInTheLookingGlass added a commit to LivInTheLookingGlass/u-msgpack-python that referenced this pull request Sep 6, 2018
@LivInTheLookingGlass
Copy link
Copy Markdown
Author

Unpacking in Cython mode now works as well, and I have edited my PR to u-msgpack-python to also check for a code attribute.

@methane
Copy link
Copy Markdown
Member

methane commented Sep 6, 2018

I don't like this API design. I don't want to require custom type extends ExtType.
ExtType is just a container when no mapping is used while packing / unpacking.

See also: https://docs.python.org/3/library/copyreg.html

@methane methane closed this Sep 6, 2018
@LivInTheLookingGlass
Copy link
Copy Markdown
Author

LivInTheLookingGlass commented Sep 6, 2018

This does not require that at all. I think you misread. The idea is that you can define types this way and then not need to pass in an ext_hook afterwards. The idea is not to require all custom objects to be done that way.

@LivInTheLookingGlass
Copy link
Copy Markdown
Author

Also, an API based on the copyreg approach is not possible to express with type hinting, whereas this is

@methane
Copy link
Copy Markdown
Member

methane commented Sep 6, 2018

Also, an API based on the copyreg approach is not possible to express with type hinting, whereas this is

I didn't meant using typereg. I meant register based approach without any subclasssing.

The idea is not to require all custom objects to be done that way.

I don't want to add N approaches. I don't want to add and maintain API I don't like.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants