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