Author: Ronan Lamy <ronan.l...@gmail.com>
Branch: multiphase
Changeset: r92152:4babb75613f0
Date: 2017-08-14 20:53 +0200
http://bitbucket.org/pypy/pypy/changeset/4babb75613f0/

Log:    hg merge py3.5

diff --git a/lib-python/3/distutils/sysconfig_pypy.py 
b/lib-python/3/distutils/sysconfig_pypy.py
--- a/lib-python/3/distutils/sysconfig_pypy.py
+++ b/lib-python/3/distutils/sysconfig_pypy.py
@@ -81,6 +81,19 @@
     g['LIBDIR'] = os.path.join(sys.prefix, 'lib')
     g['VERSION'] = get_python_version()
 
+    if sys.platform[:6] == "darwin":
+        import platform
+        if platform.machine() == 'i386':
+            if platform.architecture()[0] == '32bit':
+                arch = 'i386'
+            else:
+                arch = 'x86_64'
+        else:
+            # just a guess
+            arch = platform.machine()
+        g['LDSHARED'] += ' -undefined dynamic_lookup'
+        g['CC'] += ' -arch %s' % (arch,)
+
     global _config_vars
     _config_vars = g
 
diff --git a/lib-python/3/test/test_pyexpat.py 
b/lib-python/3/test/test_pyexpat.py
--- a/lib-python/3/test/test_pyexpat.py
+++ b/lib-python/3/test/test_pyexpat.py
@@ -11,7 +11,7 @@
 from xml.parsers import expat
 from xml.parsers.expat import errors
 
-from test.support import sortdict
+from test.support import sortdict, impl_detail
 
 
 class SetAttributeTest(unittest.TestCase):
@@ -446,6 +446,7 @@
         self.assertEqual(os.path.basename(entry[0]), filename)
         self.assertEqual(entry[2], funcname)
 
+    @impl_detail("PyPy does not have pyexpat.c", pypy=False)
     def test_exception(self):
         parser = expat.ParserCreate()
         parser.StartElementHandler = self.StartElementHandler
diff --git a/lib_pypy/pyrepl/readline.py b/lib_pypy/pyrepl/readline.py
--- a/lib_pypy/pyrepl/readline.py
+++ b/lib_pypy/pyrepl/readline.py
@@ -297,10 +297,7 @@
         line = line.rstrip('\n')
         if isinstance(line, unicode):
             return line # on py3k
-        try:
-            return unicode(line, ENCODING)
-        except UnicodeDecodeError:   # bah, silently fall back...
-            return unicode(line, 'utf-8', 'replace')
+        return unicode(line, 'utf-8', 'replace')
 
     def get_history_length(self):
         return self.saved_history_length
@@ -317,7 +314,7 @@
         # history item: we use \r\n instead of just \n.  If the history
         # file is passed to GNU readline, the extra \r are just ignored.
         history = self.get_reader().history
-        f = open(os.path.expanduser(filename), 'r')
+        f = open(os.path.expanduser(filename), 'r', encoding='utf-8')
         buffer = []
         for line in f:
             if line.endswith('\r\n'):
@@ -334,15 +331,12 @@
     def write_history_file(self, filename='~/.history'):
         maxlength = self.saved_history_length
         history = self.get_reader().get_trimmed_history(maxlength)
-        f = open(os.path.expanduser(filename), 'w')
+        f = open(os.path.expanduser(filename), 'w', encoding='utf-8')
         for entry in history:
             # if we are on py3k, we don't need to encode strings before
             # writing it to a file
             if isinstance(entry, unicode) and sys.version_info < (3,):
-                try:
-                    entry = entry.encode(ENCODING)
-                except UnicodeEncodeError:   # bah, silently fall back...
-                    entry = entry.encode('utf-8')
+                entry = entry.encode('utf-8')
             entry = entry.replace('\n', '\r\n')   # multiline history support
             f.write(entry + '\n')
         f.close()
