Mercurial > paraspace
comparison paraspace/structpath.py @ 35:2f9e7f03dbf7
Support predicates in structpath.py
author | Thinker K.F. Li <thinker@codemud.net> |
---|---|
date | Wed, 15 Jun 2011 12:03:23 +0800 |
parents | fe1ebf0c3d40 |
children | 0b9ac7cef6e5 |
comparison
equal
deleted
inserted
replaced
34:fe1ebf0c3d40 | 35:2f9e7f03dbf7 |
---|---|
1 ## | 1 ## |
2 # Implement a xpath liked query language. | 2 # Implement a xpath liked query language. |
3 # | |
4 # \section predicate Predicate | |
5 # Structpath uses syntax of Python for predicate. That means you must use | |
6 # '==' instead of '='. | |
3 # | 7 # |
4 class context(object): | 8 class context(object): |
5 all_classes = None | 9 all_classes = None |
6 class_instances = None | 10 class_instances = None |
7 root = None | 11 root = None |
47 | 51 |
48 def _is_parent_name(part): | 52 def _is_parent_name(part): |
49 return part == '..' | 53 return part == '..' |
50 | 54 |
51 | 55 |
56 def _split_attr_pred(part): | |
57 try: | |
58 lq_idx = part.index('[') | |
59 except: | |
60 return part, '' | |
61 return part[:lq_idx].strip(), part[lq_idx:].strip() | |
62 | |
63 | |
64 def _eval_obj_sub_pred(ctx, obj, sub_pred): | |
65 ns_global = {} | |
66 for attr in dir(obj): | |
67 if attr.startswith('_'): | |
68 continue | |
69 v = _obj_attr(obj, attr) | |
70 ns_global[attr] = v | |
71 pass | |
72 | |
73 truth_v = eval(sub_pred, ns_global) | |
74 return truth_v | |
75 | |
76 | |
77 def _split_pred_into_subs(pred): | |
78 striped_pred = pred.strip(' []\n\r') | |
79 subs = striped_pred.split('][') | |
80 return subs | |
81 | |
82 | |
83 def _eval_obj_pred(ctx, obj, pred): | |
84 subs = _split_pred_into_subs(pred) | |
85 | |
86 for sub in subs: | |
87 if not sub: | |
88 continue | |
89 | |
90 if not _eval_obj_sub_pred(ctx, obj, sub): | |
91 return False | |
92 pass | |
93 return True | |
94 | |
95 | |
52 def _obj_attr(obj, attrname): | 96 def _obj_attr(obj, attrname): |
53 if isinstance(obj, list): | 97 if isinstance(obj, list): |
54 idx = int(attrname) | 98 idx = int(attrname) |
55 return obj[idx] | 99 return obj[idx] |
56 elif isinstance(obj, dict): | 100 elif isinstance(obj, dict): |
58 return obj[key] | 102 return obj[key] |
59 return getattr(obj, attrname) | 103 return getattr(obj, attrname) |
60 | 104 |
61 | 105 |
62 def _handle_path_part_obj(ctx, part, obj): | 106 def _handle_path_part_obj(ctx, part, obj): |
63 if _is_parent_name(part): | 107 attr, pred = _split_attr_pred(part) |
108 | |
109 if _is_parent_name(attr): | |
64 new_objs = [ctx.get_parent(obj)] | 110 new_objs = [ctx.get_parent(obj)] |
65 elif _is_class(part): | 111 elif _is_class(attr): |
66 class_name = _class_name(part) | 112 class_name = _class_name(attr) |
67 new_objs = ctx.class_instances[class_name] | 113 new_objs = ctx.class_instances[class_name] |
68 else: | 114 else: |
69 try: | 115 try: |
70 new_objs = [_obj_attr(obj, part)] | 116 new_objs = [_obj_attr(obj, attr)] |
71 except AttributeError: | 117 except AttributeError: |
72 return [] | 118 return [] |
73 pass | 119 pass |
120 | |
121 new_objs = filter((lambda x: _eval_obj_pred(ctx, x, pred)), new_objs) | |
122 | |
74 return new_objs | 123 return new_objs |
75 | 124 |
76 | 125 |
77 def _handle_path_part(ctx, part): | 126 def _handle_path_part(ctx, part): |
78 from itertools import chain | 127 from itertools import chain |