mirror of
https://github.com/AdaCore/cpython.git
synced 2026-02-12 12:57:15 -08:00
Jiwon Seo's PEP 3102 implementation.
See SF#1549670. The compiler package has not yet been updated.
This commit is contained in:
@@ -24,7 +24,7 @@ decorators: decorator+
|
||||
funcdef: [decorators] 'def' NAME parameters ':' suite
|
||||
parameters: '(' [varargslist] ')'
|
||||
varargslist: ((fpdef ['=' test] ',')*
|
||||
('*' NAME [',' '**' NAME] | '**' NAME) |
|
||||
('*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME) |
|
||||
fpdef ['=' test] (',' fpdef ['=' test])* [','])
|
||||
fpdef: NAME | '(' fplist ')'
|
||||
fplist: fpdef (',' fpdef)* [',']
|
||||
|
||||
@@ -328,8 +328,10 @@ struct _excepthandler {
|
||||
struct _arguments {
|
||||
asdl_seq *args;
|
||||
identifier vararg;
|
||||
asdl_seq *kwonlyargs;
|
||||
identifier kwarg;
|
||||
asdl_seq *defaults;
|
||||
asdl_seq *kw_defaults;
|
||||
};
|
||||
|
||||
struct _keyword {
|
||||
@@ -427,8 +429,9 @@ comprehension_ty comprehension(expr_ty target, expr_ty iter, asdl_seq * ifs,
|
||||
PyArena *arena);
|
||||
excepthandler_ty excepthandler(expr_ty type, expr_ty name, asdl_seq * body, int
|
||||
lineno, int col_offset, PyArena *arena);
|
||||
arguments_ty arguments(asdl_seq * args, identifier vararg, identifier kwarg,
|
||||
asdl_seq * defaults, PyArena *arena);
|
||||
arguments_ty arguments(asdl_seq * args, identifier vararg, asdl_seq *
|
||||
kwonlyargs, identifier kwarg, asdl_seq * defaults,
|
||||
asdl_seq * kw_defaults, PyArena *arena);
|
||||
keyword_ty keyword(identifier arg, expr_ty value, PyArena *arena);
|
||||
alias_ty alias(identifier name, identifier asname, PyArena *arena);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ extern "C" {
|
||||
typedef struct {
|
||||
PyObject_HEAD
|
||||
int co_argcount; /* #arguments, except *args */
|
||||
int co_kwonlyargcount; /* #keyword only arguments */
|
||||
int co_nlocals; /* #local variables */
|
||||
int co_stacksize; /* #entries needed for evaluation stack */
|
||||
int co_flags; /* CO_..., see below */
|
||||
@@ -63,8 +64,9 @@ PyAPI_DATA(PyTypeObject) PyCode_Type;
|
||||
|
||||
/* Public interface */
|
||||
PyAPI_FUNC(PyCodeObject *) PyCode_New(
|
||||
int, int, int, int, PyObject *, PyObject *, PyObject *, PyObject *,
|
||||
PyObject *, PyObject *, PyObject *, PyObject *, int, PyObject *);
|
||||
int, int, int, int, int, PyObject *, PyObject *,
|
||||
PyObject *, PyObject *, PyObject *, PyObject *,
|
||||
PyObject *, PyObject *, int, PyObject *);
|
||||
/* same as struct above */
|
||||
PyAPI_FUNC(int) PyCode_Addr2Line(PyCodeObject *, int);
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ PyAPI_FUNC(PyObject *) PyEval_EvalCodeEx(PyCodeObject *co,
|
||||
PyObject **args, int argc,
|
||||
PyObject **kwds, int kwdc,
|
||||
PyObject **defs, int defc,
|
||||
PyObject *closure);
|
||||
PyObject *kwdefs, PyObject *closure);
|
||||
|
||||
PyAPI_FUNC(PyObject *) _PyEval_CallTracing(PyObject *func, PyObject *args);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ typedef struct {
|
||||
PyObject *func_code; /* A code object */
|
||||
PyObject *func_globals; /* A dictionary (other mappings won't do) */
|
||||
PyObject *func_defaults; /* NULL or a tuple */
|
||||
PyObject *func_kwdefaults; /* NULL or a dict */
|
||||
PyObject *func_closure; /* NULL or a tuple of cell objects */
|
||||
PyObject *func_doc; /* The __doc__ attribute, can be anything */
|
||||
PyObject *func_name; /* The __name__ attribute, a string object */
|
||||
@@ -47,6 +48,8 @@ PyAPI_FUNC(PyObject *) PyFunction_GetGlobals(PyObject *);
|
||||
PyAPI_FUNC(PyObject *) PyFunction_GetModule(PyObject *);
|
||||
PyAPI_FUNC(PyObject *) PyFunction_GetDefaults(PyObject *);
|
||||
PyAPI_FUNC(int) PyFunction_SetDefaults(PyObject *, PyObject *);
|
||||
PyAPI_FUNC(PyObject *) PyFunction_GetKwDefaults(PyObject *);
|
||||
PyAPI_FUNC(int) PyFunction_SetKwDefaults(PyObject *, PyObject *);
|
||||
PyAPI_FUNC(PyObject *) PyFunction_GetClosure(PyObject *);
|
||||
PyAPI_FUNC(int) PyFunction_SetClosure(PyObject *, PyObject *);
|
||||
|
||||
@@ -60,6 +63,8 @@ PyAPI_FUNC(int) PyFunction_SetClosure(PyObject *, PyObject *);
|
||||
(((PyFunctionObject *)func) -> func_module)
|
||||
#define PyFunction_GET_DEFAULTS(func) \
|
||||
(((PyFunctionObject *)func) -> func_defaults)
|
||||
#define PyFunction_GET_KW_DEFAULTS(func) \
|
||||
(((PyFunctionObject *)func) -> func_kwdefaults)
|
||||
#define PyFunction_GET_CLOSURE(func) \
|
||||
(((PyFunctionObject *)func) -> func_closure)
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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 ')'
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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',))])])),
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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!")
|
||||
|
||||
@@ -51,6 +51,7 @@ void _AddTraceback(char *funcname, char *filename, int lineno)
|
||||
if (!empty_string) goto bad;
|
||||
py_code = PyCode_New(
|
||||
0, /*int argcount,*/
|
||||
0, /*int kwonlyargcount,*/
|
||||
0, /*int nlocals,*/
|
||||
0, /*int stacksize,*/
|
||||
0, /*int flags,*/
|
||||
|
||||
@@ -1105,13 +1105,13 @@ validate_testlist_safe(node *tree)
|
||||
}
|
||||
|
||||
|
||||
/* '*' NAME [',' '**' NAME] | '**' NAME
|
||||
/* '*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME
|
||||
*/
|
||||
static int
|
||||
validate_varargslist_trailer(node *tree, int start)
|
||||
{
|
||||
int nch = NCH(tree);
|
||||
int res = 0;
|
||||
int res = 0, i;
|
||||
int sym;
|
||||
|
||||
if (nch <= start) {
|
||||
@@ -1121,15 +1121,40 @@ validate_varargslist_trailer(node *tree, int start)
|
||||
sym = TYPE(CHILD(tree, start));
|
||||
if (sym == STAR) {
|
||||
/*
|
||||
* ('*' NAME [',' '**' NAME]
|
||||
* '*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME
|
||||
*/
|
||||
if (nch-start == 2)
|
||||
res = validate_name(CHILD(tree, start+1), NULL);
|
||||
else if (nch-start == 5)
|
||||
else if (nch-start == 5 && TYPE(CHILD(tree, start+2)) == COMMA)
|
||||
res = (validate_name(CHILD(tree, start+1), NULL)
|
||||
&& validate_comma(CHILD(tree, start+2))
|
||||
&& validate_doublestar(CHILD(tree, start+3))
|
||||
&& validate_name(CHILD(tree, start+4), NULL));
|
||||
else {
|
||||
/* skip over [NAME] (',' NAME ['=' test])* */
|
||||
i = start + 1;
|
||||
if (TYPE(CHILD(tree, i)) == NAME) { /* skip over [NAME] */
|
||||
i += 1;
|
||||
}
|
||||
while (res && i+1 < nch) { /* validate (',' NAME ['=' test])* */
|
||||
res = validate_comma(CHILD(tree, i));
|
||||
if (TYPE(CHILD(tree, i+1)) == DOUBLESTAR)
|
||||
break;
|
||||
res = res && validate_name(CHILD(tree, i+1), NULL);
|
||||
if (res && i+2 < nch && TYPE(CHILD(tree, i+2)) == EQUAL) {
|
||||
res = res && (i+3 < nch)
|
||||
&& validate_test(CHILD(tree, i+3));
|
||||
i += 4;
|
||||
}
|
||||
else {
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
/* [',' '**' NAME] */
|
||||
if (res && i+1 < nch && TYPE(CHILD(tree, i+1)) == DOUBLESTAR) {
|
||||
res = validate_name(CHILD(tree, i+2), NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sym == DOUBLESTAR) {
|
||||
/*
|
||||
@@ -1148,9 +1173,8 @@ validate_varargslist_trailer(node *tree, int start)
|
||||
*
|
||||
* varargslist:
|
||||
* (fpdef ['=' test] ',')*
|
||||
* ('*' NAME [',' '**' NAME]
|
||||
* | '**' NAME)
|
||||
* | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||
* ('*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME)
|
||||
* | fpdef ['=' test] (',' fpdef ['=' test])* [',']
|
||||
*
|
||||
*/
|
||||
static int
|
||||
@@ -1169,7 +1193,7 @@ validate_varargslist(node *tree)
|
||||
sym = TYPE(CHILD(tree, 0));
|
||||
if (sym == STAR || sym == DOUBLESTAR)
|
||||
/* whole thing matches:
|
||||
* '*' NAME [',' '**' NAME] | '**' NAME
|
||||
* '*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME
|
||||
*/
|
||||
res = validate_varargslist_trailer(tree, 0);
|
||||
else if (sym == fpdef) {
|
||||
@@ -1201,7 +1225,7 @@ validate_varargslist(node *tree)
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* ... '*' NAME [',' '**' NAME] | '**' NAME
|
||||
/* .. ('*' [NAME] (',' NAME ['=' test])* [',' '**' NAME] | '**' NAME)
|
||||
* i --^^^
|
||||
*/
|
||||
if (res)
|
||||
|
||||
@@ -279,6 +279,7 @@ getcode(enum HandlerTypes slot, char* func_name, int lineno)
|
||||
filename = PyString_FromString(__FILE__);
|
||||
handler_info[slot].tb_code =
|
||||
PyCode_New(0, /* argcount */
|
||||
0, /* kwonlyargcount */
|
||||
0, /* nlocals */
|
||||
0, /* stacksize */
|
||||
0, /* flags */
|
||||
|
||||
@@ -41,7 +41,8 @@ intern_strings(PyObject *tuple)
|
||||
|
||||
|
||||
PyCodeObject *
|
||||
PyCode_New(int argcount, int nlocals, int stacksize, int flags,
|
||||
PyCode_New(int argcount, int kwonlyargcount,
|
||||
int nlocals, int stacksize, int flags,
|
||||
PyObject *code, PyObject *consts, PyObject *names,
|
||||
PyObject *varnames, PyObject *freevars, PyObject *cellvars,
|
||||
PyObject *filename, PyObject *name, int firstlineno,
|
||||
@@ -80,6 +81,7 @@ PyCode_New(int argcount, int nlocals, int stacksize, int flags,
|
||||
co = PyObject_NEW(PyCodeObject, &PyCode_Type);
|
||||
if (co != NULL) {
|
||||
co->co_argcount = argcount;
|
||||
co->co_kwonlyargcount = kwonlyargcount;
|
||||
co->co_nlocals = nlocals;
|
||||
co->co_stacksize = stacksize;
|
||||
co->co_flags = flags;
|
||||
@@ -112,6 +114,7 @@ PyCode_New(int argcount, int nlocals, int stacksize, int flags,
|
||||
|
||||
static PyMemberDef code_memberlist[] = {
|
||||
{"co_argcount", T_INT, OFF(co_argcount), READONLY},
|
||||
{"co_kwonlyargcount", T_INT, OFF(co_kwonlyargcount), READONLY},
|
||||
{"co_nlocals", T_INT, OFF(co_nlocals), READONLY},
|
||||
{"co_stacksize",T_INT, OFF(co_stacksize), READONLY},
|
||||
{"co_flags", T_INT, OFF(co_flags), READONLY},
|
||||
@@ -182,6 +185,7 @@ static PyObject *
|
||||
code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
||||
{
|
||||
int argcount;
|
||||
int kwonlyargcount;
|
||||
int nlocals;
|
||||
int stacksize;
|
||||
int flags;
|
||||
@@ -197,8 +201,9 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
||||
int firstlineno;
|
||||
PyObject *lnotab;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "iiiiSO!O!O!SSiS|O!O!:code",
|
||||
&argcount, &nlocals, &stacksize, &flags,
|
||||
if (!PyArg_ParseTuple(args, "iiiiiSO!O!O!SSiS|O!O!:code",
|
||||
&argcount, &kwonlyargcount,
|
||||
&nlocals, &stacksize, &flags,
|
||||
&code,
|
||||
&PyTuple_Type, &consts,
|
||||
&PyTuple_Type, &names,
|
||||
@@ -216,6 +221,12 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (kwonlyargcount < 0) {
|
||||
PyErr_SetString(
|
||||
PyExc_ValueError,
|
||||
"code: kwonlyargcount must not be negative");
|
||||
goto cleanup;
|
||||
}
|
||||
if (nlocals < 0) {
|
||||
PyErr_SetString(
|
||||
PyExc_ValueError,
|
||||
@@ -242,7 +253,8 @@ code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
||||
if (ourcellvars == NULL)
|
||||
goto cleanup;
|
||||
|
||||
co = (PyObject *)PyCode_New(argcount, nlocals, stacksize, flags,
|
||||
co = (PyObject *)PyCode_New(argcount, kwonlyargcount,
|
||||
nlocals, stacksize, flags,
|
||||
code, consts, ournames, ourvarnames,
|
||||
ourfreevars, ourcellvars, filename,
|
||||
name, firstlineno, lnotab);
|
||||
@@ -312,6 +324,8 @@ code_richcompare(PyObject *self, PyObject *other, int op)
|
||||
if (eq <= 0) goto unequal;
|
||||
eq = co->co_argcount == cp->co_argcount;
|
||||
if (!eq) goto unequal;
|
||||
eq = co->co_kwonlyargcount == cp->co_kwonlyargcount;
|
||||
if (!eq) goto unequal;
|
||||
eq = co->co_nlocals == cp->co_nlocals;
|
||||
if (!eq) goto unequal;
|
||||
eq = co->co_flags == cp->co_flags;
|
||||
@@ -369,7 +383,8 @@ code_hash(PyCodeObject *co)
|
||||
h6 = PyObject_Hash(co->co_cellvars);
|
||||
if (h6 == -1) return -1;
|
||||
h = h0 ^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^
|
||||
co->co_argcount ^ co->co_nlocals ^ co->co_flags;
|
||||
co->co_argcount ^ co->co_kwonlyargcount ^
|
||||
co->co_nlocals ^ co->co_flags;
|
||||
if (h == -1) h = -2;
|
||||
return h;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user