Author: Armin Rigo <[email protected]>
Branch:
Changeset: r44931:2b8a496606be
Date: 2011-06-14 11:37 +0200
http://bitbucket.org/pypy/pypy/changeset/2b8a496606be/
Log: Review the unicode keyword argument change, and get rid of the extra
'lexical_keywords' field. Instead use the invariant that
'keyword_names_w' matches the tail of the 'keywords' list.
Also fixes topacked() and add a test about the error message.
diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -90,17 +90,18 @@
### Construction ###
def __init__(self, space, args_w, keywords=None, keywords_w=None,
- w_stararg=None, w_starstararg=None):
+ w_stararg=None, w_starstararg=None, keyword_names_w=None):
self.space = space
assert isinstance(args_w, list)
self.arguments_w = args_w
self.keywords = keywords
- self.lexical_keywords = len(keywords) if keywords is not None else 0
self.keywords_w = keywords_w
- self.keyword_names_w = None
+ self.keyword_names_w = keyword_names_w # matches the tail of .keywords
if keywords is not None:
assert keywords_w is not None
assert len(keywords_w) == len(keywords)
+ assert (keyword_names_w is None or
+ len(keyword_names_w) <= len(keywords))
make_sure_not_resized(self.keywords)
make_sure_not_resized(self.keywords_w)
@@ -134,7 +135,8 @@
def replace_arguments(self, args_w):
"Return a new Arguments with a args_w as positional arguments."
- return Arguments(self.space, args_w, self.keywords, self.keywords_w)
+ return Arguments(self.space, args_w, self.keywords, self.keywords_w,
+ keyword_names_w = self.keyword_names_w)
def prepend(self, w_firstarg):
"Return a new Arguments with a new argument inserted first."
@@ -184,7 +186,6 @@
raise
keys_w = space.unpackiterable(w_keys)
if keys_w:
- self.keyword_names_w = keys_w
self._do_combine_starstarargs_wrapped(keys_w, w_starstararg)
return True
else:
@@ -208,11 +209,12 @@
key = None
else:
raise
- if key is not None and self.keywords and key in self.keywords:
- raise operationerrfmt(self.space.w_TypeError,
- "got multiple values "
- "for keyword argument "
- "'%s'", key)
+ else:
+ if self.keywords and key in self.keywords:
+ raise operationerrfmt(self.space.w_TypeError,
+ "got multiple values "
+ "for keyword argument "
+ "'%s'", key)
keywords[i] = key
keywords_w[i] = space.getitem(w_starstararg, w_key)
i += 1
@@ -222,6 +224,7 @@
else:
self.keywords = self.keywords + keywords
self.keywords_w = self.keywords_w + keywords_w
+ self.keyword_names_w = keys_w
def fixedunpack(self, argcount):
"""The simplest argument parsing: get the 'argcount' arguments,
@@ -381,14 +384,18 @@
if has_kwarg:
w_kwds = self.space.newdict()
if num_remainingkwds:
+ #
+ limit = len(keywords)
+ if self.keyword_names_w is not None:
+ limit -= len(self.keyword_names_w)
for i in range(len(keywords)):
if not used_keywords[i]:
- if i < self.lexical_keywords:
+ if i < limit:
w_key = self.space.wrap(keywords[i])
else:
- j = i - self.lexical_keywords
- w_key = self.keyword_names_w[j]
+ w_key = self.keyword_names_w[i - limit]
self.space.setitem(w_kwds, w_key, keywords_w[i])
+ #
scope_w[co_argcount + has_vararg] = w_kwds
elif num_remainingkwds:
if co_argcount == 0:
@@ -396,8 +403,7 @@
co_argcount, has_vararg, has_kwarg,
defaults_w, missing)
raise ArgErrUnknownKwds(self.space, num_remainingkwds, keywords,
- self.keyword_names_w,
self.lexical_keywords,
- used_keywords)
+ used_keywords, self.keyword_names_w)
if missing:
raise ArgErrCount(avail, num_kwds,
@@ -456,9 +462,15 @@
w_args = space.newtuple(self.arguments_w)
w_kwds = space.newdict()
if self.keywords is not None:
+ limit = len(self.keywords)
+ if self.keyword_names_w is not None:
+ limit -= len(self.keyword_names_w)
for i in range(len(self.keywords)):
- space.setitem(w_kwds, space.wrap(self.keywords[i]),
- self.keywords_w[i])
+ if i < limit:
+ w_key = space.wrap(self.keywords[i])
+ else:
+ w_key = self.keyword_names_w[i - limit]
+ space.setitem(w_kwds, w_key, self.keywords_w[i])
return w_args, w_kwds
class ArgumentsForTranslation(Arguments):
@@ -679,26 +691,33 @@
class ArgErrUnknownKwds(ArgErr):
- def __init__(self, space, num_remainingkwds, keywords, keyword_names_w,
- lexical_keywords, used_keywords):
- self.kwd_name = ''
+ def __init__(self, space, num_remainingkwds, keywords, used_keywords,
+ keyword_names_w):
+ name = ''
self.num_kwds = num_remainingkwds
if num_remainingkwds == 1:
for i in range(len(keywords)):
if not used_keywords[i]:
- if i < lexical_keywords:
- name = keywords[i]
- else:
- w_name = keyword_names_w[i - lexical_keywords]
- if not space.isinstance_w(w_name, space.w_str):
- # We'll assume it's unicode. Encode it.
+ name = keywords[i]
+ if name is None:
+ # We'll assume it's unicode. Encode it.
+ # Careful, I *think* it should not be possible to
+ # get an IndexError here but you never know.
+ try:
+ if keyword_names_w is None:
+ raise IndexError
+ # note: negative-based indexing from the end
+ w_name = keyword_names_w[i - len(keywords)]
+ except IndexError:
+ name = '?'
+ else:
w_enc = space.wrap(space.sys.defaultencoding)
w_err = space.wrap("replace")
w_name = space.call_method(w_name, "encode", w_enc,
w_err)
- name = space.str_w(w_name)
- self.kwd_name = name
+ name = space.str_w(w_name)
break
+ self.kwd_name = name
def getmsg(self, fnname):
if self.num_kwds == 1:
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
@@ -542,14 +542,25 @@
def test_unknown_keywords(self):
space = DummySpace()
- err = ArgErrUnknownKwds(space, 1, ['a', 'b'], None, 2, [True, False])
+ err = ArgErrUnknownKwds(space, 1, ['a', 'b'], [True, False], None)
s = err.getmsg('foo')
assert s == "foo() got an unexpected keyword argument 'b'"
- err = ArgErrUnknownKwds(space, 2, ['a', 'b', 'c'], None, 3,
- [True, False, False])
+ err = ArgErrUnknownKwds(space, 2, ['a', 'b', 'c'],
+ [True, False, False], None)
s = err.getmsg('foo')
assert s == "foo() got 2 unexpected keyword arguments"
+ def test_unknown_unicode_keyword(self):
+ class DummySpaceUnicode(DummySpace):
+ class sys:
+ defaultencoding = 'utf-8'
+ space = DummySpaceUnicode()
+ err = ArgErrUnknownKwds(space, 1, ['a', None, 'b', 'c'],
+ [True, False, True, True],
+ [unichr(0x1234), u'b', u'c'])
+ s = err.getmsg('foo')
+ assert s == "foo() got an unexpected keyword argument '\xe1\x88\xb4'"
+
def test_multiple_values(self):
err = ArgErrMultipleValues('bla')
s = err.getmsg('foo')
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit