~doctormo/+junk/css-parser

« back to all changes in this revision

Viewing changes to property.py

  • Committer: Martin Owens
  • Date: 2014-07-13 21:48:23 UTC
  • Revision ID: doctormo@gmail.com-20140713214823-774n9vbbhw93zlbh
Move the files around and add some simple events

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#
2
 
# Copyright 2012-2014 Martin Owens <doctormo@gmail.com>
3
 
# Copyright      2014 Ian Denhardt <ian@zenhack.net>
4
 
#
5
 
# This program is free software: you can redistribute it and/or modify
6
 
#  it under the terms of the GNU General Public License as published by
7
 
#  the Free Software Foundation, either version 3 of the License, or
8
 
#  (at your option) any later version.
9
 
#
10
 
#  This program is distributed in the hope that it will be useful,
11
 
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
#  GNU General Public License for more details.
14
 
#
15
 
#  You should have received a copy of the GNU General Public License
16
 
#  along with this program.  If not, see <http://www.gnu.org/licenses/>
17
 
#
18
 
"""
19
 
The idea here is to provide a machanism for getting attributes at the right time.
20
 
 
21
 
Should provide stateful attribute access and some signal support for changes.
22
 
"""
23
 
 
24
 
 
25
 
from collections import OrderedDict, Callable
26
 
 
27
 
 
28
 
class DefaultOrderedDict(OrderedDict):
29
 
    """Copied from: http://stackoverflow.com/questions/6190331/can-i-do-an-ordered-default-dict-in-python"""
30
 
    def __init__(self, default_factory=None, *a, **kw):
31
 
        if (default_factory is not None and
32
 
            not isinstance(default_factory, Callable)):
33
 
            raise TypeError('first argument must be callable')
34
 
        OrderedDict.__init__(self, *a, **kw)
35
 
        self.default_factory = default_factory
36
 
 
37
 
    def __getitem__(self, key):
38
 
        try:
39
 
            return OrderedDict.__getitem__(self, key)
40
 
        except KeyError:
41
 
            return self.__missing__(key)
42
 
 
43
 
    def __missing__(self, key):
44
 
        if self.default_factory is None:
45
 
            raise KeyError(key)
46
 
        self[key] = value = self.default_factory()
47
 
        return value
48
 
 
49
 
    def __reduce__(self):
50
 
        if self.default_factory is None:
51
 
            args = tuple()
52
 
        else:
53
 
            args = self.default_factory,
54
 
        return type(self), args, None, None, self.items()
55
 
 
56
 
    def copy(self):
57
 
        return self.__copy__()
58
 
 
59
 
    def __copy__(self):
60
 
        return type(self)(self.default_factory, self)
61
 
 
62
 
    def __deepcopy__(self, memo):
63
 
        import copy
64
 
        return type(self)(self.default_factory,
65
 
                          copy.deepcopy(self.items()))
66
 
    def __repr__(self):
67
 
        return 'OrderedDefaultDict(%s, %s)' % (self.default_factory,
68
 
                                        OrderedDict.__repr__(self))
69
 
 
70
 
    def sort_to_end(self, name):
71
 
        if name in self:
72
 
            self[name] = self.pop(name)
73
 
 
74
 
    def super_keys(self):
75
 
        ret = set()
76
 
        for v in self.values():
77
 
            ret.update(v.keys())
78
 
        return ret
79
 
 
80
 
    def super_gets(self, keys):
81
 
        for key in keys:
82
 
            yield (key, self.super_get(key))
83
 
 
84
 
    def super_get(self, key):
85
 
        for d in reversed(self):
86
 
            if key in self[d]:
87
 
                return self[d][key]
88
 
        return None
89
 
 
90
 
 
91
 
 
92
 
class PropertyObject(object):
93
 
    """Property objects control system of layered property dictionaries,
94
 
       attributes returned are from the top most stack with that item key
95
 
 
96
 
    ! Keeping the user attributes ahead of the pack is trouble. Is this useful?
97
 
 
98
 
    """
99
 
    def __new__(cls, *p, **k):
100
 
        inst = object.__new__(cls)
101
 
        inst.__attrs__ = DefaultOrderedDict(dict)
102
 
        return inst
103
 
 
104
 
    def __setattr__(self, name, value):
105
 
        if name[0] != '_':
106
 
            self.__attrs__['user'][name] = value
107
 
        object.__setattr__(self, name, value)
108
 
 
109
 
    def __delattr__(self, name):
110
 
        if name[0] != '_' and name in self.__attrs__['user']:
111
 
            self.__attrs__['user'].pop(name)
112
 
        self.refresh([name])
113
 
 
114
 
    def add_to(self, d, name='base'):
115
 
        reorder = name not in self.__attrs__
116
 
 
117
 
        self.__attrs__[name].update(d)
118
 
        if reorder:
119
 
            self.__attrs__.sort_to_end('user')
120
 
 
121
 
        self.__dict__.update(d)
122
 
 
123
 
        if 'user' in self.__attrs__:
124
 
            self.__dict__.update(self.__attrs__['user'])
125
 
 
126
 
    def remove(self, name):
127
 
        old = self.__attrs__.pop(name)
128
 
        self.refresh(old.keys())
129
 
 
130
 
    def refresh(self, keys=None):
131
 
        keys = keys or self.__attrs__.super_keys()
132
 
        self.__dict__.update(self.__attrs__.super_gets(keys))
133
 
 
134