Changeset 576
- Timestamp:
- 07/14/08 21:39:03 (3 months ago)
- Files:
-
- cly/trunk/cly/builder.py (modified) (13 diffs)
- cly/trunk/cly/exceptions.py (modified) (1 diff)
- cly/trunk/cly/parser.py (modified) (1 diff)
- cly/trunk/cly/test.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
cly/trunk/cly/builder.py
r575 r576 120 120 traversals = 1 121 121 label = None 122 context = None123 122 124 123 def __init__(self, *anonymous, **kwargs): … … 127 126 help = kwargs.pop('help', '') 128 127 if isinstance(help, basestring): 129 self. help = LazyHelp(self, help)128 self._help = help 130 129 elif callable(help): 131 130 self.help = help … … 177 176 lambda self, name: self._set_name(name)) 178 177 178 def help(self, context): 179 """Return help for node. 180 181 :returns: A sequence of tuples in the form (lhs, help). 182 """ 183 if self.name == self.pattern: 184 yield (self.name, self._help) 185 else: 186 yield ('<%s>' % self.name, self._help) 179 187 180 188 def __call__(self, *anonymous, **options): … … 479 487 480 488 @classmethod 481 def cast_attribute(cls, name , value):489 def cast_attribute(cls, namespace, name, value): 482 490 """Define functions for casting attributes to their correct Python type. 483 491 484 492 Upcalling is necessary. 485 493 486 :returns: Cast value. 494 :namespace: The XML namespace of the attribute. Compare against 495 XMLGrammar.EVAL_NS to determine if forced evaluation 496 can/should occur. 497 :name: Attribute name. 498 :value: Value to cast. 499 500 :returns: Tuple of (value, options) where options is a dictionary of 501 extra Node constructor arguments. 487 502 """ 488 503 casts = { … … 492 507 } 493 508 if name in casts: 494 value = casts[name](value) 495 return value 509 return casts[name](value), {} 510 511 # Attributes that can be strings but by default have a method. 512 if name == 'help' and namespace != XMLGrammar.EVAL_NS: 513 return value, {} 514 515 # Is the destination Node attribute callable? Do a lazy eval. 516 function = getattr(cls, name, None) 517 if callable(function): 518 args, _, _, _ = getargspec(function) 519 if args and args[0] == 'self': 520 args.pop(0) 521 value = lazy_attr_evaluator(value, args) 522 return value, {} 496 523 497 524 @classmethod … … 591 618 592 619 @classmethod 593 def cast_attribute(cls, name , value):594 return eval(value) 620 def cast_attribute(cls, namespace, name, value): 621 return eval(value), {} 595 622 596 623 … … 605 632 606 633 @classmethod 607 def cast_attribute(cls, name , value):634 def cast_attribute(cls, namespace, name, value): 608 635 if name == 'id': 609 return group_cast(value) 610 return super(Group, cls).cast_attribute(name , value)636 return group_cast(value), {} 637 return super(Group, cls).cast_attribute(namespace, name, value) 611 638 612 639 … … 812 839 return {'exec': 'callback'} 813 840 841 @classmethod 842 def cast_attribute(cls, namespace, name, value): 843 options = {} 844 if name == 'callback': 845 args = ['context'] 846 options['with_context'] = True 847 value = lazy_attr_evaluator(value, args) 848 return value, options 849 return super(Action, cls).cast_attribute(namespace, name, value) 850 814 851 815 852 class Variable(Node): … … 986 1023 """ 987 1024 988 node_aliases= {1025 NODE_ALIASES = { 989 1026 'var': 'variable', 990 1027 'int': 'integer', 991 1028 'str': 'string', 992 1029 } 1030 EVAL_NS = 'http://swapoff.org/cly/xml/eval' 993 1031 994 1032 def __init__(self, file, extra_nodes=None): … … 1002 1040 self.node_map = dict([(v.__name__.lower(), v) for v in nodes]) 1003 1041 self.node_map.update([(k, self.node_map[v]) 1004 for k, v in self. node_aliases.items()])1042 for k, v in self.NODE_ALIASES.items()]) 1005 1043 1006 1044 grammar = dom.firstChild … … 1057 1095 aliases.update(c.attribute_aliases()) 1058 1096 1059 attributes = dict([(str(aliases.get(k, k)), v) for k, v 1060 in xnode.attributes.items()]) 1061 1062 for k, v in attributes.items(): 1097 attributes = {} 1098 1099 for (ns, k), v in xnode.attributes.itemsNS(): 1063 1100 # Do type conversion 1064 v = cls.cast_attribute(k, v) 1065 # Is the destination Node attribute callable? Do a lazy eval. 1066 if callable(getattr(cls, k, None)): 1067 function = getattr(cls, k) 1068 if callable(function): 1069 args, _, _, _ = getargspec(function) 1070 if args and args[0] == 'self': 1071 args.pop(0) 1072 # Special-case callback(*args, **kwargs) 1073 if issubclass(cls, Action) and k == 'callback' \ 1074 and not args: 1075 args = ['context'] 1076 attributes['with_context'] = True 1077 else: 1078 args = [] 1079 v = lazy_attr_evaluator(v, args) 1080 1101 k = str(aliases.get(k, k)) 1102 v, options = cls.cast_attribute(ns, k, v) 1103 attributes.update(options) 1081 1104 attributes[k] = v 1082 1105 return attributes … … 1114 1137 data = {} 1115 1138 vars = {} 1139 def defined(vars, any=False): 1140 for var in vars.split(): 1141 defined = var in locals 1142 if any and defined: 1143 return True 1144 elif not any and not defined: 1145 return False 1146 return not any 1147 1116 1148 locals.update(vars) 1149 locals['defined'] = defined 1117 1150 locals['v'] = vars 1118 1151 locals['a'] = args … … 1438 1471 1439 1472 @classmethod 1440 def cast_attribute(cls, name , value):1473 def cast_attribute(cls, namespace, name, value): 1441 1474 if name == 'parts': 1442 1475 return int(value) 1443 return super(Hostname, cls).cast_attribute(name , value)1476 return super(Hostname, cls).cast_attribute(namespace, name, value) 1444 1477 1445 1478 cly/trunk/cly/exceptions.py
r575 r576 15 15 __all__ = ['Error', 'InvalidHelp', 'InvalidNodePath', 'InvalidAnonymousNode', 16 16 'ParseError', 'UnexpectedEOL', 'InvalidToken', 'ValidationError', 17 'XMLParseError' , 'EvaluationError']17 'XMLParseError'] 18 18 __docformat__ = 'restructuredtext en' 19 19 cly/trunk/cly/parser.py
r572 r576 330 330 context = self.context_factory(self, command, data) 331 331 332 # Set context on all nodes in the grammar 333 for node in self.grammar.walk(): 334 node.context = self 335 336 try: 337 def parse(node, match): 338 context.trail.append((node, match)) 339 if match is not None: 340 node.advance(context) 341 node.selected(context, match) 342 343 for subnode in node.next(context): 344 if subnode.valid(context): 345 submatch = subnode.match(context) 346 if submatch is not None: 347 return parse(subnode, submatch) 348 else: 349 return 350 raise InvalidToken(context) 351 352 parse(self.grammar, None) 353 return context 354 finally: 355 # Unset context on grammar 356 for node in self.grammar.walk(): 357 node.context = None 332 def parse(node, match): 333 context.trail.append((node, match)) 334 if match is not None: 335 node.advance(context) 336 node.selected(context, match) 337 338 for subnode in node.next(context): 339 if subnode.valid(context): 340 submatch = subnode.match(context) 341 if submatch is not None: 342 return parse(subnode, submatch) 343 else: 344 return 345 raise InvalidToken(context) 346 347 parse(self.grammar, None) 348 return context 358 349 359 350 def merge(self, where, grammar): cly/trunk/cly/test.py
r568 r576 163 163 class Test(Node): 164 164 @classmethod 165 def cast_attribute(cls, name , value):165 def cast_attribute(cls, namespace, name, value): 166 166 if name == 'test': 167 return int(value) 168 return value 167 return int(value), {} 168 return value, {} 169 169 170 170 xml = StringIO("""<?xml version="1.0"?>
