Author: Armin Rigo <[email protected]>
Branch: py3k
Changeset: r86363:aceb45156627
Date: 2016-08-20 22:57 +0200
http://bitbucket.org/pypy/pypy/changeset/aceb45156627/
Log: hg merge py3k-kwonly-builtin
Fix kwonly handling for built-in functions, and also probably fix
the handling of kwonly arguments in general in the JIT
diff --git a/pypy/interpreter/eval.py b/pypy/interpreter/eval.py
--- a/pypy/interpreter/eval.py
+++ b/pypy/interpreter/eval.py
@@ -40,9 +40,6 @@
and possibly more locals."""
return self.signature().getallvarnames()
- def getformalargcount(self):
- return self.signature().scope_length()
-
def getdocstring(self, space):
return space.w_None
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -38,7 +38,9 @@
'name?',
'w_kw_defs?']
- def __init__(self, space, code, w_globals=None, defs_w=[], w_kw_defs=None,
+ 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,10 +50,12 @@
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.w_func_dict = None # filled out below if needed
self.w_module = None
self.w_ann = w_ann
+ #
+ if kw_defs_w is not None:
+ self.init_kwdefaults_dict(kw_defs_w)
def __repr__(self):
# return "function %s.%s" % (self.space, self.name)
@@ -379,14 +383,29 @@
def fset_func_kwdefaults(self, space, w_new):
if space.is_w(w_new, space.w_None):
- w_new = 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
+ self.w_kw_defs = None
+ else:
+ if not space.isinstance_w(w_new, space.w_dict):
+ raise oefmt(space.w_TypeError, "__kwdefaults__ must be a dict")
+ w_instance = self.init_kwdefaults_dict()
+ w_instance.setdict(space, w_new)
+ self.w_kw_defs = w_instance.getdict(space)
def fdel_func_kwdefaults(self, space):
self.w_kw_defs = None
+ def init_kwdefaults_dict(self, kw_defs_w=[]):
+ # use the mapdict logic to get at least not-too-bad JIT code
+ # from function calls with default values of kwonly arguments
+ space = self.space
+ w_class = space.fromcache(KwDefsClassCache).w_class
+ w_instance = space.call_function(w_class)
+ for w_name, w_value in kw_defs_w:
+ attr = space.unicode_w(w_name).encode('utf-8')
+ w_instance.setdictvalue(space, attr, w_value)
+ self.w_kw_defs = w_instance.getdict(space)
+ return w_instance
+
def fget_func_doc(self, space):
if self.w_doc is None:
self.w_doc = self.code.getdocstring(space)
@@ -663,10 +682,12 @@
def __init__(self, func):
assert isinstance(func, Function)
Function.__init__(self, func.space, func.code, func.w_func_globals,
- func.defs_w, None, func.closure, None, func.name)
+ func.defs_w, None, func.closure,
+ None, func.name)
self.w_doc = func.w_doc
self.w_func_dict = func.w_func_dict
self.w_module = func.w_module
+ self.w_kw_defs = func.w_kw_defs
def descr_builtinfunction__new__(space, w_subtype):
raise oefmt(space.w_TypeError,
@@ -684,3 +705,12 @@
else:
code = None
return isinstance(code, BuiltinCode)
+
+
+class KwDefsClassCache:
+ def __init__(self, space):
+ self.w_class = space.appexec([], """():
+ class KwDefs:
+ pass
+ return KwDefs
+ """)
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -28,6 +28,8 @@
from rpython.rlib.rarithmetic import r_longlong, r_int, r_ulonglong, r_uint
from rpython.tool.sourcetools import func_with_new_name, compile2
+NO_DEFAULT = object()
+
# internal non-translatable parts:
class SignatureBuilder(object):
@@ -44,12 +46,21 @@
self.argnames = argnames
self.varargname = varargname
self.kwargname = kwargname
+ self.kwonlyargnames = None
def append(self, argname):
- self.argnames.append(argname)
+ if self.kwonlyargnames is None:
+ self.argnames.append(argname)
+ else:
+ self.kwonlyargnames.append(argname)
+
+ def marker_kwonly(self):
+ assert self.kwonlyargnames is None
+ self.kwonlyargnames = []
def signature(self):
- return Signature(self.argnames, self.varargname, self.kwargname)
+ return Signature(self.argnames, self.varargname, self.kwargname,
+ self.kwonlyargnames)
#________________________________________________________________
@@ -66,13 +77,6 @@
"""NOT_RPYTHON"""
raise NotImplementedError
-def kwonly(arg_unwrapper):
- """Mark argument as keyword-only.
-
- XXX: has no actual effect for now.
- """
- return arg_unwrapper
-
class UnwrapSpecRecipe(object):
"NOT_RPYTHON"
@@ -229,6 +233,11 @@
name = int_unwrapping_space_method(typ)
self.checked_space_method(name, app_sig)
+ def visit_kwonly(self, _, app_sig):
+ argname = self.orig_arg()
+ assert argname == '__kwonly__'
+ app_sig.marker_kwonly()
+
class UnwrapSpec_EmitRun(UnwrapSpecEmit):
@@ -316,6 +325,9 @@
def visit_truncatedint_w(self, typ):
self.run_args.append("space.truncatedint_w(%s)" % (self.scopenext(),))
+ def visit_kwonly(self, typ):
+ self.run_args.append("None")
+
def _make_unwrap_activation_class(self, unwrap_spec, cache={}):
try:
key = tuple(unwrap_spec)
@@ -468,6 +480,9 @@
def visit_truncatedint_w(self, typ):
self.unwrap.append("space.truncatedint_w(%s)" % (self.nextarg(),))
+ def visit_kwonly(self, typ):
+ raise FastFuncNotSupported
+
def make_fastfunc(unwrap_spec, func):
unwrap_info = UnwrapSpec_FastFunc_Unwrap()
unwrap_info.apply_over(unwrap_spec)
@@ -563,6 +578,8 @@
unwrap_spec.append('args_w')
elif argname.startswith('w_'):
unwrap_spec.append(W_Root)
+ elif argname == '__kwonly__':
+ unwrap_spec.append('kwonly')
else:
unwrap_spec.append(None)
@@ -616,6 +633,8 @@
argnames = sig.argnames
varargname = sig.varargname
kwargname = sig.kwargname
+ if sig.kwonlyargnames:
+ import pdb; pdb.set_trace()
self._argnames = argnames
if unwrap_spec is None:
@@ -950,64 +969,71 @@
self.name = app_name
self.as_classmethod = as_classmethod
- if not f.func_defaults:
- self._staticdefs = []
- else:
- argnames = self._code._argnames
- defaults = f.func_defaults
- self._staticdefs = zip(argnames[-len(defaults):], defaults)
+ argnames = self._code._argnames
+ defaults = f.func_defaults or ()
+ self._staticdefs = dict(zip(
+ argnames[len(argnames) - len(defaults):], defaults))
+
return self
def _getdefaults(self, space):
"NOT_RPYTHON"
- defs_w = []
- unwrap_spec = self._code._unwrap_spec[-len(self._staticdefs):]
- for i, (name, defaultval) in enumerate(self._staticdefs):
+ alldefs_w = {}
+ assert len(self._code._argnames) == len(self._code._unwrap_spec)
+ for name, spec in zip(self._code._argnames, self._code._unwrap_spec):
+ if name == '__kwonly__':
+ continue
+
+ defaultval = self._staticdefs.get(name, NO_DEFAULT)
+ w_def = Ellipsis
if name.startswith('w_'):
- assert defaultval is None, (
+ assert defaultval in (NO_DEFAULT, None), (
"%s: default value for '%s' can only be None, got %r; "
"use unwrap_spec(...=WrappedDefault(default))" % (
self._code.identifier, name, defaultval))
- defs_w.append(None)
- elif name != '__args__' and name != 'args_w':
- spec = unwrap_spec[i]
- if isinstance(defaultval, str) and spec not in [str]:
- defs_w.append(space.newbytes(defaultval))
- else:
- defs_w.append(space.wrap(defaultval))
- if self._code._unwrap_spec:
- UNDEFINED = object()
- alldefs_w = [UNDEFINED] * len(self._code.sig.argnames)
- if defs_w:
- alldefs_w[-len(defs_w):] = defs_w
- code = self._code
- assert isinstance(code._unwrap_spec, (list, tuple))
- assert isinstance(code._argnames, list)
- assert len(code._unwrap_spec) == len(code._argnames)
- for i in range(len(code._unwrap_spec)-1, -1, -1):
- spec = code._unwrap_spec[i]
- argname = code._argnames[i]
- if isinstance(spec, tuple) and spec[0] is W_Root:
- assert False, "use WrappedDefault"
- if isinstance(spec, WrappedDefault):
- default_value = spec.default_value
- if isinstance(default_value, str):
- w_default = space.newbytes(default_value)
- else:
- w_default = space.wrap(default_value)
- assert isinstance(w_default, W_Root)
- assert argname.startswith('w_')
- argname = argname[2:]
- j = self._code.sig.argnames.index(argname)
- assert alldefs_w[j] in (UNDEFINED, None)
- alldefs_w[j] = w_default
- first_defined = 0
- while (first_defined < len(alldefs_w) and
- alldefs_w[first_defined] is UNDEFINED):
- first_defined += 1
- defs_w = alldefs_w[first_defined:]
- assert UNDEFINED not in defs_w
- return defs_w
+ if defaultval is None:
+ w_def = None
+
+ if isinstance(spec, tuple) and spec[0] is W_Root:
+ assert False, "use WrappedDefault"
+ elif isinstance(spec, WrappedDefault):
+ assert name.startswith('w_')
+ defaultval = spec.default_value
+ w_def = Ellipsis
+
+ if defaultval is not NO_DEFAULT:
+ if name != '__args__' and name != 'args_w':
+ if w_def is Ellipsis:
+ if isinstance(defaultval, str) and spec not in [str]:
+ w_def = space.newbytes(defaultval)
+ else:
+ w_def = space.wrap(defaultval)
+ if name.startswith('w_'):
+ name = name[2:]
+ alldefs_w[name] = w_def
+ #
+ # Here, 'alldefs_w' maps some argnames to their wrapped default
+ # value. We return two lists:
+ # - a list of defaults for positional arguments, which covers
+ # some suffix of the sig.argnames list
+ # - a list of pairs (w_name, w_def) for kwonly arguments
+ #
+ sig = self._code.sig
+ first_defined = 0
+ while (first_defined < len(sig.argnames) and
+ sig.argnames[first_defined] not in alldefs_w):
+ first_defined += 1
+ defs_w = [alldefs_w.pop(name) for name in sig.argnames[first_defined:]]
+
+ kw_defs_w = None
+ if alldefs_w:
+ kw_defs_w = []
+ for name, w_def in sorted(alldefs_w.items()):
+ assert name in sig.kwonlyargnames
+ w_name = space.newunicode(name.decode('utf-8'))
+ kw_defs_w.append((w_name, w_def))
+
+ return defs_w, kw_defs_w
# lazy binding to space
@@ -1027,9 +1053,10 @@
def build(cache, gateway):
"NOT_RPYTHON"
space = cache.space
- defs = gateway._getdefaults(space) # needs to be implemented by
subclass
+ defs_w, kw_defs_w = gateway._getdefaults(space)
code = gateway._code
- fn = FunctionWithFixedCode(space, code, None, defs,
forcename=gateway.name)
+ fn = FunctionWithFixedCode(space, code, None, defs_w, kw_defs_w,
+ forcename=gateway.name)
if not space.config.translating:
fn.add_to_table()
if gateway.as_classmethod:
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,15 @@
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()
+ kw_defs_w.append((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
@@ -39,6 +39,7 @@
def scope_length(self):
scopelen = len(self.argnames)
+ scopelen += len(self.kwonlyargnames)
scopelen += self.has_vararg()
scopelen += self.has_kwarg()
return scopelen
diff --git a/pypy/interpreter/test/test_argument.py
b/pypy/interpreter/test/test_argument.py
--- a/pypy/interpreter/test/test_argument.py
+++ b/pypy/interpreter/test/test_argument.py
@@ -30,7 +30,7 @@
assert sig.num_argnames() == 3
assert sig.has_vararg()
assert sig.has_kwarg()
- assert sig.scope_length() == 5
+ assert sig.scope_length() == 6
assert sig.getallvarnames() == ["a", "b", "c", "d", "kwonly", "c"]
def test_eq(self):
diff --git a/pypy/interpreter/test/test_gateway.py
b/pypy/interpreter/test/test_gateway.py
--- a/pypy/interpreter/test/test_gateway.py
+++ b/pypy/interpreter/test/test_gateway.py
@@ -47,6 +47,12 @@
code = gateway.BuiltinCode(f, unwrap_spec=[gateway.ObjSpace, "index"])
assert code.signature() == Signature(["index"], None, None)
+ def f(space, __kwonly__, w_x):
+ pass
+ code = gateway.BuiltinCode(f, unwrap_spec=[gateway.ObjSpace,
+ "kwonly", W_Root])
+ assert code.signature() == Signature([], kwonlyargnames=['x'])
+
def test_call(self):
def c(space, w_x, w_y, hello_w):
@@ -753,7 +759,7 @@
@gateway.unwrap_spec(w_x = WrappedDefault(42), y=int)
def g(space, w_x, y):
never_called
- py.test.raises(AssertionError, space.wrap, gateway.interp2app_temp(g))
+ py.test.raises(KeyError, space.wrap, gateway.interp2app_temp(g))
def test_unwrap_spec_default_applevel_bug2(self):
space = self.space
@@ -803,6 +809,80 @@
w_res = space.call_args(w_g, args)
assert space.eq_w(w_res, space.newbytes('foo'))
+ def test_unwrap_spec_kwonly(self):
+ space = self.space
+ def g(space, w_x, __kwonly__, w_y):
+ return space.sub(w_x, w_y)
+ w_g = space.wrap(gateway.interp2app_temp(g))
+ w = space.wrap
+ w1 = w(1)
+
+ for i in range(4):
+ a = argument.Arguments(space, [w1, w1, w1])
+ py.test.raises(gateway.OperationError, space.call_args, w_g, a)
+ py.test.raises(gateway.OperationError, space.call_function, w_g,
+ *(i * (w1,)))
+
+ args = argument.Arguments(space, [w(1)],
+ w_starstararg = w({'y': 10}))
+ assert space.eq_w(space.call_args(w_g, args), w(-9))
+ args = argument.Arguments(space, [],
+ w_starstararg = w({'x': 2, 'y': 10}))
+ assert space.eq_w(space.call_args(w_g, args), w(-8))
+
+ def test_unwrap_spec_kwonly_default(self):
+ space = self.space
+ @gateway.unwrap_spec(w_x2=WrappedDefault(50), y2=int)
+ def g(space, w_x1, w_x2, __kwonly__, w_y1, y2=200):
+ return space.sub(space.sub(w_x1, w_x2),
+ space.sub(w_y1, w(y2)))
+ w_g = space.wrap(gateway.interp2app_temp(g))
+ w = space.wrap
+ w1 = w(1)
+
+ for i in range(6):
+ py.test.raises(gateway.OperationError, space.call_function, w_g,
+ *(i * (w1,)))
+
+ def expected(x1, x2=50, y1="missing", y2=200):
+ return (x1 - x2) - (y1 - y2)
+
+ def check(*args, **kwds):
+ a = argument.Arguments(space, [], w_stararg = w(args),
+ w_starstararg = w(kwds))
+ w_res = space.call_args(w_g, a)
+ assert space.eq_w(w_res, w(expected(*args, **kwds)))
+
+ del kwds['y1']
+ a = argument.Arguments(space, [], w_stararg = w(args),
+ w_starstararg = w(kwds))
+ py.test.raises(gateway.OperationError, space.call_args, w_g, a)
+
+ args += (1234,)
+ a = argument.Arguments(space, [], w_stararg = w(args),
+ w_starstararg = w(kwds))
+ py.test.raises(gateway.OperationError, space.call_args, w_g, a)
+
+ check(5, y1=1234)
+ check(5, 1, y1=1234)
+ check(5, x2=1, y1=1234)
+ check(5, y1=1234, y2=343)
+ check(5, 1, y1=1234, y2=343)
+ check(5, x2=1, y1=1234, y2=343)
+ check(x1=5, y1=1234, )
+ check(x1=5, x2=1, y1=1234, )
+ check(x1=5, y1=1234, y2=343)
+ check(x1=5, x2=1, y1=1234, y2=343)
+
+ def test_unwrap_spec_kwonly_default_2(self):
+ space = self.space
+ @gateway.unwrap_spec(w_x2=WrappedDefault(50))
+ def g(space, w_x2=None):
+ return w_x2
+ w_g = space.wrap(gateway.interp2app_temp(g))
+ w_res = space.call_function(w_g)
+ assert space.eq_w(w_res, space.wrap(50))
+
class AppTestPyTestMark:
@py.test.mark.unlikely_to_exist
diff --git a/pypy/interpreter/test/test_interpreter.py
b/pypy/interpreter/test/test_interpreter.py
--- a/pypy/interpreter/test/test_interpreter.py
+++ b/pypy/interpreter/test/test_interpreter.py
@@ -379,6 +379,20 @@
assert X().f() == 42
"""
+ def test_kwonlyarg_required(self):
+ """
+ def f(*, a=5, b):
+ return (a, b)
+ assert f(b=10) == (5, 10)
+ assert f(a=7, b=12) == (7, 12)
+ raises(TypeError, f)
+ raises(TypeError, f, 1)
+ raises(TypeError, f, 1, 1)
+ raises(TypeError, f, a=1)
+ raises(TypeError, f, 1, a=1)
+ raises(TypeError, f, 1, b=1)
+ """
+
def test_extended_unpacking_short(self):
"""
class Seq:
diff --git a/pypy/module/posix/interp_posix.py
b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -15,8 +15,7 @@
from rpython.rlib.unroll import unrolling_iterable
from rpython.tool.sourcetools import func_with_new_name
-from pypy.interpreter.gateway import (
- unwrap_spec, WrappedDefault, Unwrapper, kwonly)
+from pypy.interpreter.gateway import unwrap_spec, WrappedDefault, Unwrapper
from pypy.interpreter.error import (
OperationError, oefmt, wrap_oserror, wrap_oserror2, strerror as _strerror)
from pypy.interpreter.executioncontext import ExecutionContext
@@ -211,7 +210,8 @@
"%s: %s unavailable on this platform", funcname, arg)
@unwrap_spec(flags=c_int, mode=c_int, dir_fd=DirFD(rposix.HAVE_OPENAT))
-def open(space, w_path, flags, mode=0777, dir_fd=DEFAULT_DIR_FD):
+def open(space, w_path, flags, mode=0777,
+ __kwonly__=None, dir_fd=DEFAULT_DIR_FD):
"""open(path, flags, mode=0o777, *, dir_fd=None)
Open a file for low level IO. Returns a file handle (integer).
@@ -428,8 +428,8 @@
@unwrap_spec(
path=path_or_fd(allow_fd=True),
dir_fd=DirFD(rposix.HAVE_FSTATAT),
- follow_symlinks=kwonly(bool))
-def stat(space, path, dir_fd=DEFAULT_DIR_FD, follow_symlinks=True):
+ follow_symlinks=bool)
+def stat(space, path, __kwonly__, dir_fd=DEFAULT_DIR_FD, follow_symlinks=True):
"""stat(path, *, dir_fd=None, follow_symlinks=True) -> stat result
Perform a stat system call on the given path.
@@ -476,7 +476,7 @@
@unwrap_spec(
path=path_or_fd(allow_fd=False),
dir_fd=DirFD(rposix.HAVE_FSTATAT))
-def lstat(space, path, dir_fd=DEFAULT_DIR_FD):
+def lstat(space, path, __kwonly__, dir_fd=DEFAULT_DIR_FD):
"""lstat(path, *, dir_fd=None) -> stat result
Like stat(), but do not follow symbolic links.
@@ -551,9 +551,9 @@
raise wrap_oserror(space, e)
@unwrap_spec(mode=c_int,
- dir_fd=DirFD(rposix.HAVE_FACCESSAT), effective_ids=kwonly(bool),
- follow_symlinks=kwonly(bool))
-def access(space, w_path, mode,
+ dir_fd=DirFD(rposix.HAVE_FACCESSAT), effective_ids=bool,
+ follow_symlinks=bool)
+def access(space, w_path, mode, __kwonly__,
dir_fd=DEFAULT_DIR_FD, effective_ids=False, follow_symlinks=True):
"""\
access(path, mode, *, dir_fd=None, effective_ids=False, follow_symlinks=True)
@@ -626,7 +626,7 @@
return space.wrap(rc)
@unwrap_spec(dir_fd=DirFD(rposix.HAVE_UNLINKAT))
-def unlink(space, w_path, dir_fd=DEFAULT_DIR_FD):
+def unlink(space, w_path, __kwonly__, dir_fd=DEFAULT_DIR_FD):
"""unlink(path, *, dir_fd=None)
Remove a file (same as remove()).
@@ -645,7 +645,7 @@
raise wrap_oserror2(space, e, w_path)
@unwrap_spec(dir_fd=DirFD(rposix.HAVE_UNLINKAT))
-def remove(space, w_path, dir_fd=DEFAULT_DIR_FD):
+def remove(space, w_path, __kwonly__, dir_fd=DEFAULT_DIR_FD):
"""remove(path, *, dir_fd=None)
Remove a file (same as unlink()).
@@ -710,7 +710,7 @@
raise wrap_oserror2(space, e, w_path)
@unwrap_spec(mode=c_int, dir_fd=DirFD(rposix.HAVE_MKDIRAT))
-def mkdir(space, w_path, mode=0o777, dir_fd=DEFAULT_DIR_FD):
+def mkdir(space, w_path, mode=0o777, __kwonly__=None, dir_fd=DEFAULT_DIR_FD):
"""mkdir(path, mode=0o777, *, dir_fd=None)
Create a directory.
@@ -731,7 +731,7 @@
raise wrap_oserror2(space, e, w_path)
@unwrap_spec(dir_fd=DirFD(rposix.HAVE_UNLINKAT))
-def rmdir(space, w_path, dir_fd=DEFAULT_DIR_FD):
+def rmdir(space, w_path, __kwonly__, dir_fd=DEFAULT_DIR_FD):
"""rmdir(path, *, dir_fd=None)
Remove a directory.
@@ -898,8 +898,9 @@
return space.newtuple([space.wrap(fd1), space.wrap(fd2)])
@unwrap_spec(mode=c_int, dir_fd=DirFD(rposix.HAVE_FCHMODAT),
- follow_symlinks=kwonly(bool))
-def chmod(space, w_path, mode, dir_fd=DEFAULT_DIR_FD, follow_symlinks=True):
+ follow_symlinks=bool)
+def chmod(space, w_path, mode, __kwonly__,
+ dir_fd=DEFAULT_DIR_FD, follow_symlinks=True):
"""chmod(path, mode, *, dir_fd=None, follow_symlinks=True)
Change the access permissions of a file.
@@ -965,7 +966,7 @@
@unwrap_spec(src_dir_fd=DirFD(rposix.HAVE_RENAMEAT),
dst_dir_fd=DirFD(rposix.HAVE_RENAMEAT))
-def rename(space, w_src, w_dst,
+def rename(space, w_src, w_dst, __kwonly__,
src_dir_fd=DEFAULT_DIR_FD, dst_dir_fd=DEFAULT_DIR_FD):
"""rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)
@@ -989,7 +990,7 @@
@unwrap_spec(src_dir_fd=DirFD(rposix.HAVE_RENAMEAT),
dst_dir_fd=DirFD(rposix.HAVE_RENAMEAT))
-def replace(space, w_src, w_dst,
+def replace(space, w_src, w_dst, __kwonly__,
src_dir_fd=DEFAULT_DIR_FD, dst_dir_fd=DEFAULT_DIR_FD):
"""replace(src, dst, *, src_dir_fd=None, dst_dir_fd=None)
@@ -1012,7 +1013,7 @@
raise wrap_oserror(space, e)
@unwrap_spec(mode=c_int, dir_fd=DirFD(rposix.HAVE_MKFIFOAT))
-def mkfifo(space, w_path, mode=0666, dir_fd=DEFAULT_DIR_FD):
+def mkfifo(space, w_path, mode=0666, __kwonly__=None, dir_fd=DEFAULT_DIR_FD):
"""mkfifo(path, mode=0o666, *, dir_fd=None)
Create a FIFO (a POSIX named pipe).
@@ -1031,7 +1032,8 @@
raise wrap_oserror2(space, e, w_path)
@unwrap_spec(mode=c_int, device=c_int, dir_fd=DirFD(rposix.HAVE_MKNODAT))
-def mknod(space, w_filename, mode=0600, device=0, dir_fd=DEFAULT_DIR_FD):
+def mknod(space, w_filename, mode=0600, device=0,
+ __kwonly__=None, dir_fd=DEFAULT_DIR_FD):
"""mknod(filename, mode=0o600, device=0, *, dir_fd=None)
Create a filesystem node (file, device special file or named pipe)
@@ -1093,9 +1095,9 @@
@unwrap_spec(
src='fsencode', dst='fsencode',
src_dir_fd=DirFD(rposix.HAVE_LINKAT), dst_dir_fd=DirFD(rposix.HAVE_LINKAT),
- follow_symlinks=kwonly(bool))
+ follow_symlinks=bool)
def link(
- space, src, dst,
+ space, src, dst, __kwonly__,
src_dir_fd=DEFAULT_DIR_FD, dst_dir_fd=DEFAULT_DIR_FD,
follow_symlinks=True):
"""\
@@ -1125,7 +1127,7 @@
@unwrap_spec(dir_fd=DirFD(rposix.HAVE_SYMLINKAT))
def symlink(space, w_src, w_dst, w_target_is_directory=None,
- dir_fd=DEFAULT_DIR_FD):
+ __kwonly__=None, dir_fd=DEFAULT_DIR_FD):
"""symlink(src, dst, target_is_directory=False, *, dir_fd=None)
Create a symbolic link pointing to src named dst.
@@ -1153,7 +1155,7 @@
@unwrap_spec(
path=path_or_fd(allow_fd=False),
dir_fd=DirFD(rposix.HAVE_READLINKAT))
-def readlink(space, path, dir_fd=DEFAULT_DIR_FD):
+def readlink(space, path, __kwonly__, dir_fd=DEFAULT_DIR_FD):
"""readlink(path, *, dir_fd=None) -> path
Return a string representing the path to which the symbolic link points.
@@ -1353,9 +1355,9 @@
@unwrap_spec(
path=path_or_fd(allow_fd=rposix.HAVE_FUTIMENS or rposix.HAVE_FUTIMES),
- w_times=WrappedDefault(None), w_ns=kwonly(WrappedDefault(None)),
- dir_fd=DirFD(rposix.HAVE_UTIMENSAT), follow_symlinks=kwonly(bool))
-def utime(space, path, w_times, w_ns, dir_fd=DEFAULT_DIR_FD,
+ w_times=WrappedDefault(None), w_ns=WrappedDefault(None),
+ dir_fd=DirFD(rposix.HAVE_UTIMENSAT), follow_symlinks=bool)
+def utime(space, path, w_times, __kwonly__, w_ns, dir_fd=DEFAULT_DIR_FD,
follow_symlinks=True):
"""utime(path, times=None, *, ns=None, dir_fd=None, follow_symlinks=True)
@@ -1889,8 +1891,9 @@
@unwrap_spec(
uid=c_uid_t, gid=c_gid_t,
- dir_fd=DirFD(rposix.HAVE_FCHOWNAT), follow_symlinks=kwonly(bool))
-def chown(space, w_path, uid, gid, dir_fd=DEFAULT_DIR_FD,
follow_symlinks=True):
+ dir_fd=DirFD(rposix.HAVE_FCHOWNAT), follow_symlinks=bool)
+def chown(space, w_path, uid, gid, __kwonly__,
+ dir_fd=DEFAULT_DIR_FD, follow_symlinks=True):
"""chown(path, uid, gid, *, dir_fd=None, follow_symlinks=True)
Change the owner and group id of path to the numeric uid and gid.
diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -337,7 +337,7 @@
space = self.space
w_dict = obj.getdict(space)
try:
- space.delitem(w_dict, space.wrap(name))
+ space.delitem(w_dict, space.wrap(name.decode('utf-8')))
except OperationError as ex:
if not ex.match(space, space.w_KeyError):
raise
@@ -402,7 +402,7 @@
def materialize_r_dict(self, space, obj, dict_w):
new_obj = self.back.materialize_r_dict(space, obj, dict_w)
if self.index == DICT:
- w_attr = space.wrap(self.name)
+ w_attr = space.wrap(self.name.decode('utf-8'))
dict_w[w_attr] = obj._mapdict_read_storage(self.storageindex)
else:
self._copy_attr(obj, new_obj)
@@ -810,7 +810,7 @@
raise KeyError
key = curr.name
w_value = self.getitem_str(w_dict, key)
- w_key = self.space.wrap(key)
+ w_key = self.space.wrap(key.decode('utf-8'))
self.delitem(w_dict, w_key)
return (w_key, w_value)
@@ -845,7 +845,7 @@
if curr_map:
self.curr_map = curr_map.back
attr = curr_map.name
- w_attr = self.space.wrap(attr)
+ w_attr = self.space.wrap(attr.decode('utf-8'))
return w_attr
return None
@@ -886,7 +886,7 @@
if curr_map:
self.curr_map = curr_map.back
attr = curr_map.name
- w_attr = self.space.wrap(attr)
+ w_attr = self.space.wrap(attr.decode('utf-8'))
return w_attr, self.w_obj.getdictvalue(self.space, attr)
return None, None
diff --git a/pypy/objspace/std/test/test_mapdict.py
b/pypy/objspace/std/test/test_mapdict.py
--- a/pypy/objspace/std/test/test_mapdict.py
+++ b/pypy/objspace/std/test/test_mapdict.py
@@ -1,3 +1,5 @@
+# -*- coding: utf-8 -*-
+
from pypy.objspace.std.test.test_dictmultiobject import FakeSpace, W_DictObject
from pypy.objspace.std.mapdict import *
@@ -873,6 +875,15 @@
d = x.__dict__
assert list(__pypy__.reversed_dict(d)) == list(d.keys())[::-1]
+ def test_nonascii_argname(self):
+ """
+ class X:
+ pass
+ x = X()
+ x.日本 = 3
+ assert x.日本 == 3
+ assert x.__dict__ == {'日本': 3}
+ """
class AppTestWithMapDictAndCounters(object):
spaceconfig = {"objspace.std.withmethodcachecounter": True}
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit