annotate paraspace/structpath.py @ 32:9bac21d401fe

Make get_parent() as a method of structpath.context
author Thinker K.F. Li <thinker@codemud.net>
date Wed, 15 Jun 2011 02:03:38 +0800
parents aed662c820d8
children fe1ebf0c3d40
rev   line source
31
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
1 ##
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
2 # Implement a xpath liked query language.
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
3 #
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
4 class context(object):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
5 all_classes = None
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
6 class_instances = None
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
7 root = None
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
8 objs = None
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
9
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
10 def __init__(self, objs, ctx=None):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
11 if ctx:
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
12 self.all_classes = ctx.all_classes
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
13 self.class_instances = ctx.class_instances
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
14 self.root = ctx.root
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
15 pass
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
16 self.objs = objs
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
17 pass
32
9bac21d401fe Make get_parent() as a method of structpath.context
Thinker K.F. Li <thinker@codemud.net>
parents: 31
diff changeset
18
9bac21d401fe Make get_parent() as a method of structpath.context
Thinker K.F. Li <thinker@codemud.net>
parents: 31
diff changeset
19 def get_parent(self, obj):
9bac21d401fe Make get_parent() as a method of structpath.context
Thinker K.F. Li <thinker@codemud.net>
parents: 31
diff changeset
20 raise NotImplementedError, 'get_parent() is not implemented'
31
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
21 pass
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
22
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
23
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
24 def _path_split(path):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
25 parts = [p.strip()
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
26 for p in path.split('/')]
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
27 return parts
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
28
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
29
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
30 def _is_abs(path_parts):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
31 if len(path_parts) == 0:
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
32 return False
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
33 return path_parts[0] == ''
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
34
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
35
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
36 def _rel_of_abs(path_parts):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
37 return path_parts[1:]
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
38
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
39
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
40 def _is_class(part):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
41 return part.startswith('.')
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
42
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
43
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
44 def _class_name(part):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
45 return part[1:]
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
46
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
47
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
48 def _is_parent_name(part):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
49 return part == '..'
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
50
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
51
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
52 def _obj_attr(obj, attrname):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
53 if isinstance(obj, list):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
54 idx = int(attrname)
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
55 return obj[idx]
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
56 elif isinstance(obj, dict):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
57 key = eval(attrname)
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
58 return obj[key]
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
59 return getattr(obj, attrname)
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
60
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
61
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
62 def _handle_path_part_obj(ctx, part, obj):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
63 if _is_parent_name(part):
32
9bac21d401fe Make get_parent() as a method of structpath.context
Thinker K.F. Li <thinker@codemud.net>
parents: 31
diff changeset
64 new_objs = [ctx.get_parent(obj)]
31
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
65 elif _is_class(part):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
66 class_name = _class_name(part)
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
67 new_objs = ctx.class_instances[class_name]
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
68 else:
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
69 new_objs = [_obj_attr(obj, part)]
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
70 pass
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
71 return new_objs
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
72
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
73
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
74 def _handle_path_part(ctx, part):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
75 from itertools import chain
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
76
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
77 if not ctx.objs:
32
9bac21d401fe Make get_parent() as a method of structpath.context
Thinker K.F. Li <thinker@codemud.net>
parents: 31
diff changeset
78 ctx = ctx.__class__([ctx.root], ctx)
31
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
79 pass
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
80
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
81 objss = [_handle_path_part_obj(ctx, part, obj)
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
82 for obj in ctx.objs]
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
83 objs = [o for o in chain(*objss)]
32
9bac21d401fe Make get_parent() as a method of structpath.context
Thinker K.F. Li <thinker@codemud.net>
parents: 31
diff changeset
84 new_ctx = ctx.__class__(objs, ctx)
31
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
85 return new_ctx
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
86
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
87
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
88 def _handle_path_parts(ctx, path_parts):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
89 if _is_abs(path_parts):
32
9bac21d401fe Make get_parent() as a method of structpath.context
Thinker K.F. Li <thinker@codemud.net>
parents: 31
diff changeset
90 ctx = ctx.__class__([ctx.root], ctx)
31
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
91 path_parts = _rel_of_abs(path_parts)
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
92 pass
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
93
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
94 if len(path_parts) == 1 and path_parts[0] == '':
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
95 return ctx
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
96
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
97 for path_part in path_parts:
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
98 ctx = _handle_path_part(ctx, path_part)
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
99 pass
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
100
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
101 return ctx
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
102
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
103
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
104 def find_objs_path(ctx, path):
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
105 path_parts = _path_split(path)
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
106 rctx = _handle_path_parts(ctx, path_parts)
aed662c820d8 xpath like query structpath.py
Thinker K.F. Li <thinker@codemud.net>
parents:
diff changeset
107 return rctx.objs