[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pypy-svn
Subject:    [pypy-commit] pypy unicode-utf8: improve exception text compliance, fix for non-ascii attribute
From:       mattip <pypy.commits () gmail ! com>
Date:       2018-12-24 15:28:21
Message-ID: 5c20fb15.1c69fb81.56fea.95fe () mx ! google ! com
[Download RAW message or body]

Author: Matti Picus <matti.picus@gmail.com>
Branch: unicode-utf8
Changeset: r95525:5766e9675e3e
Date: 2018-12-24 14:03 +0200
http://bitbucket.org/pypy/pypy/changeset/5766e9675e3e/

Log:	improve exception text compliance, fix for non-ascii attribute

diff --git a/pypy/module/__builtin__/operation.py b/pypy/module/__builtin__/operation.py
--- a/pypy/module/__builtin__/operation.py
+++ b/pypy/module/__builtin__/operation.py
@@ -36,29 +36,33 @@
     return space.len(w_obj)
 
 
-def checkattrname(space, w_name):
+def checkattrname(space, w_name, msg):
     # This is a check to ensure that getattr/setattr/delattr only pass a
-    # string to the rest of the code.  XXX not entirely sure if these three
+    # ascii string to the rest of the code.  XXX not entirely sure if these
     # functions are the only way for non-string objects to reach
     # space.{get,set,del}attr()...
-    # Note that if w_name is already an exact string it must be returned
-    # unmodified (and not e.g. unwrapped-rewrapped).
-    if not space.is_w(space.type(w_name), space.w_text):
-        name = space.text_w(w_name)    # typecheck
-        w_name = space.newtext(name)     # rewrap as a real string
+    # Note that if w_name is already an exact string it must be ascii encoded
+    if not space.isinstance_w(w_name, space.w_text):
+        try:
+            name = space.text_w(w_name)    # typecheck
+        except Exception as e:
+            raise oefmt(space.w_TypeError,
+                 "%s(): attribute name must be string", msg)
+    if space.isinstance_w(w_name, space.w_unicode):
+        w_name = space.call_method(w_name, 'encode', space.newtext('ascii'))
     return w_name
 
 def delattr(space, w_object, w_name):
     """Delete a named attribute on an object.
 delattr(x, 'y') is equivalent to ``del x.y''."""
-    w_name = checkattrname(space, w_name)
+    w_name = checkattrname(space, w_name, 'delattr')
     space.delattr(w_object, w_name)
     return space.w_None
 
 def getattr(space, w_object, w_name, w_defvalue=None):
     """Get a named attribute from an object.
 getattr(x, 'y') is equivalent to ``x.y''."""
-    w_name = checkattrname(space, w_name)
+    w_name = checkattrname(space, w_name, 'getattr')
     try:
         return space.getattr(w_object, w_name)
     except OperationError as e:
@@ -70,7 +74,7 @@
 def hasattr(space, w_object, w_name):
     """Return whether the object has an attribute with the given name.
     (This is done by calling getattr(object, name) and catching exceptions.)"""
-    w_name = checkattrname(space, w_name)
+    w_name = checkattrname(space, w_name, 'hasattr')
     if space.findattr(w_object, w_name) is not None:
         return space.w_True
     else:
@@ -216,7 +220,7 @@
 def setattr(space, w_object, w_name, w_val):
     """Store a named attribute into an object.
 setattr(x, 'y', z) is equivalent to ``x.y = z''."""
-    w_name = checkattrname(space, w_name)
+    w_name = checkattrname(space, w_name, 'setattr')
     space.setattr(w_object, w_name, w_val)
     return space.w_None
 
diff --git a/pypy/module/__builtin__/test/test_builtin.py b/pypy/module/__builtin__/test/test_builtin.py
--- a/pypy/module/__builtin__/test/test_builtin.py
+++ b/pypy/module/__builtin__/test/test_builtin.py
@@ -568,9 +568,9 @@
         assert hasattr(x, 'bar') is False
         assert hasattr(x, 'abc') is False    # CPython compliance
         assert hasattr(x, 'bac') is False    # CPython compliance
-        raises(TypeError, hasattr, x, None)
-        raises(TypeError, hasattr, x, 42)
-        raises(UnicodeError, hasattr, x, u'\u5678')  # cannot encode attr name
+        exc = raises(TypeError, hasattr, x, None)
+        assert str(exc.value) == 'hasattr(): attribute name must be string'
+        raises(UnicodeError, hasattr, x, u'\u5678')  # 'ascii' codec can't encode
 
     def test_execfile_args(self):
         execfile(self.nullbytes) # works
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic