Author: Amaury Forgeot d'Arc <[email protected]>
Branch: py3k
Changeset: r59114:c6fd4a0b49cd
Date: 2012-11-28 23:35 +0100
http://bitbucket.org/pypy/pypy/changeset/c6fd4a0b49cd/
Log: When attribute string cannot be encoded to utf8, raise
AttributeError, not UnicodeError.
diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -49,25 +49,35 @@
return w_iter
list_iter._annspecialcase_ = 'specialize:memo'
-def raiseattrerror(space, w_obj, name, w_descr=None):
+def raiseattrerror(space, w_obj, w_name, w_descr=None):
w_type = space.type(w_obj)
typename = w_type.getname(space)
+ # space.repr always returns an encodable string.
+ name = space.str_w(space.repr(w_name))
if w_descr is None:
raise operationerrfmt(space.w_AttributeError,
- "'%s' object has no attribute '%s'",
+ "'%s' object has no attribute %s",
typename, name)
else:
raise operationerrfmt(space.w_AttributeError,
- "'%s' object attribute '%s' is read-only",
+ "'%s' object attribute %s is read-only",
typename, name)
+def get_attribute_name(space, w_obj, w_name):
+ try:
+ return space.str_w(w_name)
+ except OperationError as e:
+ if e.match(space, space.w_UnicodeEncodeError):
+ raiseattrerror(space, w_obj, w_name)
+ raise
+
def _same_class_w(space, w_obj1, w_obj2, w_typ1, w_typ2):
return space.is_w(w_typ1, w_typ2)
class Object(object):
def descr__getattribute__(space, w_obj, w_name):
- name = space.str_w(w_name)
+ name = get_attribute_name(space, w_obj, w_name)
w_descr = space.lookup(w_obj, name)
if w_descr is not None:
if space.is_data_descr(w_descr):
@@ -83,10 +93,10 @@
return w_value
if w_descr is not None:
return space.get(w_descr, w_obj)
- raiseattrerror(space, w_obj, name)
+ raiseattrerror(space, w_obj, w_name)
def descr__setattr__(space, w_obj, w_name, w_value):
- name = space.str_w(w_name)
+ name = get_attribute_name(space, w_obj, w_name)
w_descr = space.lookup(w_obj, name)
if w_descr is not None:
if space.is_data_descr(w_descr):
@@ -94,10 +104,10 @@
return
if w_obj.setdictvalue(space, name, w_value):
return
- raiseattrerror(space, w_obj, name, w_descr)
+ raiseattrerror(space, w_obj, w_name, w_descr)
def descr__delattr__(space, w_obj, w_name):
- name = space.str_w(w_name)
+ name = get_attribute_name(space, w_obj, w_name)
w_descr = space.lookup(w_obj, name)
if w_descr is not None:
if space.is_data_descr(w_descr):
@@ -105,7 +115,7 @@
return
if w_obj.deldictvalue(space, name):
return
- raiseattrerror(space, w_obj, name, w_descr)
+ raiseattrerror(space, w_obj, w_name, w_descr)
def descr__init__(space, w_obj, __args__):
pass
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -6,7 +6,8 @@
from pypy.interpreter.typedef import get_unique_interplevel_subclass
from pypy.objspace.std import (builtinshortcut, stdtypedef, frame, model,
transparent, callmethod, proxyobject)
-from pypy.objspace.descroperation import DescrOperation, raiseattrerror
+from pypy.objspace.descroperation import (
+ DescrOperation, get_attribute_name, raiseattrerror)
from pypy.rlib.objectmodel import instantiate, r_dict, specialize,
is_annotation_constant
from pypy.rlib.debug import make_sure_not_resized
from pypy.rlib.rarithmetic import base_int, widen, maxint, is_valid_int
@@ -561,7 +562,7 @@
# fast path: XXX this is duplicating most of the logic
# from the default __getattribute__ and the getattr() method...
- name = self.str_w(w_name)
+ name = get_attribute_name(space, w_obj, w_name)
w_descr = w_type.lookup(name)
e = None
if w_descr is not None:
@@ -597,7 +598,7 @@
elif e is not None:
raise e
else:
- raiseattrerror(self, w_obj, name)
+ raiseattrerror(self, w_obj, w_name)
def finditem_str(self, w_obj, key):
""" Perform a getitem on w_obj with key (string). Returns found
diff --git a/pypy/objspace/test/test_descriptor.py
b/pypy/objspace/test/test_descriptor.py
--- a/pypy/objspace/test/test_descriptor.py
+++ b/pypy/objspace/test/test_descriptor.py
@@ -72,6 +72,14 @@
raises(AttributeError, delattr, x, 'v')
raises(AttributeError, X.v.__delete__, x)
+ def test_invalid_unicode_identifier(self):
+ class X(object):
+ pass
+ x = X()
+ raises(AttributeError, setattr, x, '\ud800', 1)
+ raises(AttributeError, getattr, x, '\ud800')
+ raises(AttributeError, delattr, x, '\ud800')
+
def test_special_methods_returning_strings(self):
class A(object):
seen = []
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit