Re: flexi adaption/casting scheme

Поиск
Список
Период
Сортировка
От Daniele Varrazzo
Тема Re: flexi adaption/casting scheme
Дата
Msg-id CA+mi_8bU6y5rEj2k9NfoXqKmbBzQp=f0Um7nVMxuy4X1RQCxTg@mail.gmail.com
обсуждение исходный текст
Ответ на Re: flexi adaption/casting scheme  (Ronan Dunklau <rdunklau@gmail.com>)
Ответы Re: flexi adaption/casting scheme  (Ronan Dunklau <rdunklau@gmail.com>)
Re: flexi adaption/casting scheme  (Tobias Oberstein <tobias.oberstein@gmail.com>)
Список psycopg
On Fri, Sep 21, 2012 at 2:47 PM, Ronan Dunklau <rdunklau@gmail.com> wrote:
>> 1.3
>> composite type => plain Python dict with key/value pairs only
>> for all attributes in the composite type that have non-NULL values
>
> It would be great to have an API to customize the class to instantiate with a
> composite type.
>
> I tried an implementation in the attached patch.
>
> The idea would be to add an optional "ctor" argument, which would be used in
> place of the namedtuple argument. Additionally, an adapter can be
> automatically registered to perform the reverse conversion.

Thank you, I like the idea of customizing the composite caster. But I
don't like very much the proposed way. Oddly enough, just yesterday
I've changed the _ctor: it used to take *args instead of an iterable
of args but I've just recently discovered namedtuple._make which has
the same signature of the basic tuple and can be used to avoid
unpacking. You patch puts it back to "self._ctor = lambda *args:
tuple(args)" and then some.

Your patch passes the arguments to the ctor in the most generic way
(as **kwargs) in order to work with any possible function, but this is
overkilling for the basic use with tuple/namedtuple. And still
wouldn't be enough: you can't make an OrderedDict out of it for
instance, as **kwargs randomizes the order.

I propose the attached diff instead. It makes the CompositeCaster easy
to subclass and exposes part of the machinery used by
register_composite() in order to make the class registrable without
adding new arguments to register_composite() too, which would only
deal with the basic case. Customization is performed overriding the
method "make" which takes the attributes read from the db in input.
Attribute names can be obtained from "self".

For example, to cast composite to dictionaries one can subclass it as:

    class DictComposite(psycopg2.extras.CompositeCaster):
        def make(self, attrs):
            return dict(zip(self.attnames, attrs))

Which would be used as:

    # from psql: CREATE TYPE card AS (value int, suit text);

    c = DictComposite.from_db('card', cnn)
    c.register()

    cur.execute("select (8, 'hearts')::card")
    cur.fetchone()[0]
    {'suit': 'hearts', 'value': 8}

Seems nice, doesn't it?


Tobias: as expected it works ok with composite types, as the original
CompositeCaster does:

    # from psql: CREATE TYPE card_back AS (face card, back text);

    c2 = DictComposite.from_db('card_back', cnn)
    c2.register()

    cur.execute("select ((8, 'hearts'), 'blue')::card_back")
    cur.fetchone()[0]
    {'back': 'blue', 'face': {'suit': 'hearts', 'value': 8}}

if it doesn't work for you, you are probably doing something wrong.

-- Daniele

Вложения

В списке psycopg по дате отправления:

Предыдущее
От: Tobias Oberstein
Дата:
Сообщение: Re: flexi adaption/casting scheme
Следующее
От: Ronan Dunklau
Дата:
Сообщение: Re: flexi adaption/casting scheme