diff --git a/pypy/module/__builtin__/descriptor.py 
b/pypy/module/__builtin__/descriptor.py
--- a/pypy/module/__builtin__/descriptor.py
+++ b/pypy/module/__builtin__/descriptor.py
@@ -21,24 +21,31 @@
 
         if space.is_none(w_obj_or_type):
             w_type = None  # unbound super object
-            w_obj_or_type = space.w_None
+            w_obj_or_type = None
         else:
             w_type = _super_check(space, w_starttype, w_obj_or_type)
         self.w_starttype = w_starttype
         self.w_objtype = w_type
-        self.w_self = w_obj_or_type
+        self.w_self = w_obj_or_type      # may be None
 
     def descr_repr(self, space):
         if self.w_objtype is not None:
             objtype_name = u"<%s object>" % self.w_objtype.getname(space)
         else:
             objtype_name = u'NULL'
+        if self.w_starttype is not None:
+            starttype_name = self.w_starttype.getname(space)
+        else:
+            starttype_name = u'NULL'
         return space.newunicode(u"<super: <class '%s'>, %s>" % (
-            self.w_starttype.getname(space), objtype_name))
+            starttype_name, objtype_name))
 
     def get(self, space, w_obj, w_type=None):
-        if self.w_self is None or space.is_w(w_obj, space.w_None):
+        if self.w_self is not None or space.is_w(w_obj, space.w_None):
             return self
