diff --git a/Demo/parser/unparse.py b/Demo/parser/unparse.py index 24558858f31..53b57b39f5a 100644 --- a/Demo/parser/unparse.py +++ b/Demo/parser/unparse.py @@ -1,158 +1,158 @@ -"Usage: unparse.py " -import sys - -class Unparser: - """Methods in this class recursively traverse an AST and - output source code for the abstract syntax; original formatting - is disregarged. """ - - def __init__(self, tree, file = sys.stdout): - """Unparser(tree, file=sys.stdout) -> None. - Print the source for tree to file.""" - self.f = file - self._indent = 0 - self.dispatch(tree) - self.f.flush() - - def fill(self, text = ""): - "Indent a piece of text, according to the current indentation level" - self.f.write("\n"+" "*self._indent + text) - - def write(self, text): - "Append a piece of text to the current line." - self.f.write(text) - - def enter(self): - "Print ':', and increase the indentation." - self.write(":") - self._indent += 1 - - def leave(self): - "Decrease the indentation level." - self._indent -= 1 - - def dispatch(self, tree): - "Dispatcher function, dispatching tree type T to method _T." - if isinstance(tree, list): - for t in tree: - self.dispatch(t) - return - meth = getattr(self, "_"+tree.__class__.__name__) - meth(tree) - - - ############### Unparsing methods ###################### - # There should be one method per concrete grammar type # - # Constructors should be grouped by sum type. Ideally, # - # this would follow the order in the grammar, but # - # currently doesn't. # - ######################################################## - - def _Module(self, tree): - for stmt in tree.body: - self.dispatch(stmt) - - # stmt - def _Expr(self, tree): - self.fill() - self.dispatch(tree.value) - - def _Import(self, t): - self.fill("import ") - first = True - for a in t.names: - if first: - first = False - else: - self.write(", ") - self.write(a.name) - if a.asname: - self.write(" as "+a.asname) - - def _Assign(self, t): - self.fill() - for target in t.targets: - self.dispatch(target) - self.write(" = ") - self.dispatch(t.value) - - def _ClassDef(self, t): - self.write("\n") - self.fill("class "+t.name) - if t.bases: - self.write("(") - for a in t.bases: - self.dispatch(a) - self.write(", ") - self.write(")") - self.enter() - self.dispatch(t.body) - self.leave() - - def _FunctionDef(self, t): - self.write("\n") - self.fill("def "+t.name + "(") - self.dispatch(t.args) - self.enter() - self.dispatch(t.body) - self.leave() - - def _If(self, t): - self.fill("if ") - self.dispatch(t.test) - self.enter() - # XXX elif? - self.dispatch(t.body) - self.leave() - if t.orelse: - self.fill("else") - self.enter() - self.dispatch(t.orelse) - self.leave() - - # expr - def _Str(self, tree): - self.write(repr(tree.s)) - - def _Name(self, t): - self.write(t.id) - - def _List(self, t): - self.write("[") - for e in t.elts: - self.dispatch(e) - self.write(", ") - self.write("]") - - unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"} - def _UnaryOp(self, t): - self.write(self.unop[t.op.__class__.__name__]) - self.write("(") - self.dispatch(t.operand) - self.write(")") - - # others - def _arguments(self, t): - first = True - # XXX t.defaults - for a in t.args: - if first:first = False - else: self.write(", ") - self.dispatch(a) - if t.vararg: - if first:first = False - else: self.write(", ") - self.write("*"+t.vararg) - if t.kwarg: - if first:first = False - else: self.write(", ") - self.write("**"+self.kwarg) - self.write(")") - -def roundtrip(filename): - source = open(filename).read() - tree = compile(source, filename, "exec", 0x400) - Unparser(tree) - -if __name__=='__main__': - roundtrip(sys.argv[1]) +"Usage: unparse.py " +import sys + +class Unparser: + """Methods in this class recursively traverse an AST and + output source code for the abstract syntax; original formatting + is disregarged. """ + + def __init__(self, tree, file = sys.stdout): + """Unparser(tree, file=sys.stdout) -> None. + Print the source for tree to file.""" + self.f = file + self._indent = 0 + self.dispatch(tree) + self.f.flush() + + def fill(self, text = ""): + "Indent a piece of text, according to the current indentation level" + self.f.write("\n"+" "*self._indent + text) + + def write(self, text): + "Append a piece of text to the current line." + self.f.write(text) + + def enter(self): + "Print ':', and increase the indentation." + self.write(":") + self._indent += 1 + + def leave(self): + "Decrease the indentation level." + self._indent -= 1 + + def dispatch(self, tree): + "Dispatcher function, dispatching tree type T to method _T." + if isinstance(tree, list): + for t in tree: + self.dispatch(t) + return + meth = getattr(self, "_"+tree.__class__.__name__) + meth(tree) + + + ############### Unparsing methods ###################### + # There should be one method per concrete grammar type # + # Constructors should be grouped by sum type. Ideally, # + # this would follow the order in the grammar, but # + # currently doesn't. # + ######################################################## + + def _Module(self, tree): + for stmt in tree.body: + self.dispatch(stmt) + + # stmt + def _Expr(self, tree): + self.fill() + self.dispatch(tree.value) + + def _Import(self, t): + self.fill("import ") + first = True + for a in t.names: + if first: + first = False + else: + self.write(", ") + self.write(a.name) + if a.asname: + self.write(" as "+a.asname) + + def _Assign(self, t): + self.fill() + for target in t.targets: + self.dispatch(target) + self.write(" = ") + self.dispatch(t.value) + + def _ClassDef(self, t): + self.write("\n") + self.fill("class "+t.name) + if t.bases: + self.write("(") + for a in t.bases: + self.dispatch(a) + self.write(", ") + self.write(")") + self.enter() + self.dispatch(t.body) + self.leave() + + def _FunctionDef(self, t): + self.write("\n") + self.fill("def "+t.name + "(") + self.dispatch(t.args) + self.enter() + self.dispatch(t.body) + self.leave() + + def _If(self, t): + self.fill("if ") + self.dispatch(t.test) + self.enter() + # XXX elif? + self.dispatch(t.body) + self.leave() + if t.orelse: + self.fill("else") + self.enter() + self.dispatch(t.orelse) + self.leave() + + # expr + def _Str(self, tree): + self.write(repr(tree.s)) + + def _Name(self, t): + self.write(t.id) + + def _List(self, t): + self.write("[") + for e in t.elts: + self.dispatch(e) + self.write(", ") + self.write("]") + + unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"} + def _UnaryOp(self, t): + self.write(self.unop[t.op.__class__.__name__]) + self.write("(") + self.dispatch(t.operand) + self.write(")") + + # others + def _arguments(self, t): + first = True + # XXX t.defaults + for a in t.args: + if first:first = False + else: self.write(", ") + self.dispatch(a) + if t.vararg: + if first:first = False + else: self.write(", ") + self.write("*"+t.vararg) + if t.kwarg: + if first:first = False + else: self.write(", ") + self.write("**"+self.kwarg) + self.write(")") + +def roundtrip(filename): + source = open(filename).read() + tree = compile(source, filename, "exec", 0x400) + Unparser(tree) + +if __name__=='__main__': + roundtrip(sys.argv[1]) diff --git a/Lib/compiler/ast.py b/Lib/compiler/ast.py index e270995fa81..6e3e1825719 100644 --- a/Lib/compiler/ast.py +++ b/Lib/compiler/ast.py @@ -553,7 +553,7 @@ class Function(Node): self.varargs = 1 if flags & CO_VARKEYWORDS: self.kwargs = 1 - + def getChildren(self): @@ -584,7 +584,7 @@ class GenExpr(Node): self.lineno = lineno self.argnames = ['[outmost-iterable]'] self.varargs = self.kwargs = None - + def getChildren(self): @@ -763,7 +763,7 @@ class Lambda(Node): self.varargs = 1 if flags & CO_VARKEYWORDS: self.kwargs = 1 - + def getChildren(self): diff --git a/Lib/test/contextmanager.py b/Lib/test/contextmanager.py index 0ebf646f919..e8b08946196 100644 --- a/Lib/test/contextmanager.py +++ b/Lib/test/contextmanager.py @@ -1,34 +1,33 @@ -class GeneratorContextManager(object): - def __init__(self, gen): - self.gen = gen - - def __context__(self): - return self - - def __enter__(self): - try: - return self.gen.next() - except StopIteration: - raise RuntimeError("generator didn't yield") - - def __exit__(self, type, value, traceback): - if type is None: - try: - self.gen.next() - except StopIteration: - return - else: - raise RuntimeError("generator didn't stop") - else: - try: - self.gen.throw(type, value, traceback) - except (type, StopIteration): - return - else: - raise RuntimeError("generator caught exception") - -def contextmanager(func): - def helper(*args, **kwds): - return GeneratorContextManager(func(*args, **kwds)) - return helper - +class GeneratorContextManager(object): + def __init__(self, gen): + self.gen = gen + + def __context__(self): + return self + + def __enter__(self): + try: + return self.gen.next() + except StopIteration: + raise RuntimeError("generator didn't yield") + + def __exit__(self, type, value, traceback): + if type is None: + try: + self.gen.next() + except StopIteration: + return + else: + raise RuntimeError("generator didn't stop") + else: + try: + self.gen.throw(type, value, traceback) + except (type, StopIteration): + return + else: + raise RuntimeError("generator caught exception") + +def contextmanager(func): + def helper(*args, **kwds): + return GeneratorContextManager(func(*args, **kwds)) + return helper diff --git a/Lib/test/nested.py b/Lib/test/nested.py index bb210d462ac..a20cf43e7a6 100644 --- a/Lib/test/nested.py +++ b/Lib/test/nested.py @@ -1,41 +1,40 @@ -import sys -from collections import deque - - -class nested(object): - def __init__(self, *contexts): - self.contexts = contexts - self.entered = None - - def __context__(self): - return self - - def __enter__(self): - if self.entered is not None: - raise RuntimeError("Context is not reentrant") - self.entered = deque() - vars = [] - try: - for context in self.contexts: - mgr = context.__context__() - vars.append(mgr.__enter__()) - self.entered.appendleft(mgr) - except: - self.__exit__(*sys.exc_info()) - raise - return vars - - def __exit__(self, *exc_info): - # Behave like nested with statements - # first in, last out - # New exceptions override old ones - ex = exc_info - for mgr in self.entered: - try: - mgr.__exit__(*ex) - except: - ex = sys.exc_info() - self.entered = None - if ex is not exc_info: - raise ex[0], ex[1], ex[2] - +import sys +from collections import deque + + +class nested(object): + def __init__(self, *contexts): + self.contexts = contexts + self.entered = None + + def __context__(self): + return self + + def __enter__(self): + if self.entered is not None: + raise RuntimeError("Context is not reentrant") + self.entered = deque() + vars = [] + try: + for context in self.contexts: + mgr = context.__context__() + vars.append(mgr.__enter__()) + self.entered.appendleft(mgr) + except: + self.__exit__(*sys.exc_info()) + raise + return vars + + def __exit__(self, *exc_info): + # Behave like nested with statements + # first in, last out + # New exceptions override old ones + ex = exc_info + for mgr in self.entered: + try: + mgr.__exit__(*ex) + except: + ex = sys.exc_info() + self.entered = None + if ex is not exc_info: + raise ex[0], ex[1], ex[2] diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index 83a1baad8f9..f83dc92de6b 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -1,179 +1,178 @@ -import sys, itertools - -def to_tuple(t): - if t is None or isinstance(t, (basestring, int, long, complex)): - return t - elif isinstance(t, list): - return [to_tuple(e) for e in t] - result = [t.__class__.__name__] - if t._fields is None: - return tuple(result) - for f in t._fields: - result.append(to_tuple(getattr(t, f))) - return tuple(result) - -# These tests are compiled through "exec" -# There should be atleast one test per statement -exec_tests = [ - # FunctionDef - "def f(): pass", - # ClassDef - "class C:pass", - # Return - "def f():return 1", - # Delete - "del v", - # Assign - "v = 1", - # AugAssign - "v += 1", - # Print - "print >>f, 1, ", - # For - "for v in v:pass", - # While - "while v:pass", - # If - "if v:pass", - # Raise - "raise Exception, 'string'", - # TryExcept - "try:\n pass\nexcept Exception:\n pass", - # TryFinally - "try:\n pass\nfinally:\n pass", - # Assert - "assert v", - # Import - "import sys", - # ImportFrom - "from sys import v", - # Exec - "exec 'v'", - # Global - "global v", - # Expr - "1", - # Pass, - "pass", - # Break - "break", - # Continue - "continue", -] - -# These are compiled through "single" -# because of overlap with "eval", it just tests what -# can't be tested with "eval" -single_tests = [ - "1+2" -] - -# These are compiled through "eval" -# It should test all expressions -eval_tests = [ - # BoolOp - "a and b", - # BinOp - "a + b", - # UnaryOp - "not v", - # Lambda - "lambda:None", - # Dict - "{ 1:2 }", - # ListComp - "[a for b in c if d]", - # GeneratorExp - "(a for b in c if d)", - # Yield - yield expressions can't work outside a function - # - # Compare - "1 < 2 < 3", - # Call - "f(1,2,c=3,*d,**e)", - # Repr - "`v`", - # Num - "10L", - # Str - "'string'", - # Attribute - "a.b", - # Subscript - "a[b:c]", - # Name - "v", - # List - "[1,2,3]", - # Tuple - "1,2,3" -] - -# TODO: expr_context, slice, boolop, operator, unaryop, cmpop, comprehension -# excepthandler, arguments, keywords, alias - -if __name__=='__main__' and sys.argv[1:] == ['-g']: - for statements, kind in ((exec_tests, "exec"), (single_tests, "single"), (eval_tests, "eval")): - print kind+"_results = [" - for s in statements: - print repr(to_tuple(compile(s, "?", kind, 0x400)))+"," - print "]" - print "run_tests()" - raise SystemExit - -def run_tests(): - for input, output, kind in ((exec_tests, exec_results, "exec"), - (single_tests, single_results, "single"), - (eval_tests, eval_results, "eval")): - for i, o in itertools.izip(input, output): - assert to_tuple(compile(i, "?", kind, 0x400)) == o - -#### EVERYTHING BELOW IS GENERATED ##### -exec_results = [ -('Module', [('FunctionDef', 'f', ('arguments', [], None, None, []), [('Pass',)], [])]), -('Module', [('ClassDef', 'C', [], [('Pass',)])]), -('Module', [('FunctionDef', 'f', ('arguments', [], None, None, []), [('Return', ('Num', 1))], [])]), -('Module', [('Delete', [('Name', 'v', ('Del',))])]), -('Module', [('Assign', [('Name', 'v', ('Store',))], ('Num', 1))]), -('Module', [('AugAssign', ('Name', 'v', ('Load',)), ('Add',), ('Num', 1))]), -('Module', [('Print', ('Name', 'f', ('Load',)), [('Num', 1)], False)]), -('Module', [('For', ('Name', 'v', ('Store',)), ('Name', 'v', ('Load',)), [('Pass',)], [])]), -('Module', [('While', ('Name', 'v', ('Load',)), [('Pass',)], [])]), -('Module', [('If', ('Name', 'v', ('Load',)), [('Pass',)], [])]), -('Module', [('Raise', ('Name', 'Exception', ('Load',)), ('Str', 'string'), None)]), -('Module', [('TryExcept', [('Pass',)], [('excepthandler', ('Name', 'Exception', ('Load',)), None, [('Pass',)])], [])]), -('Module', [('TryFinally', [('Pass',)], [('Pass',)])]), -('Module', [('Assert', ('Name', 'v', ('Load',)), None)]), -('Module', [('Import', [('alias', 'sys', None)])]), -('Module', [('ImportFrom', 'sys', [('alias', 'v', None)], 0)]), -('Module', [('Exec', ('Str', 'v'), None, None)]), -('Module', [('Global', ['v'])]), -('Module', [('Expr', ('Num', 1))]), -('Module', [('Pass',)]), -('Module', [('Break',)]), -('Module', [('Continue',)]), -] -single_results = [ -('Interactive', [('Expr', ('BinOp', ('Num', 1), ('Add',), ('Num', 2)))]), -] -eval_results = [ -('Expression', ('BoolOp', ('And',), [('Name', 'a', ('Load',)), ('Name', 'b', ('Load',))])), -('Expression', ('BinOp', ('Name', 'a', ('Load',)), ('Add',), ('Name', 'b', ('Load',)))), -('Expression', ('UnaryOp', ('Not',), ('Name', 'v', ('Load',)))), -('Expression', ('Lambda', ('arguments', [], None, None, []), ('Name', 'None', ('Load',)))), -('Expression', ('Dict', [('Num', 1)], [('Num', 2)])), -('Expression', ('ListComp', ('Name', 'a', ('Load',)), [('comprehension', ('Name', 'b', ('Store',)), ('Name', 'c', ('Load',)), [('Name', 'd', ('Load',))])])), -('Expression', ('GeneratorExp', ('Name', 'a', ('Load',)), [('comprehension', ('Name', 'b', ('Store',)), ('Name', 'c', ('Load',)), [('Name', 'd', ('Load',))])])), -('Expression', ('Compare', ('Num', 1), [('Lt',), ('Lt',)], [('Num', 2), ('Num', 3)])), -('Expression', ('Call', ('Name', 'f', ('Load',)), [('Num', 1), ('Num', 2)], [('keyword', 'c', ('Num', 3))], ('Name', 'd', ('Load',)), ('Name', 'e', ('Load',)))), -('Expression', ('Repr', ('Name', 'v', ('Load',)))), -('Expression', ('Num', 10L)), -('Expression', ('Str', 'string')), -('Expression', ('Attribute', ('Name', 'a', ('Load',)), 'b', ('Load',))), -('Expression', ('Subscript', ('Name', 'a', ('Load',)), ('Slice', ('Name', 'b', ('Load',)), ('Name', 'c', ('Load',)), None), ('Load',))), -('Expression', ('Name', 'v', ('Load',))), -('Expression', ('List', [('Num', 1), ('Num', 2), ('Num', 3)], ('Load',))), -('Expression', ('Tuple', [('Num', 1), ('Num', 2), ('Num', 3)], ('Load',))), -] -run_tests() - +import sys, itertools + +def to_tuple(t): + if t is None or isinstance(t, (basestring, int, long, complex)): + return t + elif isinstance(t, list): + return [to_tuple(e) for e in t] + result = [t.__class__.__name__] + if t._fields is None: + return tuple(result) + for f in t._fields: + result.append(to_tuple(getattr(t, f))) + return tuple(result) + +# These tests are compiled through "exec" +# There should be atleast one test per statement +exec_tests = [ + # FunctionDef + "def f(): pass", + # ClassDef + "class C:pass", + # Return + "def f():return 1", + # Delete + "del v", + # Assign + "v = 1", + # AugAssign + "v += 1", + # Print + "print >>f, 1, ", + # For + "for v in v:pass", + # While + "while v:pass", + # If + "if v:pass", + # Raise + "raise Exception, 'string'", + # TryExcept + "try:\n pass\nexcept Exception:\n pass", + # TryFinally + "try:\n pass\nfinally:\n pass", + # Assert + "assert v", + # Import + "import sys", + # ImportFrom + "from sys import v", + # Exec + "exec 'v'", + # Global + "global v", + # Expr + "1", + # Pass, + "pass", + # Break + "break", + # Continue + "continue", +] + +# These are compiled through "single" +# because of overlap with "eval", it just tests what +# can't be tested with "eval" +single_tests = [ + "1+2" +] + +# These are compiled through "eval" +# It should test all expressions +eval_tests = [ + # BoolOp + "a and b", + # BinOp + "a + b", + # UnaryOp + "not v", + # Lambda + "lambda:None", + # Dict + "{ 1:2 }", + # ListComp + "[a for b in c if d]", + # GeneratorExp + "(a for b in c if d)", + # Yield - yield expressions can't work outside a function + # + # Compare + "1 < 2 < 3", + # Call + "f(1,2,c=3,*d,**e)", + # Repr + "`v`", + # Num + "10L", + # Str + "'string'", + # Attribute + "a.b", + # Subscript + "a[b:c]", + # Name + "v", + # List + "[1,2,3]", + # Tuple + "1,2,3" +] + +# TODO: expr_context, slice, boolop, operator, unaryop, cmpop, comprehension +# excepthandler, arguments, keywords, alias + +if __name__=='__main__' and sys.argv[1:] == ['-g']: + for statements, kind in ((exec_tests, "exec"), (single_tests, "single"), (eval_tests, "eval")): + print kind+"_results = [" + for s in statements: + print repr(to_tuple(compile(s, "?", kind, 0x400)))+"," + print "]" + print "run_tests()" + raise SystemExit + +def run_tests(): + for input, output, kind in ((exec_tests, exec_results, "exec"), + (single_tests, single_results, "single"), + (eval_tests, eval_results, "eval")): + for i, o in itertools.izip(input, output): + assert to_tuple(compile(i, "?", kind, 0x400)) == o + +#### EVERYTHING BELOW IS GENERATED ##### +exec_results = [ +('Module', [('FunctionDef', 'f', ('arguments', [], None, None, []), [('Pass',)], [])]), +('Module', [('ClassDef', 'C', [], [('Pass',)])]), +('Module', [('FunctionDef', 'f', ('arguments', [], None, None, []), [('Return', ('Num', 1))], [])]), +('Module', [('Delete', [('Name', 'v', ('Del',))])]), +('Module', [('Assign', [('Name', 'v', ('Store',))], ('Num', 1))]), +('Module', [('AugAssign', ('Name', 'v', ('Load',)), ('Add',), ('Num', 1))]), +('Module', [('Print', ('Name', 'f', ('Load',)), [('Num', 1)], False)]), +('Module', [('For', ('Name', 'v', ('Store',)), ('Name', 'v', ('Load',)), [('Pass',)], [])]), +('Module', [('While', ('Name', 'v', ('Load',)), [('Pass',)], [])]), +('Module', [('If', ('Name', 'v', ('Load',)), [('Pass',)], [])]), +('Module', [('Raise', ('Name', 'Exception', ('Load',)), ('Str', 'string'), None)]), +('Module', [('TryExcept', [('Pass',)], [('excepthandler', ('Name', 'Exception', ('Load',)), None, [('Pass',)])], [])]), +('Module', [('TryFinally', [('Pass',)], [('Pass',)])]), +('Module', [('Assert', ('Name', 'v', ('Load',)), None)]), +('Module', [('Import', [('alias', 'sys', None)])]), +('Module', [('ImportFrom', 'sys', [('alias', 'v', None)], 0)]), +('Module', [('Exec', ('Str', 'v'), None, None)]), +('Module', [('Global', ['v'])]), +('Module', [('Expr', ('Num', 1))]), +('Module', [('Pass',)]), +('Module', [('Break',)]), +('Module', [('Continue',)]), +] +single_results = [ +('Interactive', [('Expr', ('BinOp', ('Num', 1), ('Add',), ('Num', 2)))]), +] +eval_results = [ +('Expression', ('BoolOp', ('And',), [('Name', 'a', ('Load',)), ('Name', 'b', ('Load',))])), +('Expression', ('BinOp', ('Name', 'a', ('Load',)), ('Add',), ('Name', 'b', ('Load',)))), +('Expression', ('UnaryOp', ('Not',), ('Name', 'v', ('Load',)))), +('Expression', ('Lambda', ('arguments', [], None, None, []), ('Name', 'None', ('Load',)))), +('Expression', ('Dict', [('Num', 1)], [('Num', 2)])), +('Expression', ('ListComp', ('Name', 'a', ('Load',)), [('comprehension', ('Name', 'b', ('Store',)), ('Name', 'c', ('Load',)), [('Name', 'd', ('Load',))])])), +('Expression', ('GeneratorExp', ('Name', 'a', ('Load',)), [('comprehension', ('Name', 'b', ('Store',)), ('Name', 'c', ('Load',)), [('Name', 'd', ('Load',))])])), +('Expression', ('Compare', ('Num', 1), [('Lt',), ('Lt',)], [('Num', 2), ('Num', 3)])), +('Expression', ('Call', ('Name', 'f', ('Load',)), [('Num', 1), ('Num', 2)], [('keyword', 'c', ('Num', 3))], ('Name', 'd', ('Load',)), ('Name', 'e', ('Load',)))), +('Expression', ('Repr', ('Name', 'v', ('Load',)))), +('Expression', ('Num', 10L)), +('Expression', ('Str', 'string')), +('Expression', ('Attribute', ('Name', 'a', ('Load',)), 'b', ('Load',))), +('Expression', ('Subscript', ('Name', 'a', ('Load',)), ('Slice', ('Name', 'b', ('Load',)), ('Name', 'c', ('Load',)), None), ('Load',))), +('Expression', ('Name', 'v', ('Load',))), +('Expression', ('List', [('Num', 1), ('Num', 2), ('Num', 3)], ('Load',))), +('Expression', ('Tuple', [('Num', 1), ('Num', 2), ('Num', 3)], ('Load',))), +] +run_tests() diff --git a/Lib/test/test_importhooks.py b/Lib/test/test_importhooks.py index c58075543b4..5af7847aa45 100644 --- a/Lib/test/test_importhooks.py +++ b/Lib/test/test_importhooks.py @@ -190,7 +190,7 @@ class ImportHooksTestCase(ImportHooksBaseTestCase): TestImporter.modules['reloadmodule'] = (False, reload_co) reload(reloadmodule) self.failUnless(hasattr(reloadmodule,'reloaded')) - + import hooktestpackage.oldabs self.assertEqual(hooktestpackage.oldabs.get_name(), "hooktestpackage.oldabs") @@ -208,7 +208,7 @@ class ImportHooksTestCase(ImportHooksBaseTestCase): "hooktestpackage.futrel") self.assertEqual(hooktestpackage.futrel.sub, hooktestpackage.sub) - + import sub self.assertEqual(sub.get_name(), "sub") diff --git a/Lib/test/test_with.py b/Lib/test/test_with.py index 9d809efd739..3f328305329 100644 --- a/Lib/test/test_with.py +++ b/Lib/test/test_with.py @@ -1,560 +1,560 @@ -#!/usr/bin/env python - -"""Unit tests for the with statement specified in PEP 343.""" - -__author__ = "Mike Bland" -__email__ = "mbland at acm dot org" - -import unittest -from test.contextmanager import GeneratorContextManager -from test.nested import nested -from test.test_support import run_unittest - - -class MockContextManager(GeneratorContextManager): - def __init__(self, gen): - GeneratorContextManager.__init__(self, gen) - self.context_called = False - self.enter_called = False - self.exit_called = False - self.exit_args = None - - def __context__(self): - self.context_called = True - return GeneratorContextManager.__context__(self) - - def __enter__(self): - self.enter_called = True - return GeneratorContextManager.__enter__(self) - - def __exit__(self, type, value, traceback): - self.exit_called = True - self.exit_args = (type, value, traceback) - return GeneratorContextManager.__exit__(self, type, value, traceback) - - -def mock_contextmanager(func): - def helper(*args, **kwds): - return MockContextManager(func(*args, **kwds)) - return helper - - -class MockResource(object): - def __init__(self): - self.yielded = False - self.stopped = False - - -@mock_contextmanager -def mock_contextmanager_generator(): - mock = MockResource() - try: - mock.yielded = True - yield mock - finally: - mock.stopped = True - - -class MockNested(nested): - def __init__(self, *contexts): - nested.__init__(self, *contexts) - self.context_called = False - self.enter_called = False - self.exit_called = False - self.exit_args = None - - def __context__(self): - self.context_called = True - return nested.__context__(self) - - def __enter__(self): - self.enter_called = True - return nested.__enter__(self) - - def __exit__(self, *exc_info): - self.exit_called = True - self.exit_args = exc_info - return nested.__exit__(self, *exc_info) - - -class FailureTestCase(unittest.TestCase): - def testNameError(self): - def fooNotDeclared(): - with foo: pass - self.assertRaises(NameError, fooNotDeclared) - - def testContextAttributeError(self): - class LacksContext(object): - def __enter__(self): - pass - - def __exit__(self, type, value, traceback): - pass - - def fooLacksContext(): - foo = LacksContext() - with foo: pass - self.assertRaises(AttributeError, fooLacksContext) - - def testEnterAttributeError(self): - class LacksEnter(object): - def __context__(self): - pass - - def __exit__(self, type, value, traceback): - pass - - def fooLacksEnter(): - foo = LacksEnter() - with foo: pass - self.assertRaises(AttributeError, fooLacksEnter) - - def testExitAttributeError(self): - class LacksExit(object): - def __context__(self): - pass - - def __enter__(self): - pass - - def fooLacksExit(): - foo = LacksExit() - with foo: pass - self.assertRaises(AttributeError, fooLacksExit) - - def assertRaisesSyntaxError(self, codestr): - def shouldRaiseSyntaxError(s): - compile(s, '', 'single') - self.assertRaises(SyntaxError, shouldRaiseSyntaxError, codestr) - - def testAssignmentToNoneError(self): - self.assertRaisesSyntaxError('with mock as None:\n pass') - self.assertRaisesSyntaxError( - 'with mock as (None):\n' - ' pass') - - def testAssignmentToEmptyTupleError(self): - self.assertRaisesSyntaxError( - 'with mock as ():\n' - ' pass') - - def testAssignmentToTupleOnlyContainingNoneError(self): - self.assertRaisesSyntaxError('with mock as None,:\n pass') - self.assertRaisesSyntaxError( - 'with mock as (None,):\n' - ' pass') - - def testAssignmentToTupleContainingNoneError(self): - self.assertRaisesSyntaxError( - 'with mock as (foo, None, bar):\n' - ' pass') - - def testContextThrows(self): - class ContextThrows(object): - def __context__(self): - raise RuntimeError("Context threw") - - def shouldThrow(): - ct = ContextThrows() - self.foo = None - with ct as self.foo: - pass - self.assertRaises(RuntimeError, shouldThrow) - self.assertEqual(self.foo, None) - - def testEnterThrows(self): - class EnterThrows(object): - def __context__(self): - return self - - def __enter__(self): - raise RuntimeError("Context threw") - - def __exit__(self, *args): - pass - - def shouldThrow(): - ct = EnterThrows() - self.foo = None - with ct as self.foo: - pass - self.assertRaises(RuntimeError, shouldThrow) - self.assertEqual(self.foo, None) - - def testExitThrows(self): - class ExitThrows(object): - def __context__(self): - return self - def __enter__(self): - return - def __exit__(self, *args): - raise RuntimeError(42) - def shouldThrow(): - with ExitThrows(): - pass - self.assertRaises(RuntimeError, shouldThrow) - -class ContextmanagerAssertionMixin(object): - TEST_EXCEPTION = RuntimeError("test exception") - - def assertInWithManagerInvariants(self, mock_manager): - self.assertTrue(mock_manager.context_called) - self.assertTrue(mock_manager.enter_called) - self.assertFalse(mock_manager.exit_called) - self.assertEqual(mock_manager.exit_args, None) - - def assertAfterWithManagerInvariants(self, mock_manager, exit_args): - self.assertTrue(mock_manager.context_called) - self.assertTrue(mock_manager.enter_called) - self.assertTrue(mock_manager.exit_called) - self.assertEqual(mock_manager.exit_args, exit_args) - - def assertAfterWithManagerInvariantsNoError(self, mock_manager): - self.assertAfterWithManagerInvariants(mock_manager, - (None, None, None)) - - def assertInWithGeneratorInvariants(self, mock_generator): - self.assertTrue(mock_generator.yielded) - self.assertFalse(mock_generator.stopped) - - def assertAfterWithGeneratorInvariantsNoError(self, mock_generator): - self.assertTrue(mock_generator.yielded) - self.assertTrue(mock_generator.stopped) - - def raiseTestException(self): - raise self.TEST_EXCEPTION - - def assertAfterWithManagerInvariantsWithError(self, mock_manager): - self.assertTrue(mock_manager.context_called) - self.assertTrue(mock_manager.enter_called) - self.assertTrue(mock_manager.exit_called) - self.assertEqual(mock_manager.exit_args[0], RuntimeError) - self.assertEqual(mock_manager.exit_args[1], self.TEST_EXCEPTION) - - def assertAfterWithGeneratorInvariantsWithError(self, mock_generator): - self.assertTrue(mock_generator.yielded) - self.assertTrue(mock_generator.stopped) - - -class NonexceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin): - def testInlineGeneratorSyntax(self): - with mock_contextmanager_generator(): - pass - - def testUnboundGenerator(self): - mock = mock_contextmanager_generator() - with mock: - pass - self.assertAfterWithManagerInvariantsNoError(mock) - - def testInlineGeneratorBoundSyntax(self): - with mock_contextmanager_generator() as foo: - self.assertInWithGeneratorInvariants(foo) - # FIXME: In the future, we'll try to keep the bound names from leaking - self.assertAfterWithGeneratorInvariantsNoError(foo) - - def testInlineGeneratorBoundToExistingVariable(self): - foo = None - with mock_contextmanager_generator() as foo: - self.assertInWithGeneratorInvariants(foo) - self.assertAfterWithGeneratorInvariantsNoError(foo) - - def testInlineGeneratorBoundToDottedVariable(self): - with mock_contextmanager_generator() as self.foo: - self.assertInWithGeneratorInvariants(self.foo) - self.assertAfterWithGeneratorInvariantsNoError(self.foo) - - def testBoundGenerator(self): - mock = mock_contextmanager_generator() - with mock as foo: - self.assertInWithGeneratorInvariants(foo) - self.assertInWithManagerInvariants(mock) - self.assertAfterWithGeneratorInvariantsNoError(foo) - self.assertAfterWithManagerInvariantsNoError(mock) - - def testNestedSingleStatements(self): - mock_a = mock_contextmanager_generator() - with mock_a as foo: - mock_b = mock_contextmanager_generator() - with mock_b as bar: - self.assertInWithManagerInvariants(mock_a) - self.assertInWithManagerInvariants(mock_b) - self.assertInWithGeneratorInvariants(foo) - self.assertInWithGeneratorInvariants(bar) - self.assertAfterWithManagerInvariantsNoError(mock_b) - self.assertAfterWithGeneratorInvariantsNoError(bar) - self.assertInWithManagerInvariants(mock_a) - self.assertInWithGeneratorInvariants(foo) - self.assertAfterWithManagerInvariantsNoError(mock_a) - self.assertAfterWithGeneratorInvariantsNoError(foo) - - -class NestedNonexceptionalTestCase(unittest.TestCase, - ContextmanagerAssertionMixin): - def testSingleArgInlineGeneratorSyntax(self): - with nested(mock_contextmanager_generator()): - pass - - def testSingleArgUnbound(self): - mock_contextmanager = mock_contextmanager_generator() - mock_nested = MockNested(mock_contextmanager) - with mock_nested: - self.assertInWithManagerInvariants(mock_contextmanager) - self.assertInWithManagerInvariants(mock_nested) - self.assertAfterWithManagerInvariantsNoError(mock_contextmanager) - self.assertAfterWithManagerInvariantsNoError(mock_nested) - - def testSingleArgBoundToNonTuple(self): - m = mock_contextmanager_generator() - # This will bind all the arguments to nested() into a single list - # assigned to foo. - with nested(m) as foo: - self.assertInWithManagerInvariants(m) - self.assertAfterWithManagerInvariantsNoError(m) - - def testSingleArgBoundToSingleElementParenthesizedList(self): - m = mock_contextmanager_generator() - # This will bind all the arguments to nested() into a single list - # assigned to foo. - # FIXME: what should this do: with nested(m) as (foo,): - with nested(m) as (foo): - self.assertInWithManagerInvariants(m) - self.assertAfterWithManagerInvariantsNoError(m) - - def testSingleArgBoundToMultipleElementTupleError(self): - def shouldThrowValueError(): - with nested(mock_contextmanager_generator()) as (foo, bar): - pass - self.assertRaises(ValueError, shouldThrowValueError) - - def testSingleArgUnbound(self): - mock_contextmanager = mock_contextmanager_generator() - mock_nested = MockNested(mock_contextmanager) - with mock_nested: - self.assertInWithManagerInvariants(mock_contextmanager) - self.assertInWithManagerInvariants(mock_nested) - self.assertAfterWithManagerInvariantsNoError(mock_contextmanager) - self.assertAfterWithManagerInvariantsNoError(mock_nested) - - def testMultipleArgUnbound(self): - m = mock_contextmanager_generator() - n = mock_contextmanager_generator() - o = mock_contextmanager_generator() - mock_nested = MockNested(m, n, o) - with mock_nested: - self.assertInWithManagerInvariants(m) - self.assertInWithManagerInvariants(n) - self.assertInWithManagerInvariants(o) - self.assertInWithManagerInvariants(mock_nested) - self.assertAfterWithManagerInvariantsNoError(m) - self.assertAfterWithManagerInvariantsNoError(n) - self.assertAfterWithManagerInvariantsNoError(o) - self.assertAfterWithManagerInvariantsNoError(mock_nested) - - def testMultipleArgBound(self): - mock_nested = MockNested(mock_contextmanager_generator(), - mock_contextmanager_generator(), mock_contextmanager_generator()) - with mock_nested as (m, n, o): - self.assertInWithGeneratorInvariants(m) - self.assertInWithGeneratorInvariants(n) - self.assertInWithGeneratorInvariants(o) - self.assertInWithManagerInvariants(mock_nested) - self.assertAfterWithGeneratorInvariantsNoError(m) - self.assertAfterWithGeneratorInvariantsNoError(n) - self.assertAfterWithGeneratorInvariantsNoError(o) - self.assertAfterWithManagerInvariantsNoError(mock_nested) - - -class ExceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin): - def testSingleResource(self): - cm = mock_contextmanager_generator() - def shouldThrow(): - with cm as self.resource: - self.assertInWithManagerInvariants(cm) - self.assertInWithGeneratorInvariants(self.resource) - self.raiseTestException() - self.assertRaises(RuntimeError, shouldThrow) - self.assertAfterWithManagerInvariantsWithError(cm) - self.assertAfterWithGeneratorInvariantsWithError(self.resource) - - def testNestedSingleStatements(self): - mock_a = mock_contextmanager_generator() - mock_b = mock_contextmanager_generator() - def shouldThrow(): - with mock_a as self.foo: - with mock_b as self.bar: - self.assertInWithManagerInvariants(mock_a) - self.assertInWithManagerInvariants(mock_b) - self.assertInWithGeneratorInvariants(self.foo) - self.assertInWithGeneratorInvariants(self.bar) - self.raiseTestException() - self.assertRaises(RuntimeError, shouldThrow) - self.assertAfterWithManagerInvariantsWithError(mock_a) - self.assertAfterWithManagerInvariantsWithError(mock_b) - self.assertAfterWithGeneratorInvariantsWithError(self.foo) - self.assertAfterWithGeneratorInvariantsWithError(self.bar) - - def testMultipleResourcesInSingleStatement(self): - cm_a = mock_contextmanager_generator() - cm_b = mock_contextmanager_generator() - mock_nested = MockNested(cm_a, cm_b) - def shouldThrow(): - with mock_nested as (self.resource_a, self.resource_b): - self.assertInWithManagerInvariants(cm_a) - self.assertInWithManagerInvariants(cm_b) - self.assertInWithManagerInvariants(mock_nested) - self.assertInWithGeneratorInvariants(self.resource_a) - self.assertInWithGeneratorInvariants(self.resource_b) - self.raiseTestException() - self.assertRaises(RuntimeError, shouldThrow) - self.assertAfterWithManagerInvariantsWithError(cm_a) - self.assertAfterWithManagerInvariantsWithError(cm_b) - self.assertAfterWithManagerInvariantsWithError(mock_nested) - self.assertAfterWithGeneratorInvariantsWithError(self.resource_a) - self.assertAfterWithGeneratorInvariantsWithError(self.resource_b) - - def testNestedExceptionBeforeInnerStatement(self): - mock_a = mock_contextmanager_generator() - mock_b = mock_contextmanager_generator() - self.bar = None - def shouldThrow(): - with mock_a as self.foo: - self.assertInWithManagerInvariants(mock_a) - self.assertInWithGeneratorInvariants(self.foo) - self.raiseTestException() - with mock_b as self.bar: - pass - self.assertRaises(RuntimeError, shouldThrow) - self.assertAfterWithManagerInvariantsWithError(mock_a) - self.assertAfterWithGeneratorInvariantsWithError(self.foo) - - # The inner statement stuff should never have been touched - self.assertEqual(self.bar, None) - self.assertFalse(mock_b.context_called) - self.assertFalse(mock_b.enter_called) - self.assertFalse(mock_b.exit_called) - self.assertEqual(mock_b.exit_args, None) - - def testNestedExceptionAfterInnerStatement(self): - mock_a = mock_contextmanager_generator() - mock_b = mock_contextmanager_generator() - def shouldThrow(): - with mock_a as self.foo: - with mock_b as self.bar: - self.assertInWithManagerInvariants(mock_a) - self.assertInWithManagerInvariants(mock_b) - self.assertInWithGeneratorInvariants(self.foo) - self.assertInWithGeneratorInvariants(self.bar) - self.raiseTestException() - self.assertRaises(RuntimeError, shouldThrow) - self.assertAfterWithManagerInvariantsWithError(mock_a) - self.assertAfterWithManagerInvariantsNoError(mock_b) - self.assertAfterWithGeneratorInvariantsWithError(self.foo) - self.assertAfterWithGeneratorInvariantsNoError(self.bar) - - -class NonLocalFlowControlTestCase(unittest.TestCase): - - def testWithBreak(self): - counter = 0 - while True: - counter += 1 - with mock_contextmanager_generator(): - counter += 10 - break - counter += 100 # Not reached - self.assertEqual(counter, 11) - - def testWithContinue(self): - counter = 0 - while True: - counter += 1 - if counter > 2: - break - with mock_contextmanager_generator(): - counter += 10 - continue - counter += 100 # Not reached - self.assertEqual(counter, 12) - - def testWithReturn(self): - def foo(): - counter = 0 - while True: - counter += 1 - with mock_contextmanager_generator(): - counter += 10 - return counter - counter += 100 # Not reached - self.assertEqual(foo(), 11) - - def testWithYield(self): - def gen(): - with mock_contextmanager_generator(): - yield 12 - yield 13 - x = list(gen()) - self.assertEqual(x, [12, 13]) - - def testWithRaise(self): - counter = 0 - try: - counter += 1 - with mock_contextmanager_generator(): - counter += 10 - raise RuntimeError - counter += 100 # Not reached - except RuntimeError: - self.assertEqual(counter, 11) - else: - self.fail("Didn't raise RuntimeError") - - -class AssignmentTargetTestCase(unittest.TestCase): - - def testSingleComplexTarget(self): - targets = {1: [0, 1, 2]} - with mock_contextmanager_generator() as targets[1][0]: - self.assertEqual(targets.keys(), [1]) - self.assertEqual(targets[1][0].__class__, MockResource) - with mock_contextmanager_generator() as targets.values()[0][1]: - self.assertEqual(targets.keys(), [1]) - self.assertEqual(targets[1][1].__class__, MockResource) - with mock_contextmanager_generator() as targets[2]: - keys = targets.keys() - keys.sort() - self.assertEqual(keys, [1, 2]) - class C: pass - blah = C() - with mock_contextmanager_generator() as blah.foo: - self.assertEqual(hasattr(blah, "foo"), True) - - def testMultipleComplexTargets(self): - class C: - def __context__(self): return self - def __enter__(self): return 1, 2, 3 - def __exit__(self, *a): pass - targets = {1: [0, 1, 2]} - with C() as (targets[1][0], targets[1][1], targets[1][2]): - self.assertEqual(targets, {1: [1, 2, 3]}) - with C() as (targets.values()[0][2], targets.values()[0][1], targets.values()[0][0]): - self.assertEqual(targets, {1: [3, 2, 1]}) - with C() as (targets[1], targets[2], targets[3]): - self.assertEqual(targets, {1: 1, 2: 2, 3: 3}) - class B: pass - blah = B() - with C() as (blah.one, blah.two, blah.three): - self.assertEqual(blah.one, 1) - self.assertEqual(blah.two, 2) - self.assertEqual(blah.three, 3) - - -def test_main(): - run_unittest(FailureTestCase, NonexceptionalTestCase, - NestedNonexceptionalTestCase, ExceptionalTestCase, - NonLocalFlowControlTestCase, - AssignmentTargetTestCase) - - -if __name__ == '__main__': - test_main() +#!/usr/bin/env python + +"""Unit tests for the with statement specified in PEP 343.""" + +__author__ = "Mike Bland" +__email__ = "mbland at acm dot org" + +import unittest +from test.contextmanager import GeneratorContextManager +from test.nested import nested +from test.test_support import run_unittest + + +class MockContextManager(GeneratorContextManager): + def __init__(self, gen): + GeneratorContextManager.__init__(self, gen) + self.context_called = False + self.enter_called = False + self.exit_called = False + self.exit_args = None + + def __context__(self): + self.context_called = True + return GeneratorContextManager.__context__(self) + + def __enter__(self): + self.enter_called = True + return GeneratorContextManager.__enter__(self) + + def __exit__(self, type, value, traceback): + self.exit_called = True + self.exit_args = (type, value, traceback) + return GeneratorContextManager.__exit__(self, type, value, traceback) + + +def mock_contextmanager(func): + def helper(*args, **kwds): + return MockContextManager(func(*args, **kwds)) + return helper + + +class MockResource(object): + def __init__(self): + self.yielded = False + self.stopped = False + + +@mock_contextmanager +def mock_contextmanager_generator(): + mock = MockResource() + try: + mock.yielded = True + yield mock + finally: + mock.stopped = True + + +class MockNested(nested): + def __init__(self, *contexts): + nested.__init__(self, *contexts) + self.context_called = False + self.enter_called = False + self.exit_called = False + self.exit_args = None + + def __context__(self): + self.context_called = True + return nested.__context__(self) + + def __enter__(self): + self.enter_called = True + return nested.__enter__(self) + + def __exit__(self, *exc_info): + self.exit_called = True + self.exit_args = exc_info + return nested.__exit__(self, *exc_info) + + +class FailureTestCase(unittest.TestCase): + def testNameError(self): + def fooNotDeclared(): + with foo: pass + self.assertRaises(NameError, fooNotDeclared) + + def testContextAttributeError(self): + class LacksContext(object): + def __enter__(self): + pass + + def __exit__(self, type, value, traceback): + pass + + def fooLacksContext(): + foo = LacksContext() + with foo: pass + self.assertRaises(AttributeError, fooLacksContext) + + def testEnterAttributeError(self): + class LacksEnter(object): + def __context__(self): + pass + + def __exit__(self, type, value, traceback): + pass + + def fooLacksEnter(): + foo = LacksEnter() + with foo: pass + self.assertRaises(AttributeError, fooLacksEnter) + + def testExitAttributeError(self): + class LacksExit(object): + def __context__(self): + pass + + def __enter__(self): + pass + + def fooLacksExit(): + foo = LacksExit() + with foo: pass + self.assertRaises(AttributeError, fooLacksExit) + + def assertRaisesSyntaxError(self, codestr): + def shouldRaiseSyntaxError(s): + compile(s, '', 'single') + self.assertRaises(SyntaxError, shouldRaiseSyntaxError, codestr) + + def testAssignmentToNoneError(self): + self.assertRaisesSyntaxError('with mock as None:\n pass') + self.assertRaisesSyntaxError( + 'with mock as (None):\n' + ' pass') + + def testAssignmentToEmptyTupleError(self): + self.assertRaisesSyntaxError( + 'with mock as ():\n' + ' pass') + + def testAssignmentToTupleOnlyContainingNoneError(self): + self.assertRaisesSyntaxError('with mock as None,:\n pass') + self.assertRaisesSyntaxError( + 'with mock as (None,):\n' + ' pass') + + def testAssignmentToTupleContainingNoneError(self): + self.assertRaisesSyntaxError( + 'with mock as (foo, None, bar):\n' + ' pass') + + def testContextThrows(self): + class ContextThrows(object): + def __context__(self): + raise RuntimeError("Context threw") + + def shouldThrow(): + ct = ContextThrows() + self.foo = None + with ct as self.foo: + pass + self.assertRaises(RuntimeError, shouldThrow) + self.assertEqual(self.foo, None) + + def testEnterThrows(self): + class EnterThrows(object): + def __context__(self): + return self + + def __enter__(self): + raise RuntimeError("Context threw") + + def __exit__(self, *args): + pass + + def shouldThrow(): + ct = EnterThrows() + self.foo = None + with ct as self.foo: + pass + self.assertRaises(RuntimeError, shouldThrow) + self.assertEqual(self.foo, None) + + def testExitThrows(self): + class ExitThrows(object): + def __context__(self): + return self + def __enter__(self): + return + def __exit__(self, *args): + raise RuntimeError(42) + def shouldThrow(): + with ExitThrows(): + pass + self.assertRaises(RuntimeError, shouldThrow) + +class ContextmanagerAssertionMixin(object): + TEST_EXCEPTION = RuntimeError("test exception") + + def assertInWithManagerInvariants(self, mock_manager): + self.assertTrue(mock_manager.context_called) + self.assertTrue(mock_manager.enter_called) + self.assertFalse(mock_manager.exit_called) + self.assertEqual(mock_manager.exit_args, None) + + def assertAfterWithManagerInvariants(self, mock_manager, exit_args): + self.assertTrue(mock_manager.context_called) + self.assertTrue(mock_manager.enter_called) + self.assertTrue(mock_manager.exit_called) + self.assertEqual(mock_manager.exit_args, exit_args) + + def assertAfterWithManagerInvariantsNoError(self, mock_manager): + self.assertAfterWithManagerInvariants(mock_manager, + (None, None, None)) + + def assertInWithGeneratorInvariants(self, mock_generator): + self.assertTrue(mock_generator.yielded) + self.assertFalse(mock_generator.stopped) + + def assertAfterWithGeneratorInvariantsNoError(self, mock_generator): + self.assertTrue(mock_generator.yielded) + self.assertTrue(mock_generator.stopped) + + def raiseTestException(self): + raise self.TEST_EXCEPTION + + def assertAfterWithManagerInvariantsWithError(self, mock_manager): + self.assertTrue(mock_manager.context_called) + self.assertTrue(mock_manager.enter_called) + self.assertTrue(mock_manager.exit_called) + self.assertEqual(mock_manager.exit_args[0], RuntimeError) + self.assertEqual(mock_manager.exit_args[1], self.TEST_EXCEPTION) + + def assertAfterWithGeneratorInvariantsWithError(self, mock_generator): + self.assertTrue(mock_generator.yielded) + self.assertTrue(mock_generator.stopped) + + +class NonexceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin): + def testInlineGeneratorSyntax(self): + with mock_contextmanager_generator(): + pass + + def testUnboundGenerator(self): + mock = mock_contextmanager_generator() + with mock: + pass + self.assertAfterWithManagerInvariantsNoError(mock) + + def testInlineGeneratorBoundSyntax(self): + with mock_contextmanager_generator() as foo: + self.assertInWithGeneratorInvariants(foo) + # FIXME: In the future, we'll try to keep the bound names from leaking + self.assertAfterWithGeneratorInvariantsNoError(foo) + + def testInlineGeneratorBoundToExistingVariable(self): + foo = None + with mock_contextmanager_generator() as foo: + self.assertInWithGeneratorInvariants(foo) + self.assertAfterWithGeneratorInvariantsNoError(foo) + + def testInlineGeneratorBoundToDottedVariable(self): + with mock_contextmanager_generator() as self.foo: + self.assertInWithGeneratorInvariants(self.foo) + self.assertAfterWithGeneratorInvariantsNoError(self.foo) + + def testBoundGenerator(self): + mock = mock_contextmanager_generator() + with mock as foo: + self.assertInWithGeneratorInvariants(foo) + self.assertInWithManagerInvariants(mock) + self.assertAfterWithGeneratorInvariantsNoError(foo) + self.assertAfterWithManagerInvariantsNoError(mock) + + def testNestedSingleStatements(self): + mock_a = mock_contextmanager_generator() + with mock_a as foo: + mock_b = mock_contextmanager_generator() + with mock_b as bar: + self.assertInWithManagerInvariants(mock_a) + self.assertInWithManagerInvariants(mock_b) + self.assertInWithGeneratorInvariants(foo) + self.assertInWithGeneratorInvariants(bar) + self.assertAfterWithManagerInvariantsNoError(mock_b) + self.assertAfterWithGeneratorInvariantsNoError(bar) + self.assertInWithManagerInvariants(mock_a) + self.assertInWithGeneratorInvariants(foo) + self.assertAfterWithManagerInvariantsNoError(mock_a) + self.assertAfterWithGeneratorInvariantsNoError(foo) + + +class NestedNonexceptionalTestCase(unittest.TestCase, + ContextmanagerAssertionMixin): + def testSingleArgInlineGeneratorSyntax(self): + with nested(mock_contextmanager_generator()): + pass + + def testSingleArgUnbound(self): + mock_contextmanager = mock_contextmanager_generator() + mock_nested = MockNested(mock_contextmanager) + with mock_nested: + self.assertInWithManagerInvariants(mock_contextmanager) + self.assertInWithManagerInvariants(mock_nested) + self.assertAfterWithManagerInvariantsNoError(mock_contextmanager) + self.assertAfterWithManagerInvariantsNoError(mock_nested) + + def testSingleArgBoundToNonTuple(self): + m = mock_contextmanager_generator() + # This will bind all the arguments to nested() into a single list + # assigned to foo. + with nested(m) as foo: + self.assertInWithManagerInvariants(m) + self.assertAfterWithManagerInvariantsNoError(m) + + def testSingleArgBoundToSingleElementParenthesizedList(self): + m = mock_contextmanager_generator() + # This will bind all the arguments to nested() into a single list + # assigned to foo. + # FIXME: what should this do: with nested(m) as (foo,): + with nested(m) as (foo): + self.assertInWithManagerInvariants(m) + self.assertAfterWithManagerInvariantsNoError(m) + + def testSingleArgBoundToMultipleElementTupleError(self): + def shouldThrowValueError(): + with nested(mock_contextmanager_generator()) as (foo, bar): + pass + self.assertRaises(ValueError, shouldThrowValueError) + + def testSingleArgUnbound(self): + mock_contextmanager = mock_contextmanager_generator() + mock_nested = MockNested(mock_contextmanager) + with mock_nested: + self.assertInWithManagerInvariants(mock_contextmanager) + self.assertInWithManagerInvariants(mock_nested) + self.assertAfterWithManagerInvariantsNoError(mock_contextmanager) + self.assertAfterWithManagerInvariantsNoError(mock_nested) + + def testMultipleArgUnbound(self): + m = mock_contextmanager_generator() + n = mock_contextmanager_generator() + o = mock_contextmanager_generator() + mock_nested = MockNested(m, n, o) + with mock_nested: + self.assertInWithManagerInvariants(m) + self.assertInWithManagerInvariants(n) + self.assertInWithManagerInvariants(o) + self.assertInWithManagerInvariants(mock_nested) + self.assertAfterWithManagerInvariantsNoError(m) + self.assertAfterWithManagerInvariantsNoError(n) + self.assertAfterWithManagerInvariantsNoError(o) + self.assertAfterWithManagerInvariantsNoError(mock_nested) + + def testMultipleArgBound(self): + mock_nested = MockNested(mock_contextmanager_generator(), + mock_contextmanager_generator(), mock_contextmanager_generator()) + with mock_nested as (m, n, o): + self.assertInWithGeneratorInvariants(m) + self.assertInWithGeneratorInvariants(n) + self.assertInWithGeneratorInvariants(o) + self.assertInWithManagerInvariants(mock_nested) + self.assertAfterWithGeneratorInvariantsNoError(m) + self.assertAfterWithGeneratorInvariantsNoError(n) + self.assertAfterWithGeneratorInvariantsNoError(o) + self.assertAfterWithManagerInvariantsNoError(mock_nested) + + +class ExceptionalTestCase(unittest.TestCase, ContextmanagerAssertionMixin): + def testSingleResource(self): + cm = mock_contextmanager_generator() + def shouldThrow(): + with cm as self.resource: + self.assertInWithManagerInvariants(cm) + self.assertInWithGeneratorInvariants(self.resource) + self.raiseTestException() + self.assertRaises(RuntimeError, shouldThrow) + self.assertAfterWithManagerInvariantsWithError(cm) + self.assertAfterWithGeneratorInvariantsWithError(self.resource) + + def testNestedSingleStatements(self): + mock_a = mock_contextmanager_generator() + mock_b = mock_contextmanager_generator() + def shouldThrow(): + with mock_a as self.foo: + with mock_b as self.bar: + self.assertInWithManagerInvariants(mock_a) + self.assertInWithManagerInvariants(mock_b) + self.assertInWithGeneratorInvariants(self.foo) + self.assertInWithGeneratorInvariants(self.bar) + self.raiseTestException() + self.assertRaises(RuntimeError, shouldThrow) + self.assertAfterWithManagerInvariantsWithError(mock_a) + self.assertAfterWithManagerInvariantsWithError(mock_b) + self.assertAfterWithGeneratorInvariantsWithError(self.foo) + self.assertAfterWithGeneratorInvariantsWithError(self.bar) + + def testMultipleResourcesInSingleStatement(self): + cm_a = mock_contextmanager_generator() + cm_b = mock_contextmanager_generator() + mock_nested = MockNested(cm_a, cm_b) + def shouldThrow(): + with mock_nested as (self.resource_a, self.resource_b): + self.assertInWithManagerInvariants(cm_a) + self.assertInWithManagerInvariants(cm_b) + self.assertInWithManagerInvariants(mock_nested) + self.assertInWithGeneratorInvariants(self.resource_a) + self.assertInWithGeneratorInvariants(self.resource_b) + self.raiseTestException() + self.assertRaises(RuntimeError, shouldThrow) + self.assertAfterWithManagerInvariantsWithError(cm_a) + self.assertAfterWithManagerInvariantsWithError(cm_b) + self.assertAfterWithManagerInvariantsWithError(mock_nested) + self.assertAfterWithGeneratorInvariantsWithError(self.resource_a) + self.assertAfterWithGeneratorInvariantsWithError(self.resource_b) + + def testNestedExceptionBeforeInnerStatement(self): + mock_a = mock_contextmanager_generator() + mock_b = mock_contextmanager_generator() + self.bar = None + def shouldThrow(): + with mock_a as self.foo: + self.assertInWithManagerInvariants(mock_a) + self.assertInWithGeneratorInvariants(self.foo) + self.raiseTestException() + with mock_b as self.bar: + pass + self.assertRaises(RuntimeError, shouldThrow) + self.assertAfterWithManagerInvariantsWithError(mock_a) + self.assertAfterWithGeneratorInvariantsWithError(self.foo) + + # The inner statement stuff should never have been touched + self.assertEqual(self.bar, None) + self.assertFalse(mock_b.context_called) + self.assertFalse(mock_b.enter_called) + self.assertFalse(mock_b.exit_called) + self.assertEqual(mock_b.exit_args, None) + + def testNestedExceptionAfterInnerStatement(self): + mock_a = mock_contextmanager_generator() + mock_b = mock_contextmanager_generator() + def shouldThrow(): + with mock_a as self.foo: + with mock_b as self.bar: + self.assertInWithManagerInvariants(mock_a) + self.assertInWithManagerInvariants(mock_b) + self.assertInWithGeneratorInvariants(self.foo) + self.assertInWithGeneratorInvariants(self.bar) + self.raiseTestException() + self.assertRaises(RuntimeError, shouldThrow) + self.assertAfterWithManagerInvariantsWithError(mock_a) + self.assertAfterWithManagerInvariantsNoError(mock_b) + self.assertAfterWithGeneratorInvariantsWithError(self.foo) + self.assertAfterWithGeneratorInvariantsNoError(self.bar) + + +class NonLocalFlowControlTestCase(unittest.TestCase): + + def testWithBreak(self): + counter = 0 + while True: + counter += 1 + with mock_contextmanager_generator(): + counter += 10 + break + counter += 100 # Not reached + self.assertEqual(counter, 11) + + def testWithContinue(self): + counter = 0 + while True: + counter += 1 + if counter > 2: + break + with mock_contextmanager_generator(): + counter += 10 + continue + counter += 100 # Not reached + self.assertEqual(counter, 12) + + def testWithReturn(self): + def foo(): + counter = 0 + while True: + counter += 1 + with mock_contextmanager_generator(): + counter += 10 + return counter + counter += 100 # Not reached + self.assertEqual(foo(), 11) + + def testWithYield(self): + def gen(): + with mock_contextmanager_generator(): + yield 12 + yield 13 + x = list(gen()) + self.assertEqual(x, [12, 13]) + + def testWithRaise(self): + counter = 0 + try: + counter += 1 + with mock_contextmanager_generator(): + counter += 10 + raise RuntimeError + counter += 100 # Not reached + except RuntimeError: + self.assertEqual(counter, 11) + else: + self.fail("Didn't raise RuntimeError") + + +class AssignmentTargetTestCase(unittest.TestCase): + + def testSingleComplexTarget(self): + targets = {1: [0, 1, 2]} + with mock_contextmanager_generator() as targets[1][0]: + self.assertEqual(targets.keys(), [1]) + self.assertEqual(targets[1][0].__class__, MockResource) + with mock_contextmanager_generator() as targets.values()[0][1]: + self.assertEqual(targets.keys(), [1]) + self.assertEqual(targets[1][1].__class__, MockResource) + with mock_contextmanager_generator() as targets[2]: + keys = targets.keys() + keys.sort() + self.assertEqual(keys, [1, 2]) + class C: pass + blah = C() + with mock_contextmanager_generator() as blah.foo: + self.assertEqual(hasattr(blah, "foo"), True) + + def testMultipleComplexTargets(self): + class C: + def __context__(self): return self + def __enter__(self): return 1, 2, 3 + def __exit__(self, *a): pass + targets = {1: [0, 1, 2]} + with C() as (targets[1][0], targets[1][1], targets[1][2]): + self.assertEqual(targets, {1: [1, 2, 3]}) + with C() as (targets.values()[0][2], targets.values()[0][1], targets.values()[0][0]): + self.assertEqual(targets, {1: [3, 2, 1]}) + with C() as (targets[1], targets[2], targets[3]): + self.assertEqual(targets, {1: 1, 2: 2, 3: 3}) + class B: pass + blah = B() + with C() as (blah.one, blah.two, blah.three): + self.assertEqual(blah.one, 1) + self.assertEqual(blah.two, 2) + self.assertEqual(blah.three, 3) + + +def test_main(): + run_unittest(FailureTestCase, NonexceptionalTestCase, + NestedNonexceptionalTestCase, ExceptionalTestCase, + NonLocalFlowControlTestCase, + AssignmentTargetTestCase) + + +if __name__ == '__main__': + test_main() diff --git a/Parser/asdl.py b/Parser/asdl.py index 2128732cfba..3a693088f20 100644 --- a/Parser/asdl.py +++ b/Parser/asdl.py @@ -38,7 +38,7 @@ class Id(Token): def __str__(self): return self.value - + class String(Token): def __init__(self, value, lineno): self.type = 'String' @@ -71,7 +71,7 @@ class ASDLScanner(spark.GenericScanner, object): # XXX doesn't distinguish upper vs. lower, which is # significant for ASDL. self.rv.append(Id(s, self.lineno)) - + def t_string(self, s): r'"[^"]*"' self.rv.append(String(s, self.lineno)) @@ -123,7 +123,7 @@ class ASDLParser(spark.GenericParser, object): raise ASDLSyntaxError(module.lineno, msg="expected 'module', found %s" % module) return Module(name, definitions, version) - + def p_version(self, (version, V)): "version ::= Id String" if version.value != "version": diff --git a/Parser/asdl_c.py b/Parser/asdl_c.py index 1f63df9f80f..ff091dd229c 100755 --- a/Parser/asdl_c.py +++ b/Parser/asdl_c.py @@ -354,7 +354,7 @@ class PyTypesDeclareVisitor(PickleVisitor): for f in prod.fields: self.emit('"%s",' % f.name, 1) self.emit("};", 0) - + def visitSum(self, sum, name): self.emit("PyTypeObject *%s_type;" % name, 0) if sum.attributes: @@ -373,7 +373,7 @@ class PyTypesDeclareVisitor(PickleVisitor): self.emit("static PyObject* ast2obj_%s(%s);" % (name, ptype), 0) for t in sum.types: self.visitConstructor(t, name) - + def visitConstructor(self, cons, name): self.emit("PyTypeObject *%s_type;" % cons.name, 0) if cons.fields: @@ -405,7 +405,7 @@ static PyTypeObject* make_type(char *type, PyTypeObject* base, char**fields, int } PyTuple_SET_ITEM(fnames, i, field); } - result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){sOss}", + result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){sOss}", type, base, "_fields", fnames, "__module__", "_ast"); Py_DECREF(fnames); return (PyTypeObject*)result; @@ -481,35 +481,35 @@ static PyObject* ast2obj_int(bool b) fields = name.value+"_fields" else: fields = "NULL" - self.emit('%s_type = make_type("%s", AST_type, %s, %d);' % + self.emit('%s_type = make_type("%s", AST_type, %s, %d);' % (name, name, fields, len(prod.fields)), 1) self.emit("if (!%s_type) return 0;" % name, 1) - + def visitSum(self, sum, name): self.emit('%s_type = make_type("%s", AST_type, NULL, 0);' % (name, name), 1) self.emit("if (!%s_type) return 0;" % name, 1) if sum.attributes: - self.emit("if (!add_attributes(%s_type, %s_attributes, %d)) return 0;" % + self.emit("if (!add_attributes(%s_type, %s_attributes, %d)) return 0;" % (name, name, len(sum.attributes)), 1) else: self.emit("if (!add_attributes(%s_type, NULL, 0)) return 0;" % name, 1) simple = is_simple(sum) for t in sum.types: self.visitConstructor(t, name, simple) - + def visitConstructor(self, cons, name, simple): if cons.fields: fields = cons.name.value+"_fields" else: fields = "NULL" - self.emit('%s_type = make_type("%s", %s_type, %s, %d);' % + self.emit('%s_type = make_type("%s", %s_type, %s, %d);' % (cons.name, cons.name, name, fields, len(cons.fields)), 1) self.emit("if (!%s_type) return 0;" % cons.name, 1) if simple: self.emit("%s_singleton = PyType_GenericNew(%s_type, NULL, NULL);" % (cons.name, cons.name), 1) self.emit("if (!%s_singleton) return 0;" % cons.name, 1) - + class ASTModuleVisitor(PickleVisitor): def visitModule(self, mod): @@ -533,15 +533,15 @@ class ASTModuleVisitor(PickleVisitor): def visitProduct(self, prod, name): self.addObj(name) - + def visitSum(self, sum, name): self.addObj(name) for t in sum.types: self.visitConstructor(t, name) - + def visitConstructor(self, cons, name): self.addObj(cons.name) - + def addObj(self, name): self.emit('if(PyDict_SetItemString(d, "%s", (PyObject*)%s_type) < 0) return;' % (name, name), 1) @@ -609,7 +609,7 @@ class ObjVisitor(PickleVisitor): self.emit("if (!value) goto failed;", 1) self.emit('PyObject_SetAttrString(result, "%s", value);' % a.name, 1) self.func_end() - + def simpleSum(self, sum, name): self.emit("PyObject* ast2obj_%s(%s_ty o)" % (name, name), 0) self.emit("{", 0)