Jiwon Seo's PEP 3102 implementation.

See SF#1549670.
The compiler package has not yet been updated.
This commit is contained in:
Guido van Rossum 2006-10-27 23:31:49 +00:00
parent fc2a0a8e3c
commit 4f72a78684
31 changed files with 739 additions and 227 deletions

View file

@ -487,11 +487,12 @@ class From(Node):
return "From(%s, %s, %s)" % (repr(self.modname), repr(self.names), repr(self.level))
class Function(Node):
def __init__(self, decorators, name, argnames, defaults, flags, doc, code, lineno=None):
def __init__(self, decorators, name, argnames, defaults, kwonlyargs, flags, doc, code, lineno=None):
self.decorators = decorators
self.name = name
self.argnames = argnames
self.defaults = defaults
self.kwonlyargs = kwonlyargs
self.flags = flags
self.doc = doc
self.code = code
@ -509,6 +510,7 @@ class Function(Node):
children.append(self.name)
children.append(self.argnames)
children.extend(flatten(self.defaults))
children.append(self.kwonlyargs)
children.append(self.flags)
children.append(self.doc)
children.append(self.code)
@ -523,7 +525,7 @@ class Function(Node):
return tuple(nodelist)
def __repr__(self):
return "Function(%s, %s, %s, %s, %s, %s, %s)" % (repr(self.decorators), repr(self.name), repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.doc), repr(self.code))
return "Function(%s, %s, %s, %s, %s, %s, %s, %s)" % (repr(self.decorators), repr(self.name), repr(self.argnames), repr(self.defaults), repr(self.kwonlyargs), repr(self.flags), repr(self.doc), repr(self.code))
class GenExpr(Node):
def __init__(self, code, lineno=None):
@ -531,6 +533,7 @@ class GenExpr(Node):
self.lineno = lineno
self.argnames = ['.0']
self.varargs = self.kwargs = None
self.kwonlyargs = ()
def getChildren(self):
@ -713,9 +716,10 @@ class Keyword(Node):
return "Keyword(%s, %s)" % (repr(self.name), repr(self.expr))
class Lambda(Node):
def __init__(self, argnames, defaults, flags, code, lineno=None):
def __init__(self, argnames, defaults, kwonlyargs, flags, code, lineno=None):
self.argnames = argnames
self.defaults = defaults
self.kwonlyargs = kwonlyargs
self.flags = flags
self.code = code
self.lineno = lineno
@ -730,6 +734,7 @@ class Lambda(Node):
children = []
children.append(self.argnames)
children.extend(flatten(self.defaults))
children.append(self.kwonlyargs)
children.append(self.flags)
children.append(self.code)
return tuple(children)
@ -741,7 +746,7 @@ class Lambda(Node):
return tuple(nodelist)
def __repr__(self):
return "Lambda(%s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.flags), repr(self.code))
return "Lambda(%s, %s, %s, %s, %s)" % (repr(self.argnames), repr(self.defaults), repr(self.kwonlyargs), repr(self.flags), repr(self.code))
class LeftShift(Node):
def __init__(self, (left, right), lineno=None):

View file

@ -313,13 +313,15 @@ DONE = "DONE"
class PyFlowGraph(FlowGraph):
super_init = FlowGraph.__init__
def __init__(self, name, filename, args=(), optimized=0, klass=None):
def __init__(self, name, filename,
args=(), kwonlyargs={}, optimized=0, klass=None):
self.super_init()
self.name = name
self.filename = filename
self.docstring = None
self.args = args # XXX
self.argcount = getArgCount(args)
self.kwonlyargs = kwonlyargs
self.klass = klass
if optimized:
self.flags = CO_OPTIMIZED | CO_NEWLOCALS
@ -595,7 +597,9 @@ class PyFlowGraph(FlowGraph):
argcount = self.argcount
if self.flags & CO_VARKEYWORDS:
argcount = argcount - 1
return new.code(argcount, nlocals, self.stacksize, self.flags,
kwonlyargcount = len(self.kwonlyargs)
return new.code(argcount, kwonlyargcount,
nlocals, self.stacksize, self.flags,
self.lnotab.getCode(), self.getConsts(),
tuple(self.names), tuple(self.varnames),
self.filename, self.name, self.lnotab.firstline,
@ -804,7 +808,8 @@ class StackDepthTracker:
def CALL_FUNCTION_VAR_KW(self, argc):
return self.CALL_FUNCTION(argc)-2
def MAKE_FUNCTION(self, argc):
return -argc
hi, lo = divmod(argc, 256)
return -(lo + hi * 2)
def MAKE_CLOSURE(self, argc):
# XXX need to account for free variables too!
return -argc

View file

@ -378,6 +378,12 @@ class CodeGenerator:
walk(node.code, gen)
gen.finish()
self.set_lineno(node)
for keyword in node.kwonlyargs:
default = keyword.expr
if isinstance(default, ast.EmptyNode):
continue
self.emit('LOAD_CONST', keyword.name)
self.visit(default)
for default in node.defaults:
self.visit(default)
self._makeClosure(gen, len(node.defaults))
@ -1320,7 +1326,9 @@ class AbstractFunctionCode:
name = func.name
args, hasTupleArg = generateArgList(func.argnames)
kwonlyargs = generateKwonlyArgList(func.kwonlyargs)
self.graph = pyassem.PyFlowGraph(name, func.filename, args,
kwonlyargs=kwonlyargs,
optimized=1)
self.isLambda = isLambda
self.super_init()
@ -1456,6 +1464,13 @@ def generateArgList(arglist):
raise ValueError, "unexpect argument type:", elt
return args + extra, count
def generateKwonlyArgList(keywordOnlyArgs):
kwonlyargs = {}
for elt in keywordOnlyArgs:
assert isinstance(elt, ast.Keyword)
kwonlyargs[elt.name] = elt.expr
return kwonlyargs
def findOp(node):
"""Find the op (DELETE, LOAD, STORE) in an AssTuple tree"""
v = OpFinder()

View file

@ -250,9 +250,9 @@ class Transformer:
args = nodelist[-3][2]
if args[0] == symbol.varargslist:
names, defaults, flags = self.com_arglist(args[1:])
names, defaults, kwonlyargs, flags = self.com_arglist(args[1:])
else:
names = defaults = ()
names = defaults = kwonlyargs = ()
flags = 0
doc = self.get_docstring(nodelist[-1])
@ -263,21 +263,23 @@ class Transformer:
assert isinstance(code, Stmt)
assert isinstance(code.nodes[0], Discard)
del code.nodes[0]
return Function(decorators, name, names, defaults, flags, doc, code,
lineno=lineno)
return Function(decorators, name, names, defaults,
kwonlyargs, flags, doc, code, lineno=lineno)
def lambdef(self, nodelist):
# lambdef: 'lambda' [varargslist] ':' test
if nodelist[2][0] == symbol.varargslist:
names, defaults, flags = self.com_arglist(nodelist[2][1:])
names, defaults, kwonlyargs, flags = \
self.com_arglist(nodelist[2][1:])
else:
names = defaults = ()
names = defaults = kwonlyargs = ()
flags = 0
# code for lambda
code = self.com_node(nodelist[-1])
return Lambda(names, defaults, flags, code, lineno=nodelist[1][2])
return Lambda(names, defaults, kwonlyargs,
flags, code, lineno=nodelist[1][2])
old_lambdef = lambdef
def classdef(self, nodelist):
@ -783,13 +785,37 @@ class Transformer:
# ('const', xxxx)) Nodes)
return Discard(Const(None))
def keywordonlyargs(self, nodelist):
# (',' NAME ['=' test])*
# ^^^
# ------+
kwonlyargs = []
i = 0
while i < len(nodelist):
default = EmptyNode()
node = nodelist[i]
#assert node[0] == token.COMMA
#node = nodelist[i+1]
if i+1 < len(nodelist) and nodelist[i+1][0] == token.EQUAL:
assert i+2 < len(nodelist)
default = self.com_node(nodelist[i+2])
i += 2
if node[0] == token.DOUBLESTAR:
return kwonlyargs, i
elif node[0] == token.NAME:
kwonlyargs.append(Keyword(node[1], default, lineno=node[2]))
i += 2
return kwonlyargs, i
def com_arglist(self, nodelist):
# varargslist:
# (fpdef ['=' test] ',')* ('*' NAME [',' '**' NAME] | '**' NAME)
# | fpdef ['=' test] (',' fpdef ['=' test])* [',']
# (fpdef ['=' test] ',')*
# ('*' [NAME] (',' NAME '=' test)* [',' '**' NAME] | '**' NAME)
# | fpdef ['=' test] (',' fpdef ['=' test])* [',']
# fpdef: NAME | '(' fplist ')'
# fplist: fpdef (',' fpdef)* [',']
names = []
kwonlyargs = []
defaults = []
flags = 0
@ -799,10 +825,22 @@ class Transformer:
if node[0] == token.STAR or node[0] == token.DOUBLESTAR:
if node[0] == token.STAR:
node = nodelist[i+1]
if node[0] == token.NAME:
if node[0] == token.NAME: # vararg
names.append(node[1])
flags = flags | CO_VARARGS
i = i + 3
else: # no vararg
assert node[0] == token.COMMA
i += 1
#elif node[0] == token.COMMA:
# i += 1
# kwonlyargs, skip = self.keywordonlyargs(nodelist[i:])
# i += skip
if nodelist[i][0] == token.NAME:
kwonlyargs, skip = self.keywordonlyargs(nodelist[i:])
i += skip
print "kwonlyargs:", kwonlyargs
if i < len(nodelist):
# should be DOUBLESTAR
@ -831,7 +869,8 @@ class Transformer:
# skip the comma
i = i + 1
return names, defaults, flags
print "names:", names, "defaults:", defaults, "kwonlyargs:", kwonlyargs, "flags:", flags
return names, defaults, kwonlyargs, flags
def com_fpdef(self, node):
# fpdef: NAME | '(' fplist ')'

View file

@ -9,9 +9,9 @@ test_extcall
(1, 2, 3) {'a': 4, 'b': 5}
(1, 2, 3, 4, 5) {'a': 6, 'b': 7}
(1, 2, 3, 6, 7) {'a': 8, 'b': 9, 'x': 4, 'y': 5}
TypeError: g() takes at least 1 argument (0 given)
TypeError: g() takes at least 1 argument (0 given)
TypeError: g() takes at least 1 argument (0 given)
TypeError: g() takes at least 1 positional argument (0 given)
TypeError: g() takes at least 1 positional argument (0 given)
TypeError: g() takes at least 1 positional argument (0 given)
1 () {}
1 (2,) {}
1 (2, 3) {}
@ -35,24 +35,24 @@ dir() got multiple values for keyword argument 'b'
3 512 True
3
3
za () {} -> za() takes exactly 1 argument (0 given)
za () {} -> za() takes exactly 1 positional argument (0 given)
za () {'a': 'aa'} -> ok za aa B D E V a
za () {'d': 'dd'} -> za() got an unexpected keyword argument 'd'
za () {'a': 'aa', 'd': 'dd'} -> za() got an unexpected keyword argument 'd'
za () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> za() got an unexpected keyword argument 'b'
za (1, 2) {} -> za() takes exactly 1 argument (2 given)
za (1, 2) {'a': 'aa'} -> za() takes exactly 1 non-keyword argument (2 given)
za (1, 2) {'d': 'dd'} -> za() takes exactly 1 non-keyword argument (2 given)
za (1, 2) {'a': 'aa', 'd': 'dd'} -> za() takes exactly 1 non-keyword argument (2 given)
za (1, 2) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> za() takes exactly 1 non-keyword argument (2 given)
za (1, 2, 3, 4, 5) {} -> za() takes exactly 1 argument (5 given)
za (1, 2, 3, 4, 5) {'a': 'aa'} -> za() takes exactly 1 non-keyword argument (5 given)
za (1, 2, 3, 4, 5) {'d': 'dd'} -> za() takes exactly 1 non-keyword argument (5 given)
za (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> za() takes exactly 1 non-keyword argument (5 given)
za (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> za() takes exactly 1 non-keyword argument (5 given)
zade () {} -> zade() takes at least 1 argument (0 given)
za (1, 2) {} -> za() takes exactly 1 positional argument (2 given)
za (1, 2) {'a': 'aa'} -> za() takes exactly 1 non-keyword positional argument (2 given)
za (1, 2) {'d': 'dd'} -> za() takes exactly 1 non-keyword positional argument (2 given)
za (1, 2) {'a': 'aa', 'd': 'dd'} -> za() takes exactly 1 non-keyword positional argument (2 given)
za (1, 2) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> za() takes exactly 1 non-keyword positional argument (2 given)
za (1, 2, 3, 4, 5) {} -> za() takes exactly 1 positional argument (5 given)
za (1, 2, 3, 4, 5) {'a': 'aa'} -> za() takes exactly 1 non-keyword positional argument (5 given)
za (1, 2, 3, 4, 5) {'d': 'dd'} -> za() takes exactly 1 non-keyword positional argument (5 given)
za (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> za() takes exactly 1 non-keyword positional argument (5 given)
za (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> za() takes exactly 1 non-keyword positional argument (5 given)
zade () {} -> zade() takes at least 1 positional argument (0 given)
zade () {'a': 'aa'} -> ok zade aa B d e V a
zade () {'d': 'dd'} -> zade() takes at least 1 non-keyword argument (0 given)
zade () {'d': 'dd'} -> zade() takes at least 1 non-keyword positional argument (0 given)
zade () {'a': 'aa', 'd': 'dd'} -> ok zade aa B dd e V d
zade () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zade() got an unexpected keyword argument 'b'
zade (1, 2) {} -> ok zade 1 B 2 e V e
@ -60,30 +60,30 @@ zade (1, 2) {'a': 'aa'} -> zade() got multiple values for keyword argument 'a'
zade (1, 2) {'d': 'dd'} -> zade() got multiple values for keyword argument 'd'
zade (1, 2) {'a': 'aa', 'd': 'dd'} -> zade() got multiple values for keyword argument 'a'
zade (1, 2) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zade() got multiple values for keyword argument 'a'
zade (1, 2, 3, 4, 5) {} -> zade() takes at most 3 arguments (5 given)
zade (1, 2, 3, 4, 5) {'a': 'aa'} -> zade() takes at most 3 non-keyword arguments (5 given)
zade (1, 2, 3, 4, 5) {'d': 'dd'} -> zade() takes at most 3 non-keyword arguments (5 given)
zade (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> zade() takes at most 3 non-keyword arguments (5 given)
zade (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zade() takes at most 3 non-keyword arguments (5 given)
zabk () {} -> zabk() takes exactly 2 arguments (0 given)
zabk () {'a': 'aa'} -> zabk() takes exactly 2 non-keyword arguments (1 given)
zabk () {'d': 'dd'} -> zabk() takes exactly 2 non-keyword arguments (0 given)
zabk () {'a': 'aa', 'd': 'dd'} -> zabk() takes exactly 2 non-keyword arguments (1 given)
zade (1, 2, 3, 4, 5) {} -> zade() takes at most 3 positional arguments (5 given)
zade (1, 2, 3, 4, 5) {'a': 'aa'} -> zade() takes at most 3 non-keyword positional arguments (5 given)
zade (1, 2, 3, 4, 5) {'d': 'dd'} -> zade() takes at most 3 non-keyword positional arguments (5 given)
zade (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> zade() takes at most 3 non-keyword positional arguments (5 given)
zade (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zade() takes at most 3 non-keyword positional arguments (5 given)
zabk () {} -> zabk() takes exactly 2 positional arguments (0 given)
zabk () {'a': 'aa'} -> zabk() takes exactly 2 non-keyword positional arguments (1 given)
zabk () {'d': 'dd'} -> zabk() takes exactly 2 non-keyword positional arguments (0 given)
zabk () {'a': 'aa', 'd': 'dd'} -> zabk() takes exactly 2 non-keyword positional arguments (1 given)
zabk () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> ok zabk aa bb D E V {'d': 'dd', 'e': 'ee'}
zabk (1, 2) {} -> ok zabk 1 2 D E V {}
zabk (1, 2) {'a': 'aa'} -> zabk() got multiple values for keyword argument 'a'
zabk (1, 2) {'d': 'dd'} -> ok zabk 1 2 D E V {'d': 'dd'}
zabk (1, 2) {'a': 'aa', 'd': 'dd'} -> zabk() got multiple values for keyword argument 'a'
zabk (1, 2) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabk() got multiple values for keyword argument 'a'
zabk (1, 2, 3, 4, 5) {} -> zabk() takes exactly 2 arguments (5 given)
zabk (1, 2, 3, 4, 5) {'a': 'aa'} -> zabk() takes exactly 2 non-keyword arguments (5 given)
zabk (1, 2, 3, 4, 5) {'d': 'dd'} -> zabk() takes exactly 2 non-keyword arguments (5 given)
zabk (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> zabk() takes exactly 2 non-keyword arguments (5 given)
zabk (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabk() takes exactly 2 non-keyword arguments (5 given)
zabdv () {} -> zabdv() takes at least 2 arguments (0 given)
zabdv () {'a': 'aa'} -> zabdv() takes at least 2 non-keyword arguments (1 given)
zabdv () {'d': 'dd'} -> zabdv() takes at least 2 non-keyword arguments (0 given)
zabdv () {'a': 'aa', 'd': 'dd'} -> zabdv() takes at least 2 non-keyword arguments (1 given)
zabk (1, 2, 3, 4, 5) {} -> zabk() takes exactly 2 positional arguments (5 given)
zabk (1, 2, 3, 4, 5) {'a': 'aa'} -> zabk() takes exactly 2 non-keyword positional arguments (5 given)
zabk (1, 2, 3, 4, 5) {'d': 'dd'} -> zabk() takes exactly 2 non-keyword positional arguments (5 given)
zabk (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> zabk() takes exactly 2 non-keyword positional arguments (5 given)
zabk (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabk() takes exactly 2 non-keyword positional arguments (5 given)
zabdv () {} -> zabdv() takes at least 2 positional arguments (0 given)
zabdv () {'a': 'aa'} -> zabdv() takes at least 2 non-keyword positional arguments (1 given)
zabdv () {'d': 'dd'} -> zabdv() takes at least 2 non-keyword positional arguments (0 given)
zabdv () {'a': 'aa', 'd': 'dd'} -> zabdv() takes at least 2 non-keyword positional arguments (1 given)
zabdv () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabdv() got an unexpected keyword argument 'e'
zabdv (1, 2) {} -> ok zabdv 1 2 d E () e
zabdv (1, 2) {'a': 'aa'} -> zabdv() got multiple values for keyword argument 'a'
@ -95,10 +95,10 @@ zabdv (1, 2, 3, 4, 5) {'a': 'aa'} -> zabdv() got multiple values for keyword arg
zabdv (1, 2, 3, 4, 5) {'d': 'dd'} -> zabdv() got multiple values for keyword argument 'd'
zabdv (1, 2, 3, 4, 5) {'a': 'aa', 'd': 'dd'} -> zabdv() got multiple values for keyword argument 'a'
zabdv (1, 2, 3, 4, 5) {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> zabdv() got multiple values for keyword argument 'a'
zabdevk () {} -> zabdevk() takes at least 2 arguments (0 given)
zabdevk () {'a': 'aa'} -> zabdevk() takes at least 2 non-keyword arguments (1 given)
zabdevk () {'d': 'dd'} -> zabdevk() takes at least 2 non-keyword arguments (0 given)
zabdevk () {'a': 'aa', 'd': 'dd'} -> zabdevk() takes at least 2 non-keyword arguments (1 given)
zabdevk () {} -> zabdevk() takes at least 2 positional arguments (0 given)
zabdevk () {'a': 'aa'} -> zabdevk() takes at least 2 non-keyword positional arguments (1 given)
zabdevk () {'d': 'dd'} -> zabdevk() takes at least 2 non-keyword positional arguments (0 given)
zabdevk () {'a': 'aa', 'd': 'dd'} -> zabdevk() takes at least 2 non-keyword positional arguments (1 given)
zabdevk () {'a': 'aa', 'b': 'bb', 'd': 'dd', 'e': 'ee'} -> ok zabdevk aa bb dd ee () {}
zabdevk (1, 2) {} -> ok zabdevk 1 2 d e () {}
zabdevk (1, 2) {'a': 'aa'} -> zabdevk() got multiple values for keyword argument 'a'

View file

@ -151,9 +151,9 @@ def run_tests():
#### EVERYTHING BELOW IS GENERATED #####
exec_results = [
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, []), [('Pass', (1, 9))], [])]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], None, [], []), [('Pass', (1, 9))], [])]),
('Module', [('ClassDef', (1, 0), 'C', [], [('Pass', (1, 8))])]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, None, []), [('Return', (1, 8), ('Num', (1, 15), 1))], [])]),
('Module', [('FunctionDef', (1, 0), 'f', ('arguments', [], None, [], None, [], []), [('Return', (1, 8), ('Num', (1, 15), 1))], [])]),
('Module', [('Delete', (1, 0), [('Name', (1, 4), 'v', ('Del',))])]),
('Module', [('Assign', (1, 0), [('Name', (1, 0), 'v', ('Store',))], ('Num', (1, 4), 1))]),
('Module', [('AugAssign', (1, 0), ('Name', (1, 0), 'v', ('Store',)), ('Add',), ('Num', (1, 5), 1))]),
@ -180,7 +180,7 @@ eval_results = [
('Expression', ('BoolOp', (1, 0), ('And',), [('Name', (1, 0), 'a', ('Load',)), ('Name', (1, 6), 'b', ('Load',))])),
('Expression', ('BinOp', (1, 0), ('Name', (1, 0), 'a', ('Load',)), ('Add',), ('Name', (1, 4), 'b', ('Load',)))),
('Expression', ('UnaryOp', (1, 0), ('Not',), ('Name', (1, 4), 'v', ('Load',)))),
('Expression', ('Lambda', (1, 0), ('arguments', [], None, None, []), ('Name', (1, 7), 'None', ('Load',)))),
('Expression', ('Lambda', (1, 0), ('arguments', [], None, [], None, [], []), ('Name', (1, 7), 'None', ('Load',)))),
('Expression', ('Dict', (1, 0), [('Num', (1, 2), 1)], [('Num', (1, 4), 2)])),
('Expression', ('ListComp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))])])),
('Expression', ('GeneratorExp', (1, 1), ('Name', (1, 1), 'a', ('Load',)), [('comprehension', ('Name', (1, 7), 'b', ('Store',)), ('Name', (1, 12), 'c', ('Load',)), [('Name', (1, 17), 'd', ('Load',))])])),

View file

@ -9,6 +9,7 @@
>>> dump(f.func_code)
name: f
argcount: 1
kwonlyargcount: 0
names: ()
varnames: ('x', 'g')
cellvars: ('x',)
@ -20,6 +21,7 @@ consts: ('None', '<code object g>')
>>> dump(f(4).func_code)
name: g
argcount: 1
kwonlyargcount: 0
names: ()
varnames: ('y',)
cellvars: ()
@ -34,9 +36,11 @@ consts: ('None',)
... c = a * b
... return c
...
>>> dump(h.func_code)
name: h
argcount: 2
kwonlyargcount: 0
names: ()
varnames: ('x', 'y', 'a', 'b', 'c')
cellvars: ()
@ -53,6 +57,7 @@ consts: ('None',)
>>> dump(attrs.func_code)
name: attrs
argcount: 1
kwonlyargcount: 0
names: ('attr1', 'attr2', 'attr3')
varnames: ('obj',)
cellvars: ()
@ -70,6 +75,7 @@ consts: ('None',)
>>> dump(optimize_away.func_code)
name: optimize_away
argcount: 0
kwonlyargcount: 0
names: ()
varnames: ()
cellvars: ()
@ -78,6 +84,22 @@ nlocals: 0
flags: 67
consts: ("'doc string'", 'None')
>>> def keywordonly_args(a,b,*,k1):
... return a,b,k1
...
>>> dump(keywordonly_args.func_code)
name: keywordonly_args
argcount: 2
kwonlyargcount: 1
names: ()
varnames: ('a', 'b', 'k1')
cellvars: ()
freevars: ()
nlocals: 3
flags: 67
consts: ('None',)
"""
def consts(t):
@ -91,8 +113,8 @@ def consts(t):
def dump(co):
"""Print out a text representation of a code object."""
for attr in ["name", "argcount", "names", "varnames", "cellvars",
"freevars", "nlocals", "flags"]:
for attr in ["name", "argcount", "kwonlyargcount", "names", "varnames",
"cellvars", "freevars", "nlocals", "flags"]:
print "%s: %s" % (attr, getattr(co, "co_" + attr))
print "consts:", tuple(consts(co.co_consts))

View file

@ -19,36 +19,51 @@ class CompilerTest(unittest.TestCase):
libdir = os.path.dirname(unittest.__file__)
testdir = os.path.dirname(test.test_support.__file__)
for dir in [libdir, testdir]:
for basename in os.listdir(dir):
# Print still working message since this test can be really slow
if next_time <= time.time():
next_time = time.time() + _PRINT_WORKING_MSG_INTERVAL
print >>sys.__stdout__, \
' testCompileLibrary still working, be patient...'
sys.__stdout__.flush()
## for dir in [libdir, testdir]:
## for basename in os.listdir(dir):
## # Print still working message since this test can be really slow
## if next_time <= time.time():
## next_time = time.time() + _PRINT_WORKING_MSG_INTERVAL
## print >>sys.__stdout__, \
## ' testCompileLibrary still working, be patient...'
## sys.__stdout__.flush()
##
## if not basename.endswith(".py"):
## continue
## if not TEST_ALL and random() < 0.98:
## continue
## path = os.path.join(dir, basename)
## if test.test_support.verbose:
## print "compiling", path
## f = open(path, "U")
## buf = f.read()
## f.close()
## if "badsyntax" in basename or "bad_coding" in basename:
## self.assertRaises(SyntaxError, compiler.compile,
## buf, basename, "exec")
## else:
## try:
## compiler.compile(buf, basename, "exec")
## except Exception, e:
## args = list(e.args)
## args[0] += "[in file %s]" % basename
## e.args = tuple(args)
## raise
path = "/home/jiwon/p3yk/Lib/test/test_keywordonlyarg.py"
if test.test_support.verbose:
print "compiling", path
f = open(path, "U")
buf = f.read()
f.close()
#try:
compiler.compile(buf, "test_keywordonlyarg.py", "exec")
#except Exception, e:
# args = list(e.args)
# args[0] += "[in file %s]" % path
# e.args = tuple(args)
# raise
if not basename.endswith(".py"):
continue
if not TEST_ALL and random() < 0.98:
continue
path = os.path.join(dir, basename)
if test.test_support.verbose:
print "compiling", path
f = open(path, "U")
buf = f.read()
f.close()
if "badsyntax" in basename or "bad_coding" in basename:
self.assertRaises(SyntaxError, compiler.compile,
buf, basename, "exec")
else:
try:
compiler.compile(buf, basename, "exec")
except Exception, e:
args = list(e.args)
args[0] += "[in file %s]" % basename
e.args = tuple(args)
raise
def testNewClassSyntax(self):
compiler.compile("class foo():pass\n\n","<string>","exec")

View file

@ -1,4 +1,11 @@
# Test the frozen module defined in frozen.c.
# Currently test_frozen fails:
# Implementing pep3102(keyword only argument) needs changes in
# code object, which needs modification to marshal.
# However, to regenerate hard-coded marshal data in frozen.c,
# we need to run Tools/freeze/freeze.py, which currently doesn't work
# because Lib/modulefinder.py cannot handle relative module import
# This test will keep failing until Lib/modulefinder.py is fixed
from test.test_support import TestFailed
import sys, os

View file

@ -148,7 +148,8 @@ x = eval('1, 0 or 1')
print 'funcdef'
### 'def' NAME parameters ':' suite
### parameters: '(' [varargslist] ')'
### varargslist: (fpdef ['=' test] ',')* ('*' NAME [',' ('**'|'*' '*') NAME]
### varargslist: (fpdef ['=' test] ',')*
### ('*' (NAME|',' fpdef ['=' test]) [',' ('**'|'*' '*') NAME]
### | ('**'|'*' '*') NAME)
### | fpdef ['=' test] (',' fpdef ['=' test])* [',']
### fpdef: NAME | '(' fplist ')'
@ -265,6 +266,16 @@ def d31v((x)): pass
d31v(1)
def d32v((x,)): pass
d32v((1,))
#keyword only argument tests
def pos0key1(*, key): return key
pos0key1(key=100)
def pos2key2(p1, p2, *, k1, k2=100): return p1,p2,k1,k2
pos2key2(1, 2, k1=100)
pos2key2(1, 2, k1=100, k2=200)
pos2key2(1, 2, k2=100, k1=200)
def pos2key2dict(p1, p2, *, k1=100, k2, **kwarg): return p1,p2,k1,k2,kwarg
pos2key2dict(1,2,k2=100,tokwarg1=100,tokwarg2=200)
pos2key2dict(1,2,tokwarg1=100,tokwarg2=200, k2=100)
### lambdef: 'lambda' [varargslist] ':' test
print 'lambdef'
@ -279,6 +290,9 @@ l5 = lambda x, y, z=2: x + y + z
verify(l5(1, 2) == 5)
verify(l5(1, 2, 3) == 6)
check_syntax("lambda x: x = 2")
l6 = lambda x, y, *, k=20: x+y+k
verify(l6(1,2) == 1+2+20)
verify(l6(1,2,k=10) == 1+2+10)
### stmt: simple_stmt | compound_stmt
# Tested below

View file

@ -103,6 +103,7 @@ if hasattr(new, 'code'):
c = f.func_code
argcount = c.co_argcount
kwonlyargcount = c.co_kwonlyargcount
nlocals = c.co_nlocals
stacksize = c.co_stacksize
flags = c.co_flags
@ -117,17 +118,20 @@ if hasattr(new, 'code'):
freevars = c.co_freevars
cellvars = c.co_cellvars
d = new.code(argcount, nlocals, stacksize, flags, codestring,
d = new.code(argcount, kwonlyargcount,
nlocals, stacksize, flags, codestring,
constants, names, varnames, filename, name,
firstlineno, lnotab, freevars, cellvars)
# test backwards-compatibility version with no freevars or cellvars
d = new.code(argcount, nlocals, stacksize, flags, codestring,
d = new.code(argcount, kwonlyargcount,
nlocals, stacksize, flags, codestring,
constants, names, varnames, filename, name,
firstlineno, lnotab)
try: # this used to trigger a SystemError
d = new.code(-argcount, nlocals, stacksize, flags, codestring,
d = new.code(-argcount, kwonlyargcount,
nlocals, stacksize, flags, codestring,
constants, names, varnames, filename, name,
firstlineno, lnotab)
except ValueError:
@ -136,7 +140,8 @@ if hasattr(new, 'code'):
raise TestFailed, "negative co_argcount didn't trigger an exception"
try: # this used to trigger a SystemError
d = new.code(argcount, -nlocals, stacksize, flags, codestring,
d = new.code(argcount, kwonlyargcount,
-nlocals, stacksize, flags, codestring,
constants, names, varnames, filename, name,
firstlineno, lnotab)
except ValueError:
@ -145,7 +150,8 @@ if hasattr(new, 'code'):
raise TestFailed, "negative co_nlocals didn't trigger an exception"
try: # this used to trigger a Py_FatalError!
d = new.code(argcount, nlocals, stacksize, flags, codestring,
d = new.code(argcount, kwonlyargcount,
nlocals, stacksize, flags, codestring,
constants, (5,), varnames, filename, name,
firstlineno, lnotab)
except TypeError:
@ -156,7 +162,8 @@ if hasattr(new, 'code'):
# new.code used to be a way to mutate a tuple...
class S(str): pass
t = (S("ab"),)
d = new.code(argcount, nlocals, stacksize, flags, codestring,
d = new.code(argcount, kwonlyargcount,
nlocals, stacksize, flags, codestring,
constants, t, varnames, filename, name,
firstlineno, lnotab)
verify(type(t[0]) is S, "eek, tuple changed under us!")