[pypy-commit] pypy py3k-kwonly-builtin: more fixes
arigo
pypy.commits at gmail.com
Fri Aug 19 14:45:30 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch: py3k-kwonly-builtin
Changeset: r86332:b130c20feba7
Date: 2016-08-19 20:44 +0200
http://bitbucket.org/pypy/pypy/changeset/b130c20feba7/
Log: more fixes
diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -153,7 +153,7 @@
@jit.unroll_safe
def _match_signature(self, w_firstarg, scope_w, signature, defaults_w=None,
- w_kw_defs=None, blindargs=0):
+ kw_defs_w=None, blindargs=0):
"""Parse args and kwargs according to the signature of a code object,
or raise an ArgErr in case of failure.
"""
@@ -281,19 +281,18 @@
else:
missing_positional.append(signature.argnames[i])
- # finally, fill kwonly arguments with w_kw_defs (if needed)
- for i in range(co_argcount, co_argcount + co_kwonlyargcount):
- if scope_w[i] is not None:
+ # finally, fill kwonly arguments with kw_defs_w (if needed)
+ for i in range(co_kwonlyargcount):
+ j = co_argcount + i
+ if scope_w[j] is not None:
continue
- name = signature.kwonlyargnames[i - co_argcount]
- if w_kw_defs is None:
+ try:
+ w_def = signature.get_kwonly_default(i, kw_defs_w)
+ except KeyError:
+ name = signature.kwonlyargnames[i]
missing_kwonly.append(name)
- continue
- w_def = self.space.finditem_str(w_kw_defs, name)
- if w_def is not None:
- scope_w[i] = w_def
else:
- missing_kwonly.append(name)
+ scope_w[j] = w_def
if missing_positional:
raise ArgErrMissing(missing_positional, True)
@@ -303,7 +302,7 @@
def parse_into_scope(self, w_firstarg,
scope_w, fnname, signature, defaults_w=None,
- w_kw_defs=None):
+ kw_defs_w=None):
"""Parse args and kwargs to initialize a frame
according to the signature of code object.
Store the argumentvalues into scope_w.
@@ -312,30 +311,30 @@
try:
self._match_signature(w_firstarg,
scope_w, signature, defaults_w,
- w_kw_defs, 0)
+ kw_defs_w, 0)
except ArgErr as e:
raise oefmt(self.space.w_TypeError, "%s() %8", fnname, e.getmsg())
return signature.scope_length()
- def _parse(self, w_firstarg, signature, defaults_w, w_kw_defs, blindargs=0):
+ def _parse(self, w_firstarg, signature, defaults_w, kw_defs_w, blindargs=0):
"""Parse args and kwargs according to the signature of a code object,
or raise an ArgErr in case of failure.
"""
scopelen = signature.scope_length()
scope_w = [None] * scopelen
self._match_signature(w_firstarg, scope_w, signature, defaults_w,
- w_kw_defs, blindargs)
+ kw_defs_w, blindargs)
return scope_w
def parse_obj(self, w_firstarg,
- fnname, signature, defaults_w=None, w_kw_defs=None,
+ fnname, signature, defaults_w=None, kw_defs_w=None,
blindargs=0):
"""Parse args and kwargs to initialize a frame
according to the signature of code object.
"""
try:
- return self._parse(w_firstarg, signature, defaults_w, w_kw_defs,
+ return self._parse(w_firstarg, signature, defaults_w, kw_defs_w,
blindargs)
except ArgErr as e:
raise oefmt(self.space.w_TypeError, "%s() %8", fnname, e.getmsg())
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -36,9 +36,9 @@
'closure?[*]',
'defs_w?[*]',
'name?',
- 'w_kw_defs?']
+ 'kw_defs_w?']
- def __init__(self, space, code, w_globals=None, defs_w=[], w_kw_defs=None,
+ def __init__(self, space, code, w_globals=None, defs_w=[], kw_defs_w=None,
closure=None, w_ann=None, forcename=None, qualname=None):
self.space = space
self.name = forcename or code.co_name
@@ -48,7 +48,7 @@
self.w_func_globals = w_globals # the globals dictionary
self.closure = closure # normally, list of Cell instances or None
self.defs_w = defs_w
- self.w_kw_defs = w_kw_defs
+ self.kw_defs_w = kw_defs_w
self.w_func_dict = None # filled out below if needed
self.w_module = None
self.w_ann = w_ann
@@ -373,19 +373,35 @@
self.defs_w = []
def fget_func_kwdefaults(self, space):
- if self.w_kw_defs is None:
+ if self.kw_defs_w is None:
return space.w_None
- return self.w_kw_defs
+ w_result = space.newdict(strdict=True)
+ for key, w_value in self.kw_defs_w.items():
+ space.setitem_str(w_result, key, w_value)
+ return w_result
+
+ @staticmethod
+ def add_kwdefaults(space, kw_defs_w, w_key, w_value):
+ key = space.unicode_w(w_key).encode('utf-8')
+ kw_defs_w[key] = w_value
def fset_func_kwdefaults(self, space, w_new):
if space.is_w(w_new, space.w_None):
- w_new = None
+ self.kw_defs_w = None
elif not space.isinstance_w(w_new, space.w_dict):
raise oefmt(space.w_TypeError, "__kwdefaults__ must be a dict")
- self.w_kw_defs = w_new
+ else:
+ # must assign a new dictionary to 'kw_defs_w', never mutate
+ # the existing dictionary: this is because
+ # Signature.get_kwonly_default() is an elidable function.
+ new_w = {}
+ for w_key in space.unpackiterable(w_new):
+ w_value = space.getitem(w_new, w_key)
+ self.add_kwdefaults(space, new_w, w_key, w_value)
+ self.kw_defs_w = new_w
def fdel_func_kwdefaults(self, space):
- self.w_kw_defs = None
+ self.kw_defs_w = None
def fget_func_doc(self, space):
if self.w_doc is None:
@@ -663,7 +679,7 @@
def __init__(self, func):
assert isinstance(func, Function)
Function.__init__(self, func.space, func.code, func.w_func_globals,
- func.defs_w, func.w_kw_defs, func.closure,
+ func.defs_w, func.kw_defs_w, func.closure,
None, func.name)
self.w_doc = func.w_doc
self.w_func_dict = func.w_func_dict
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -723,7 +723,7 @@
space = func.space
activation = self.activation
scope_w = args.parse_obj(w_obj, func.name, self.sig,
- func.defs_w, func.w_kw_defs, self.minargs)
+ func.defs_w, func.kw_defs_w, self.minargs)
try:
w_result = activation._run(space, scope_w)
except DescrMismatch:
diff --git a/pypy/interpreter/pycode.py b/pypy/interpreter/pycode.py
--- a/pypy/interpreter/pycode.py
+++ b/pypy/interpreter/pycode.py
@@ -262,7 +262,7 @@
fresh_frame = jit.hint(frame, access_directly=True,
fresh_virtualizable=True)
args.parse_into_scope(None, fresh_frame.locals_cells_stack_w, func.name,
- sig, func.defs_w, func.w_kw_defs)
+ sig, func.defs_w, func.kw_defs_w)
fresh_frame.init_cells()
return frame.run()
@@ -274,7 +274,7 @@
fresh_frame = jit.hint(frame, access_directly=True,
fresh_virtualizable=True)
args.parse_into_scope(w_obj, fresh_frame.locals_cells_stack_w, func.name,
- sig, func.defs_w, func.w_kw_defs)
+ sig, func.defs_w, func.kw_defs_w)
fresh_frame.init_cells()
return frame.run()
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1235,15 +1235,16 @@
for i in range(len(names_w) - 1, -1, -1):
space.setitem(w_ann, names_w[i], self.popvalue())
defaultarguments = self.popvalues(posdefaults)
- w_kw_defs = None
+ kw_defs_w = None
if kwdefaults:
- w_kw_defs = space.newdict(strdict=True)
- for i in range(kwdefaults - 1, -1, -1):
- w_name = self.popvalue()
- w_def = self.popvalue()
- space.setitem(w_kw_defs, w_def, w_name)
+ kw_defs_w = {}
+ for i in range(kwdefaults):
+ w_defvalue = self.popvalue()
+ w_defname = self.popvalue()
+ function.Function.add_kwdefaults(space, kw_defs_w,
+ w_defname, w_defvalue)
fn = function.Function(space, codeobj, self.get_w_globals(), defaultarguments,
- w_kw_defs, freevars, w_ann, qualname=qualname)
+ kw_defs_w, freevars, w_ann, qualname=qualname)
self.pushvalue(space.wrap(fn))
def MAKE_FUNCTION(self, oparg, next_instr):
diff --git a/pypy/interpreter/signature.py b/pypy/interpreter/signature.py
--- a/pypy/interpreter/signature.py
+++ b/pypy/interpreter/signature.py
@@ -25,6 +25,13 @@
pass
return -1
+ @jit.elidable
+ def get_kwonly_default(self, i, kw_defs_w):
+ if kw_defs_w is None:
+ raise KeyError
+ name = self.kwonlyargnames[i]
+ return kw_defs_w[name]
+
def num_argnames(self):
return len(self.argnames)
More information about the pypy-commit
mailing list