[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