Subclassing Traits Dict for Sorted Dict

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Subclassing Traits Dict for Sorted Dict

Raphael Walker
Hello,

I try to implement a SortedDict in Traits with class objects as elements.
It cannot be a list because the access to the objects have to be like on
a dict (with unique id).

Until now the Sorted Dict was implemented in "pure python" with a list
of objects and a key_map, to have the correct order (PEP372). But to use
the Sorted Dict in ETS we would like the Sorted Dict to be a Traits object.

Ideas:
1. Sub classing from HasTraits, change the object list to a Traits List
    - The new Traits object does not get info about manipulation
      events (insert/delete)
2. Sub classing Traits Dict
    - overwrite functions keys, iterkeys, ..., didn't found them.
3. Define a container class and use Trait Property


Many thanks for suggestions.

Raphael

--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev
Reply | Threaded
Open this post in threaded view
|

Re: Subclassing Traits Dict for Sorted Dict

Robert Kern
On Wed, Feb 10, 2010 at 03:42, Raphael Walker <[hidden email]> wrote:

> Hello,
>
> I try to implement a SortedDict in Traits with class objects as elements.
> It cannot be a list because the access to the objects have to be like on
> a dict (with unique id).
>
> Until now the Sorted Dict was implemented in "pure python" with a list
> of objects and a key_map, to have the correct order (PEP372). But to use
> the Sorted Dict in ETS we would like the Sorted Dict to be a Traits object.
>
> Ideas:
> 1. Sub classing from HasTraits, change the object list to a Traits List
>    - The new Traits object does not get info about manipulation
>      events (insert/delete)
> 2. Sub classing Traits Dict
>    - overwrite functions keys, iterkeys, ..., didn't found them.
> 3. Define a container class and use Trait Property

Note that Dict() and List() are not the dict and list objects
themselves. They are just trait declarations. The actual subclasses of
dict and list that provide notifications are TraitDictObject and
TraitListObject. What you will need to do is subclass TraitDictObject
and override the appropriate methods to keep the order information
consistent. There are many recipes for Python ordered dicts floating
around. I suggest finding one that subclasses from dict rather than
some other implementation strategy. That will be the best guide to how
you would want subclass TraitDictObject. Then you will want to
subclass the Dict trait declaration to use your SortedTraitDictObject.
One funky, totally undocumented thing that you will need to change is
how to set the default value. Dict is special-cased in the C code, so
you will have to do something different. There is some bad design that
we haven't gotten around to fixing, yet:


# FIXME: Fix Traits so we don't need this hack.
class WeirdInt(int):
    """ Work around a missing feature in Traits.

    Traits uses the default_value_type to determine if a trait is a List, Dict,
    etc. through a dict lookup for deciding if it is going to add the *_items
    events. Dict subclasses need to use a different default_value_type, though,
    so we'll pretend that we look like a dict (default_value_type=6). The other
    place where Traits uses the default_value_type is in the C code, where it
    converts it to a C int, so it will get the real value of "8" there.

    Horrible, horrible hack. I am not proud.
    """
    def __hash__(self):
        return hash(6)
    def __eq__(self, other):
        if other == 6:
            return True
        else:
            return int(self) == other

class SortedDict(Dict):

    default_value_type = WeirdInt(8)

    def __init__(self, *args, **kwds):
        Dict.__init__(self, *args, **kwds)

        # Set up the Type-8 initializer.
        self.real_default_value = self.default_value
        def type8_init(obj):
            # Handle the conversion to a SortedTraitDictObject in the validator.
            return self.real_default_value
        self.default_value = type8_init

    def validate(self, object, name, value):
        """ Validates that the value is a valid SortedTraitDictObject.
        """
        if isinstance(value, dict):
            if object is None:
                return value
            return SortedTraitDictObject(self, object, name, value)

        self.error(object, name, value)

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless
enigma that is made terrible by our own mad attempt to interpret it as
though it had an underlying truth."
  -- Umberto Eco
_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev