Changeset 557
- Timestamp:
- 07/10/08 10:55:04 (5 months ago)
- Files:
-
- cly/trunk/cly/builder.py (modified) (7 diffs)
- cly/trunk/cly/interactive.py (modified) (1 diff)
- cly/trunk/cly/test.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
cly/trunk/cly/builder.py
r556 r557 479 479 480 480 @classmethod 481 def xml_ attribute_casts(cls):481 def xml_cast_attribute(cls, name, value): 482 482 """Define functions for casting attributes to their correct Python type. 483 483 484 Parent classes are automatically merged, so upcalling is unnecessary.485 486 :returns: A dictionary of name, function mappings.487 """ 488 return{484 Upcalling is necessary. 485 486 :returns: Cast value. 487 """ 488 casts = { 489 489 'traversals': int, 'group': _xml_group_type, 490 490 'order': int, 'match_candidates': _xml_boolean_type, 491 491 'with_context': _xml_boolean_type, 492 492 } 493 if name in casts: 494 value = casts[name](value) 495 return value 493 496 494 497 @classmethod … … 564 567 565 568 class Set(Masquerade): 566 """Set variables in a branch.""" 567 def __init__(self, vars='', unset='', **kwargs): 568 self.vars = eval('dict(%s)' % vars) 569 self.unset = unset 570 super(Set, self).__init__(**kwargs) 569 """Set variables in a branch. 570 571 >>> from cly import * 572 >>> parser = Parser(Grammar(Set(foo=10, bar=20)(baz=Node()))) 573 >>> parser.parse('baz').vars 574 {'foo': 10, 'bar': 20} 575 """ 576 vars = '' 577 unset = '' 578 579 def __init__(self, **kwargs): 580 super(Set, self).__init__() 581 self.vars = kwargs 571 582 572 583 def follow(self, context): … … 585 596 586 597 @classmethod 587 def xml_attribute_aliases(cls): 588 return {'id': _xml_group_type} 598 def xml_cast_attribute(cls, name, value): 599 if name == 'id': 600 return _xml_group_type(value) 601 return super(Group, cls).xml_cast_attribute(name, value) 589 602 590 603 … … 1026 1039 # callbacks. 1027 1040 aliases = {} 1028 attr_type_map = {} 1029 def call_and_merge(method_name, d): 1030 for c in reversed(cls.mro()): 1031 if method_name in c.__dict__: 1032 d.update(getattr(c, method_name)()) 1033 call_and_merge('xml_attribute_aliases', aliases) 1034 call_and_merge('xml_attribute_casts', attr_type_map) 1041 for c in reversed(cls.mro()): 1042 if 'xml_attribute_aliases' in c.__dict__: 1043 aliases.update(c.xml_attribute_aliases()) 1035 1044 1036 1045 attributes = dict([(str(aliases.get(k, k)), v) for k, v … … 1038 1047 1039 1048 for k, v in attributes.items(): 1040 # Do type-map conversion 1041 if k in attr_type_map: 1042 v = attr_type_map[k](v) 1049 # Do type conversion 1050 v = cls.xml_cast_attribute(k, v) 1043 1051 # Is the destination Node attribute callable? Do a lazy eval. 1044 elif callable(getattr(cls, k, None)):1052 if callable(getattr(cls, k, None)): 1045 1053 function = getattr(cls, k) 1046 1054 if callable(function): … … 1379 1387 :suffix: Optional domain suffix to require. 1380 1388 1381 >>> from cly.parser import Parser 1389 >>> from cly.parser import * 1390 1391 Supports bare hostnames: 1392 1393 >>> parser = Parser(Grammar(foo=Hostname())) 1394 >>> parser.parse('www').vars 1395 {'foo': 'www'} 1396 1397 Fully-qualified names: 1398 1399 >>> parser.parse('www.example.com').vars 1400 {'foo': 'www.example.com'} 1401 1402 IN-ADDR ARPA addresses: 1403 1404 >>> parser.parse('1.1.10.in-addr.arpa').vars 1405 {'foo': '1.1.10.in-addr.arpa'} 1406 1407 But not IP addresses: 1408 1409 >>> parser.parse('10.1.1.1').vars 1410 {} 1411 1412 Suffix checking is also supported: 1413 1414 >>> parser = Parser(Grammar(foo=Hostname(suffix='.example.com'))) 1415 >>> parser.parse('www').vars 1416 {} 1417 >>> parser.parse('www.example.com').vars 1418 {'foo': 'www.example.com'} 1419 1420 As well as requiring a minumum number of host parts: 1421 1382 1422 >>> parser = Parser(Grammar(foo=Hostname(parts=2))) 1383 >>> parser.parse('www').vars['foo'] 1384 Traceback (most recent call last): 1385 ... 1386 KeyError: 'foo' 1387 >>> parser.parse('www.example.com').vars['foo'] 1388 'www.example.com' 1389 >>> parser.parse('1.1.10.in-addr.arpa').vars['foo'] 1390 '1.1.10.in-addr.arpa' 1391 >>> parser.parse('10.1.1.1').vars['foo'] 1392 Traceback (most recent call last): 1393 ... 1394 KeyError: 'foo' 1395 1423 >>> parser.parse('www').vars 1424 {} 1425 >>> parser.parse('www.foo.com').vars 1426 {'foo': 'www.foo.com'} 1396 1427 """ 1397 1428 pattern = r'(?i)([A-Z0-9][A-Z0-9_-]*)((\.([A-Z0-9][A-Z0-9_-]*))*\.([A-Z0-9][A-Z0-9_-]*[A-Z]))?\.?' … … 1407 1438 match = None 1408 1439 return match 1440 1441 @classmethod 1442 def xml_cast_attribute(cls): 1443 return {'parts': _xml_boolean_type} 1409 1444 1410 1445 cly/trunk/cly/interactive.py
r556 r557 133 133 print >> sys.stderr, \ 134 134 'WARNING: neither pyreadline nor CLY\'s built-in readline ' \ 135 'extensions found,\n contextual help arenot ' \135 'extensions found,\n contextual help is not ' \ 136 136 'available.' 137 137 return readline cly/trunk/cly/test.py
r556 r557 11 11 from StringIO import StringIO 12 12 from cly.exceptions import InvalidToken 13 from cly import XMLGrammar, Parser13 from cly import Node, XMLGrammar, Parser 14 14 15 15 … … 159 159 parser.execute('echo hello') 160 160 self.assertEqual(self._output, (('hello',), {})) 161 162 def test_xml_cast_attribute(self): 163 class Test(Node): 164 @classmethod 165 def xml_cast_attribute(cls, name, value): 166 if name == 'test': 167 return int(value) 168 return value 169 170 xml = StringIO("""<?xml version="1.0"?> 171 <grammar> 172 <test test="10" name="test"> 173 </test> 174 </grammar> 175 """) 176 grammar = XMLGrammar(xml, extra_nodes=[Test]) 177 self.assertTrue(isinstance(grammar.find('/test').test, int)) 178 179 def test_xml_attribute_aliases(self): 180 class Parent(Node): 181 @classmethod 182 def xml_attribute_aliases(cls): 183 return {'foo': 'bar'} 184 185 class Test(Parent): 186 @classmethod 187 def xml_attribute_aliases(cls): 188 return {'baz': 'waz'} 189 190 xml = StringIO("""<?xml version="1.0"?> 191 <grammar> 192 <test baz="10" foo="20" name="test"> 193 </test> 194 </grammar> 195 """) 196 grammar = XMLGrammar(xml, extra_nodes=[Test]) 197 node = grammar.find('/test') 198 self.assertTrue(node.bar, '10') 199 self.assertTrue(node.waz, '20') 161 200 162 201
