1 # |
|
2 """ |
|
3 Helper functions and classes |
|
4 """ |
|
5 import re |
|
6 |
|
7 def str_num_cmp(s1,s2): |
|
8 """ |
|
9 string comparator function that will put 'toto_10' after 'toto_2' |
|
10 Also works for strings like 'toto_1_et_23er25'. |
|
11 """ |
|
12 r = re.compile(r'((?<=\d)\D+|(?<=\D)\d+)') |
|
13 r1= r.split(s1) |
|
14 r2= r.split(s2) |
|
15 r1=[not x.isdigit() and x or int(x) for x in r1 if x!=''] |
|
16 r2=[not x.isdigit() and x or int(x) for x in r2 if x!=''] |
|
17 return cmp(r1,r2) |
|
18 |
|
19 |
|
20 class AbstractRegister(object): |
|
21 _instance = None |
|
22 _registered_type = None |
|
23 def __new__(cls): |
|
24 # implements a singleton |
|
25 if cls._instance is None: |
|
26 #debug('Instanciating %s', cls.__name__) |
|
27 cls._instance = super(AbstractRegister, cls).__new__(cls) |
|
28 cls._instance.registered = {} |
|
29 cls._instance.accepts = set() |
|
30 return cls._instance |
|
31 |
|
32 def add(self, cls): |
|
33 assert issubclass(cls, self._registered_type) |
|
34 if cls is self._registered_type: |
|
35 return |
|
36 if cls._accepts is None: |
|
37 return |
|
38 #assert isinstance(cls._accepts, (basestring, tuple)) |
|
39 |
|
40 #debug("Registerered %s for %s", cls.__name__) |
|
41 if not isinstance(cls._accepts, tuple): |
|
42 cls._accepts = (cls._accepts,) |
|
43 for key in cls._accepts: |
|
44 key = self._get_typ(key) |
|
45 #debug(" new key = %s", key) |
|
46 self.registered.setdefault(key, []).append(cls) |
|
47 self.accepts.add(key) |
|
48 |
|
49 def _get_typ(self, typ): |
|
50 if not isinstance(typ, basestring): |
|
51 if not isinstance(typ, type): |
|
52 return None |
|
53 typ = typ.__name__ |
|
54 return typ |
|
55 |
|
56 def __contains__(self, val): |
|
57 val = self._get_typ(val) |
|
58 return val in self.accepts |
|
59 |
|
60 def get_class(self, typ): |
|
61 item = typ |
|
62 if not isinstance(typ, type): |
|
63 typ = typ.__class__ |
|
64 name = typ.__name__ |
|
65 #debug("Looking a widget for %s", typ.__name__) |
|
66 orig_typ = typ |
|
67 while typ is not None: |
|
68 if typ.__name__ in self.registered: |
|
69 for w in self.registered[typ.__name__]: |
|
70 if w._filter is None or w._filter(item): |
|
71 #debug("Widget for %s is %s", typ.__name__, w) |
|
72 return w#self.registered[typ.__name__] |
|
73 if typ.__bases__: |
|
74 typ = typ.__bases__[0] |
|
75 if typ == object: |
|
76 typ = None |
|
77 elif typ.__name__ in ("ObjectItem_", "AbstractListItem_"): |
|
78 typ = orig_typ._type |
|
79 else: |
|
80 typ = None |
|
81 raise ValueError('No registered class for %s' % (name)) |
|