Changeset 1142
- Timestamp:
- Oct 25, 2010, 12:39:08 AM (13 years ago)
- Location:
- branches/experimental/py3k/genshi/template
- Files:
-
- 3 edited
-
astutil.py (modified) (4 diffs)
-
eval.py (modified) (10 diffs)
-
tests/eval.py (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/experimental/py3k/genshi/template/astutil.py
r1120 r1142 22 22 return compile(source, '', mode, _ast.PyCF_ONLY_AST) 23 23 24 from genshi.compat import IS_PYTHON2 24 25 25 26 __docformat__ = 'restructuredtext en' … … 130 131 self._write('**' + node.kwarg) 131 132 133 if not IS_PYTHON2: 134 # In Python 3 arguments get a special node 135 def visit_arg(self, node): 136 self._write(node.arg) 137 132 138 # FunctionDef(identifier name, arguments args, 133 139 # stmt* body, expr* decorator_list) … … 290 296 291 297 292 # Raise(expr? type, expr? inst, expr? tback) 293 def visit_Raise(self, node): 294 self._new_line() 295 self._write('raise') 296 if not node.type: 297 return 298 self._write(' ') 299 self.visit(node.type) 300 if not node.inst: 301 return 302 self._write(', ') 303 self.visit(node.inst) 304 if not node.tback: 305 return 306 self._write(', ') 307 self.visit(node.tback) 298 if IS_PYTHON2: 299 # Raise(expr? type, expr? inst, expr? tback) 300 def visit_Raise(self, node): 301 self._new_line() 302 self._write('raise') 303 if not node.type: 304 return 305 self._write(' ') 306 self.visit(node.type) 307 if not node.inst: 308 return 309 self._write(', ') 310 self.visit(node.inst) 311 if not node.tback: 312 return 313 self._write(', ') 314 self.visit(node.tback) 315 else: 316 # Raise(expr? exc from expr? cause) 317 def visit_Raise(self, node): 318 self._new_line() 319 self._write('raise') 320 if not node.exc: 321 return 322 self._write(' ') 323 self.visit(node.exc) 324 if not node.cause: 325 return 326 self._write(' from ') 327 self.visit(node.cause) 308 328 309 329 # TryExcept(stmt* body, excepthandler* handlers, stmt* orelse) … … 626 646 def visit_Str(self, node): 627 647 self._write(repr(node.s)) 648 649 if not IS_PYTHON2: 650 # Bytes(bytes s) 651 def visit_Bytes(self, node): 652 self._write(repr(node.s)) 628 653 629 654 # Attribute(expr value, identifier attr, expr_context ctx) -
branches/experimental/py3k/genshi/template/eval.py
r1120 r1142 24 24 from genshi.template.base import TemplateRuntimeError 25 25 from genshi.util import flatten 26 27 from genshi.compat import get_code_params, build_code_chunk, IS_PYTHON2 26 28 27 29 __all__ = ['Code', 'Expression', 'Suite', 'LenientLookup', 'StrictLookup', … … 99 101 state = {'source': self.source, 'ast': self.ast, 100 102 'lookup': self._globals.im_self} 101 c = self.code 102 state['code'] = (c.co_nlocals, c.co_stacksize, c.co_flags, c.co_code, 103 c.co_consts, c.co_names, c.co_varnames, c.co_filename, 104 c.co_name, c.co_firstlineno, c.co_lnotab, (), ()) 103 state['code'] = get_code_params(self.code) 105 104 return state 106 105 … … 237 236 reference that undefined variable. 238 237 239 >>> foo('bar') 240 Traceback (most recent call last): 241 ... 242 UndefinedError: "foo" not defined 243 244 >>> foo.bar 245 Traceback (most recent call last): 246 ... 247 UndefinedError: "foo" not defined 238 >>> try: 239 ... foo('bar') 240 ... except UndefinedError, e: 241 ... print e.msg 242 "foo" not defined 243 244 >>> try: 245 ... foo.bar 246 ... except UndefinedError, e: 247 ... print e.msg 248 "foo" not defined 248 249 249 250 :see: `LenientLookup` … … 389 390 390 391 >>> expr = Expression('nothing', lookup='strict') 391 >>> expr.evaluate({}) 392 Traceback (most recent call last): 393 ... 394 UndefinedError: "nothing" not defined 392 >>> try: 393 ... expr.evaluate({}) 394 ... except UndefinedError, e: 395 ... print e.msg 396 "nothing" not defined 395 397 396 398 The same happens when a non-existing attribute or item is accessed on an … … 398 400 399 401 >>> expr = Expression('something.nil', lookup='strict') 400 >>> expr.evaluate({'something': dict()}) 401 Traceback (most recent call last): 402 ... 403 UndefinedError: {} has no member named "nil" 402 >>> try: 403 ... expr.evaluate({'something': dict()}) 404 ... except UndefinedError, e: 405 ... print e.msg 406 {} has no member named "nil" 404 407 """ 405 408 … … 422 425 source = '\n'.join([first, rest]) 423 426 if isinstance(source, unicode): 424 source = '\xef\xbb\xbf' + source.encode('utf-8')427 source = (u'\ufeff' + source).encode('utf-8') 425 428 return parse(source, mode) 426 429 … … 428 431 def _compile(node, source=None, mode='eval', filename=None, lineno=-1, 429 432 xform=None): 430 if isinstance(filename, unicode): 431 # unicode file names not allowed for code objects 432 filename = filename.encode('utf-8', 'replace') 433 elif not filename: 433 if not filename: 434 434 filename = '<string>' 435 if IS_PYTHON2: 436 # Python 2 requires non-unicode filenames 437 if isinstance(filename, unicode): 438 filename = filename.encode('utf-8', 'replace') 439 else: 440 # Python 3 requires unicode filenames 441 if not isinstance(filename, unicode): 442 filename = filename.decode('utf-8', 'replace') 435 443 if lineno <= 0: 436 444 lineno = 1 … … 459 467 # We'd like to just set co_firstlineno, but it's readonly. So we need 460 468 # to clone the code object while adjusting the line number 461 return CodeType(0, code.co_nlocals, code.co_stacksize, 462 code.co_flags | 0x0040, code.co_code, code.co_consts, 463 code.co_names, code.co_varnames, filename, name, 464 lineno, code.co_lnotab, (), ()) 469 return build_code_chunk(code, filename, name, lineno) 465 470 except RuntimeError: 466 471 return code … … 494 499 names = set() 495 500 def _process(node): 501 if not IS_PYTHON2 and isinstance(node, _ast.arg): 502 names.add(node.arg) 496 503 if isinstance(node, _ast.Name): 497 504 names.add(node.id) … … 514 521 515 522 def visit_Str(self, node): 516 if isinstance(node.s, str):523 if not isinstance(node.s, unicode): 517 524 try: # If the string is ASCII, return a `str` object 518 525 node.s.decode('ascii') -
branches/experimental/py3k/genshi/template/tests/eval.py
r1120 r1142 15 15 import os 16 16 import pickle 17 from StringIO import StringIO18 17 import sys 19 18 from tempfile import mkstemp … … 24 23 from genshi.template.eval import Expression, Suite, Undefined, UndefinedError, \ 25 24 UNDEFINED 25 from genshi.compat import BytesIO, IS_PYTHON2, wrapped_bytes 26 26 27 27 … … 40 40 def test_pickle(self): 41 41 expr = Expression('1 < 2') 42 buf = StringIO()42 buf = BytesIO() 43 43 pickle.dump(expr, buf, 2) 44 44 buf.seek(0) … … 59 59 self.assertEqual('foo', Expression('"foo"').evaluate({})) 60 60 self.assertEqual('foo', Expression('"""foo"""').evaluate({})) 61 self.assertEqual('foo', Expression("'foo'").evaluate({})) 61 self.assertEqual(u'foo'.encode('utf-8'), 62 Expression(wrapped_bytes("b'foo'")).evaluate({})) 62 63 self.assertEqual('foo', Expression("'''foo'''").evaluate({})) 63 64 self.assertEqual('foo', Expression("u'foo'").evaluate({})) … … 69 70 expr = Expression("u'\xfe'") 70 71 self.assertEqual(u'þ', expr.evaluate({})) 71 expr = Expression("'\xc3\xbe'") 72 self.assertEqual(u'þ', expr.evaluate({})) 72 # On Python2 strings are converted to unicode if they contained 73 # non-ASCII characters. 74 # On Py3k, we have no need to do this as non-prefixed strings aren't 75 # raw. 76 expr = Expression(wrapped_bytes(r"b'\xc3\xbe'")) 77 if IS_PYTHON2: 78 self.assertEqual(u'þ', expr.evaluate({})) 79 else: 80 self.assertEqual(u'þ'.encode('utf-8'), expr.evaluate({})) 73 81 74 82 def test_num_literal(self): 75 83 self.assertEqual(42, Expression("42").evaluate({})) 76 self.assertEqual(42L, Expression("42L").evaluate({})) 84 if IS_PYTHON2: 85 self.assertEqual(42L, Expression("42L").evaluate({})) 77 86 self.assertEqual(.42, Expression(".42").evaluate({})) 78 self.assertEqual(07, Expression("07").evaluate({})) 87 if IS_PYTHON2: 88 self.assertEqual(07, Expression("07").evaluate({})) 79 89 self.assertEqual(0xF2, Expression("0xF2").evaluate({})) 80 90 self.assertEqual(0XF2, Expression("0XF2").evaluate({})) … … 247 257 data = {'items': range(5)} 248 258 expr = Expression("filter(lambda x: x > 2, items)") 249 self.assertEqual([3, 4], expr.evaluate(data))259 self.assertEqual([3, 4], list(expr.evaluate(data))) 250 260 251 261 def test_lambda_tuple_arg(self): 262 # This syntax goes away in Python 3 263 if not IS_PYTHON2: 264 return 252 265 data = {'items': [(1, 2), (2, 1)]} 253 266 expr = Expression("filter(lambda (x, y): x > y, items)") 254 self.assertEqual([(2, 1)], expr.evaluate(data))267 self.assertEqual([(2, 1)], list(expr.evaluate(data))) 255 268 256 269 def test_list_comprehension(self): … … 471 484 def test_pickle(self): 472 485 suite = Suite('foo = 42') 473 buf = StringIO()486 buf = BytesIO() 474 487 pickle.dump(suite, buf, 2) 475 488 buf.seek(0) … … 646 659 647 660 def test_import(self): 648 suite = Suite("from itertools import ifilter")649 data = {} 650 suite.execute(data) 651 assert ' ifilter' in data661 suite = Suite("from itertools import repeat") 662 data = {} 663 suite.execute(data) 664 assert 'repeat' in data 652 665 653 666 def test_import_star(self): … … 655 668 data = Context() 656 669 suite.execute(data) 657 assert ' ifilter' in data670 assert 'repeat' in data 658 671 659 672 def test_import_in_def(self): 660 673 suite = Suite("""def fun(): 661 from itertools import ifilter662 return ifilter(None, range(3))674 from itertools import repeat 675 return repeat(1, 3) 663 676 """) 664 677 data = Context() 665 678 suite.execute(data) 666 assert ' ifilter' not in data667 self.assertEqual([1, 2], list(data['fun']()))679 assert 'repeat' not in data 680 self.assertEqual([1, 1, 1], list(data['fun']())) 668 681 669 682 def test_for(self): … … 767 780 768 781 def test_exec(self): 769 suite = Suite("x = 1; exec d['k']; assert x == 42, x")782 suite = Suite("x = 1; exec(d['k']); assert x == 42, x") 770 783 suite.execute({"d": {"k": "x = 42"}}) 771 784 … … 829 842 def test_yield_expression(self): 830 843 d = {} 831 suite = Suite("""results = [] 844 suite = Suite("""from genshi.compat import next 845 results = [] 832 846 def counter(maximum): 833 847 i = 0 … … 839 853 i += 1 840 854 it = counter(5) 841 results.append( it.next())855 results.append(next(it)) 842 856 results.append(it.send(3)) 843 results.append( it.next())857 results.append(next(it)) 844 858 """) 845 859 suite.execute(d)
Note: See TracChangeset
for help on using the changeset viewer.
