Changeset 430
- Timestamp:
- 05/21/07 19:44:44 (2 years ago)
- Files:
-
- cly/trunk/cly/extra.py (modified) (2 diffs)
- cly/trunk/cly/__init__.py (modified) (13 diffs)
- cly/trunk/cly/interactive.py (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
cly/trunk/cly/extra.py
r429 r430 48 48 49 49 Each underscore separated part of the function name is converted into a 50 Node, each argument without a default is converted into a Variable, and 51 each argument with a default is converted into a non-optional Variable. 50 Node, each argument without a default is converted into a required 51 Variable, and each argument with a default is converted into an optional 52 Variable. 52 53 53 54 >>> from cly import Grammar … … 56 57 >>> grammar = Grammar() 57 58 >>> integrate(grammar, [foo_bar]) 58 >>> for i in grammar.walk(): print i 59 <Grammar:/> 60 <Node:/foo> 61 <Node:/foo/bar> 62 <Variable:/foo/bar/one> 63 <Variable:/foo/bar/one/two> 64 <Action:/foo/bar/one/two/action> 65 <Node:/foo/bar/one/two/four> 66 <Variable:/foo/bar/one/two/four/four> 67 <Alias:/foo/bar/one/two/four/four/__anonymous_0 for /foo/bar/one/two/*> 68 <Node:/foo/bar/one/two/three> 69 <Variable:/foo/bar/one/two/three/three> 70 <Alias:/foo/bar/one/two/three/three/__anonymous_0 for /foo/bar/one/two/*> 59 >>> list(grammar.walk()) # doctest: +NORMALIZE_WHITESPACE 60 [<Grammar:/>, <Node:/foo>, <Node:/foo/bar>, <Variable:/foo/bar/one>, 61 <Variable:/foo/bar/one/two>, <Action:/foo/bar/one/two/action>, 62 <Node:/foo/bar/one/two/four>, <Variable:/foo/bar/one/two/four/four>, 63 <Alias:/foo/bar/one/two/four/four/__anonymous_0 for /foo/bar/one/two/*>, 64 <Node:/foo/bar/one/two/three>, <Variable:/foo/bar/one/two/three/three>, 65 <Alias:/foo/bar/one/two/three/three/__anonymous_0 for /foo/bar/one/two/*>] 71 66 """ 72 67 import inspect cly/trunk/cly/__init__.py
r429 r430 246 246 247 247 >>> tree = Node('One')(two=Node('Two'), three=Node('Three')) 248 >>> for child in tree: print child 249 <Node:/three> 250 <Node:/two> 248 >>> list(tree) 249 [<Node:/three>, <Node:/two>] 251 250 """ 252 251 children = sorted(self._children.values(), … … 260 259 >>> node = Node('One') 261 260 >>> node['two'] = Node('Two') 262 >>> for i in node.walk(): print i 263 <Node:/> 264 <Node:/two> 261 >>> list(node.walk()) 262 [<Node:/>, <Node:/two>] 265 263 """ 266 264 self(**{key: child}) … … 279 277 280 278 >>> node = Node('One')(two=Node('Two'), three=Node('Three')) 281 >>> for i in node.walk(): print i 282 <Node:/> 283 <Node:/three> 284 <Node:/two> 279 >>> list(node.walk()) 280 [<Node:/>, <Node:/three>, <Node:/two>] 285 281 >>> del node['two'] 286 >>> for i in node.walk(): print i 287 <Node:/> 288 <Node:/three> 282 >>> list(node.walk()) 283 [<Node:/>, <Node:/three>] 289 284 """ 290 285 child = self._children.pop(key) … … 305 300 >>> tree = Node('One')(two=Node('Two', three=Node('Three'), 306 301 ... four=Node('Four'))) 307 >>> for i in tree.walk(): print i 308 <Node:/> 309 <Node:/two> 310 <Node:/two/four> 311 <Node:/two/three> 302 >>> list(tree.walk()) 303 [<Node:/>, <Node:/two>, <Node:/two/four>, <Node:/two/three>] 312 304 """ 313 305 def walk(root): … … 325 317 ... four=Node('Four')), five=Alias('../two/*')) 326 318 >>> context = Context(None, None) 327 >>> for i in tree.children(context): print i 328 <Alias:/five for /two/*> 329 <Node:/two> 330 >>> for i in tree.children(context, follow=True): print i 331 <Node:/two/four> 332 <Node:/two/three> 333 <Node:/two> 319 >>> list(tree.children(context)) 320 [<Alias:/five for /two/*>, <Node:/two>] 321 >>> list(tree.children(context, follow=True)) 322 [<Node:/two/four>, <Node:/two/three>, <Node:/two>] 334 323 """ 335 324 for child in self: … … 522 511 <Alias:/four for /one> 523 512 >>> context = Context(None, None) 524 >>> for node in alias.follow(context): print node525 <Node:/one>513 >>> list(alias.follow(context)) 514 [<Node:/one>] 526 515 >>> alias = parser.find('/five/six') 527 516 >>> alias 528 517 <Alias:/five/six for /*> 529 >>> for node in alias.follow(context): print node 530 <Node:/five> 531 <Node:/one> 532 <Node:/one> 533 <Node:/two> 518 >>> list(alias.follow(context)) 519 [<Node:/five>, <Node:/one>, <Node:/one>, <Node:/two>] 534 520 """ 535 521 … … 590 576 ... print "some text" 591 577 >>> grammar = Grammar(action=Action("Write some text", write_text)) 578 >>> parser = Parser(grammar) 579 >>> context = Context(parser, 'foo bar') 592 580 >>> node = grammar.find('action') 593 581 >>> node.help(None) … … 595 583 >>> list(node.help(None)) 596 584 [('<eol>', 'Write some text')] 597 >>> node.terminal( Context(None, 'foo bar'))585 >>> node.terminal(context) 598 586 some text 599 587 """ 600 588 pattern = '$' 601 589 group = 9999 602 with_context = False590 with_context = None 603 591 604 592 def __init__(self, help, callback=None, *args, **kwargs): … … 609 597 610 598 def help(self, context): 599 """Return help for this action. 600 601 >>> Action('Test', None).help(None) 602 (('<eol>', 'Test'),) 603 """ 611 604 if not self.visible(context): 612 605 return … … 617 610 618 611 def terminal(self, context): 619 if self.with_context :612 if self.with_context or (self.with_context is None and self.parser.with_context): 620 613 return self.callback(context.user_context, **context.vars) 621 614 else: … … 642 635 pattern = r'\w+' 643 636 644 def __init__(self, help, var_name=None, *args, **kwargs): 645 Node.__init__(self, help, *args, **kwargs) 646 self._var_name = var_name 637 def __init__(self, *args, **kwargs): 638 self._var_name = kwargs.pop('var_name', None) 639 Node.__init__(self, *args, **kwargs) 640 641 def _set_var_name(self, value): 642 self._var_name = value 647 643 648 644 def _get_var_name(self): 649 """Get the var name for this variable. Will use ``var_name`` if provided650 to the constructor, otherwise it will use the node name."""645 """Get the var name for this variable. Will use ``var_name`` if 646 provided to the constructor, otherwise it will use the node name.""" 651 647 if self._var_name is not None: 652 648 return self._var_name 653 649 return self.name 654 650 655 var_name = property(_get_var_name )651 var_name = property(_get_var_name, _set_var_name) 656 652 657 653 def valid(self, context): 658 if not self.traversals or self.traversals >1 or \654 if self.traversals != 1 or \ 659 655 (self.traversals == 1 and self.name not in context.vars) or \ 660 656 len(context.vars.get(self.name, [])) < self.traversals: … … 909 905 class Parser(object): 910 906 """Parse and execute CLY grammars.""" 911 def __init__(self, grammar ):907 def __init__(self, grammar, with_context=False): 912 908 self.grammar = grammar 909 self.with_context = with_context 913 910 914 911 def _set_grammar(self, grammar): … … 928 925 929 926 >>> parser = Parser(Grammar(one=Node('One'), two=Node('Two', three=Node('Three')))) 930 >>> for node in parser: print node 931 <Grammar:/> 932 <Node:/two> 933 <Node:/two/three> 934 <Node:/one> 927 >>> list(parser) 928 [<Grammar:/>, <Node:/two>, <Node:/two/three>, <Node:/one>] 935 929 """ 936 930 for node in self.grammar.walk(): cly/trunk/cly/interactive.py
r425 r430 49 49 parse ``Context`` with this object, which in turn will deliver this 50 50 object on to terminal nodes that have set ``with_context=True``. 51 52 ``with_context=False``: `boolean` 53 Force ``user_context`` to be passed to all action nodes, unless they 54 explicitly set the member variable ``with_context=False``. 55 56 ``history_file=None``: `string` 57 Defaults to ``~/.<application>_history``. 58 59 ``history_length=500``: `integer` 60 Lines of history to keep. 61 62 ``completion_key='tab'``: `string` 63 Key to use for completion, per the readline documentation. 64 65 ``completion_delimiters=' \t'``: `string` 66 Characters that terminate completion. 67 68 ``help_key='?'``: `key` 69 Key to use for tab completion. 70 51 71 """ 52 72 _cli_inject_text = '' … … 59 79 60 80 def __init__(self, parser, application='cly', prompt=None, 61 user_context=None, history_file=None, history_length=500,62 completion_key='tab',81 user_context=None, with_context=None, history_file=None, 82 history_length=500, completion_key='tab', 63 83 #completion_delimiters='`!#$%^&*()=+[{]}\|;\'",<>? \t', 64 84 completion_delimiters=' \t', 65 help_key='?'): 85 help_key='?', inhibit_exceptions=False, 86 with_backtrace=False): 66 87 if prompt is None: 67 88 prompt = application + '> ' … … 71 92 parser = cly.Parser(parser) 72 93 94 if with_context is not None: 95 parser.with_context = with_context 96 if user_context is not None: 97 parser.user_context = user_context 73 98 Interact._parser = parser 74 99 Interact.prompt = prompt … … 95 120 96 121 97 def interact_once(self, default_text='', callback=None):98 """ Input one command from the user and return the result of the122 def once(self, default_text='', callback=None): 123 """Input one command from the user and return the result of the 99 124 executed command. `callback` is called with the Interact object before 100 each line is displayed. """125 each line is displayed.""" 101 126 Interact._cli_inject_text = default_text 102 127 … … 113 138 114 139 try: 115 context = Interact._parser.parse(command )140 context = Interact._parser.parse(command, user_context=self.user_context) 116 141 context.execute() 117 142 except cly.ParseError, e: … … 119 144 return context 120 145 146 def loop(self, inhibit_exceptions=False, with_backtrace=False): 147 """Repeatedly read and execute commands from the user. 148 149 Arguments: 150 151 ``inhibit_exceptions=True``: `boolean` 152 Normally, ``interact_loop`` will pass exceptions back to the caller for 153 handling. Setting this to ``True`` will cause an error message to 154 be printed, but interaction will continue. 155 156 ``with_backtrace=False``: `boolean` 157 Whether to print a full backtrace when ``inhibit_exceptions=True``. 158 """ 159 try: 160 while True: 161 try: 162 if not self.once(): 163 break 164 except Exception, e: 165 if inhibit_exceptions: 166 if with_backtrace: 167 import traceback 168 console.error(traceback.format_exc()) 169 else: 170 console.error('error: %s' % e) 171 else: 172 raise 173 finally: 174 self.write_history() 175 121 176 def print_error(self, context, e): 122 """Called by ` interact_once()` to print a ParseError."""177 """Called by `once()` to print a ParseError.""" 123 178 candidates = [help[1] for help in context.help()] 124 179 if len(candidates) > 1: … … 141 196 else: 142 197 console.error(indent + '^ ' + text) 143 144 def interact_loop(self):145 """ Repeatedly read and execute commands from the user. """146 try:147 while self.interact_once():148 pass149 finally:150 self.write_history()151 198 152 199 def write_history(self):