+        if self.w_starttype is None:
+            raise oefmt(space.w_TypeError,
+                "__get__(x) is invalid on an uninitialized instance of 
'super'")
         else:
             # if type(self) is W_Super:
             #     XXX write a fast path for this common case
@@ -50,6 +57,7 @@
         # only use a special logic for bound super objects and not for
         # getting the __class__ of the super object itself.
         if self.w_objtype is not None and name != '__class__':
+            assert self.w_starttype is not None
             w_value = space.lookup_in_type_starting_at(self.w_objtype,
                                                        self.w_starttype,
                                                        name)
@@ -59,10 +67,9 @@
                     return w_value
                 # Only pass 'obj' param if this is instance-mode super
                 # (see CPython sourceforge id #743627)
-                if self.w_self is self.w_objtype:
+                w_obj = self.w_self
+                if w_obj is None or w_obj is self.w_objtype:
                     w_obj = space.w_None
-                else:
-                    w_obj = self.w_self
                 return space.get_and_call_function(w_get, w_value,
                                                    w_obj, self.w_objtype)
         # fallback to object.__getattribute__()
@@ -160,7 +167,11 @@
     _immutable_fields_ = ["w_fget", "w_fset", "w_fdel"]
 
     def __init__(self, space):
-        pass
+        self.w_fget = space.w_None
+        self.w_fset = space.w_None
+        self.w_fdel = space.w_None
+        self.w_doc = space.w_None
+        self.getter_doc = False
 
     @unwrap_spec(w_fget=WrappedDefault(None),
                  w_fset=WrappedDefault(None),
diff --git a/pypy/module/__builtin__/test/test_descriptor.py 
b/pypy/module/__builtin__/test/test_descriptor.py
--- a/pypy/module/__builtin__/test/test_descriptor.py
+++ b/pypy/module/__builtin__/test/test_descriptor.py
@@ -333,6 +333,22 @@
         assert repr(A()).endswith('>!')
         assert repr(super(A, A())) == "<super: <class 'A'>, <A object>>"
 
+    def test_super_get_corner_case(self):
+        class A(object):
+            pass
+        s1 = super(A, A())
+        assert s1.__get__(42) is s1
+        assert s1.__get__(42, int) is s1
+        s2 = super(A)
+        assert s2.__get__(None, "anything") is s2
+        #
+        assert s1.__get__(None, "anything") is s1
+        raises(TypeError, s2.__get__, 42)
+        raises(TypeError, s2.__get__, 42, int)
+        a = A()
+        assert s2.__get__(a).__self__ is a
+        assert s1.__get__(a) is s1
+
     def test_property_docstring(self):
         assert property.__doc__.startswith('property')
 
@@ -520,3 +536,35 @@
                 super()
         raises(RuntimeError, X().f)
         """
+
+    def test_uninitialized_property(self):
+        p = property.__new__(property)
+        raises(AttributeError, p.__get__, 42)
+        raises(AttributeError, p.__set__, 42, None)
+        raises(AttributeError, p.__delete__, 42)
+        assert repr(p).startswith("<property object at ")
+        assert p.fget is p.fset is p.fdel is p.__doc__ is None
+        #
+        lst = []
+        p.deleter(lst.append).__delete__(42)
+        assert lst == [42]
+        #
+        lst = []
+        p.getter(lst.append).__get__(43)
+        assert lst == [43]
+        #
+        lst = []
+        p.setter(lambda x, y: lst.append((x, y))).__set__(44, 45)
+        assert lst == [(44, 45)]
+
+    def test_uninitialized_super(self):
+        s = super.__new__(super)
+        assert repr(s) == "<super: <class 'NULL'>, NULL>"
+        assert s.__thisclass__ is s.__self__ is s.__self_class__ is None
+        assert s.__get__(None, "anything") is s
+        raises(TypeError, s.__get__, 42)
+        raises(TypeError, s.__get__, int)
+        raises(TypeError, s.__get__, type(None))
+        raises(AttributeError, "s.abcde")
+        raises(AttributeError, "s.abcde = 42")
+        raises(AttributeError, "del s.abcde")
diff --git a/pypy/module/cpyext/src/modsupport.c 
b/pypy/module/cpyext/src/modsupport.c
--- a/pypy/module/cpyext/src/modsupport.c
+++ b/pypy/module/cpyext/src/modsupport.c
@@ -523,12 +523,10 @@
     return res;
 }
 
-/* returns -1 in case of error, 0 if a new key was added, 1 if the key
-   was already there (and replaced) */
-static int
-_PyModule_AddObject_NoConsumeRef(PyObject *m, const char *name, PyObject *o)
+int
+PyModule_AddObject(PyObject *m, const char *name, PyObject *o)
 {
-    PyObject *dict, *prev;
+    PyObject *dict;
     if (!PyModule_Check(m)) {
         PyErr_SetString(PyExc_TypeError,
                     "PyModule_AddObject() needs module as first arg");
@@ -548,49 +546,34 @@
                      PyModule_GetName(m));
         return -1;
     }
-    prev = PyDict_GetItemString(dict, name);
     if (PyDict_SetItemString(dict, name, o))
         return -1;
-    return prev != NULL;
-}
-
-int
-PyModule_AddObject(PyObject *m, const char *name, PyObject *o)
-{
-    int result = _PyModule_AddObject_NoConsumeRef(m, name, o);
-    /* XXX WORKAROUND for a common misusage of PyModule_AddObject:
-       for the common case of adding a new key, we don't consume a
-       reference, but instead just leak it away.  The issue is that
-       people generally don't realize that this function consumes a
-       reference, because on CPython the reference is still stored
-       on the dictionary. */
-    if (result != 0)
-        Py_DECREF(o);
-    return result < 0 ? -1 : 0;
+    Py_DECREF(o);
+    return 0;
 }
 
 int
 PyModule_AddIntConstant(PyObject *m, const char *name, long value)
 {
-    int result;
     PyObject *o = PyLong_FromLong(value);
     if (!o)
         return -1;
-    result = _PyModule_AddObject_NoConsumeRef(m, name, o);
+    if (PyModule_AddObject(m, name, o) == 0)
+        return 0;
     Py_DECREF(o);
-    return result < 0 ? -1 : 0;
+    return -1;
 }
 
 int
 PyModule_AddStringConstant(PyObject *m, const char *name, const char *value)
 {
-    int result;
     PyObject *o = PyUnicode_FromString(value);
     if (!o)
         return -1;
-    result = _PyModule_AddObject_NoConsumeRef(m, name, o);
+    if (PyModule_AddObject(m, name, o) == 0)
+        return 0;
     Py_DECREF(o);
-    return result < 0 ? -1 : 0;
+    return -1;
 }
 
 PyModuleDef*
diff --git a/pypy/module/cpyext/test/test_capsule.py 
b/pypy/module/cpyext/test/test_capsule.py
--- a/pypy/module/cpyext/test/test_capsule.py
+++ b/pypy/module/cpyext/test/test_capsule.py
@@ -12,9 +12,6 @@
                  if (PyErr_Occurred()) return NULL;
                  module = PyImport_ImportModule("foo");
                  PyModule_AddObject(module, "_ptr", capsule);
-                 #ifdef PYPY_VERSION
-                   Py_DECREF(capsule);  /* XXX <--- anti-workaround */
-                 #endif
                  Py_DECREF(module);
                  if (PyErr_Occurred()) return NULL;
                  Py_RETURN_NONE;
diff --git a/pypy/module/pyexpat/test/test_parser.py 
b/pypy/module/pyexpat/test/test_parser.py
--- a/pypy/module/pyexpat/test/test_parser.py
+++ b/pypy/module/pyexpat/test/test_parser.py
@@ -210,6 +210,30 @@
             p.ParseFile(fake_reader)
             assert fake_reader.read_count == 4
 
+
+    def test_exception(self):
+        """
+        lib-python/3/test_pyexpat.py:HandlerExceptionTest.test_exception port
+        without the fragile traceback inspection.
+        """
+        import pyexpat as expat
+
+        def StartElementHandler(name, attrs):
+            raise RuntimeError(name)
+
+        parser = expat.ParserCreate()
+        parser.StartElementHandler = StartElementHandler
+
+        try:
+            parser.Parse(b"<a><b><c/></b></a>", 1)
+            self.fail()
+        except RuntimeError as e:
+            assert e.args[0] == 'a', (
+                "Expected RuntimeError for element 'a', but" + \
+                " found %r" % e.args[0]
+            )
+
+
 class AppTestPyexpat2:
     spaceconfig = dict(usemodules=['_rawffi', 'pyexpat', 'itertools',
                                    '_socket', 'time', 'struct', 'binascii',
diff --git a/pypy/module/readline/test/test_readline.py 
b/pypy/module/readline/test/test_readline.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/readline/test/test_readline.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+
+class AppTestReadline:
+    spaceconfig = dict(usemodules={
+        'unicodedata', 'termios', 'select', 'signal', 'fcntl',
+        '_minimal_curses', 'faulthandler', '_socket', 'binascii',
+        '_posixsubprocess',
+    })
+
+    def test_nonascii_history(self):
+        import os, readline
+        TESTFN = "{}_{}_tmp".format("@test", os.getpid())
+
+        is_editline = readline.__doc__ and "libedit" in readline.__doc__
+
+        readline.clear_history()
+        try:
+            readline.add_history("entr&#233;e 1")
+        except UnicodeEncodeError as err:
+            skip("Locale cannot encode test data: " + format(err))
+        readline.add_history("entr&#233;e 2")
+        readline.replace_history_item(1, "entr&#233;e 22")
+        readline.write_history_file(TESTFN)
+        readline.clear_history()
+        readline.read_history_file(TESTFN)
+        if is_editline:
+            # An add_history() call seems to be required for get_history_
+            # item() to register items from the file
+            readline.add_history("dummy")
+        assert readline.get_history_item(1) ==  "entr&#233;e 1"
+        assert readline.get_history_item(2) == "entr&#233;e 22"
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to