[pypy-commit] pypy winconsoleio: merged heads

andrewjlawrence pypy.commits at gmail.com
Tue Sep 17 09:43:44 EDT 2019


Author: andrewjlawrence
Branch: winconsoleio
Changeset: r97516:4d02b4bab2af
Date: 2019-09-17 14:42 +0100
http://bitbucket.org/pypy/pypy/changeset/4d02b4bab2af/

Log:	merged heads

diff --git a/lib-python/3/test/test_timeit.py b/lib-python/3/test/test_timeit.py
--- a/lib-python/3/test/test_timeit.py
+++ b/lib-python/3/test/test_timeit.py
@@ -387,7 +387,8 @@
             num_loops, time_taken = self.autorange(callback)
         self.assertEqual(num_loops, 1000)
         self.assertEqual(time_taken, 1.0)
-        expected = ('10 0.010\n'
+        expected = ('1 0.001\n'
+                    '10 0.010\n'
                     '100 0.100\n'
                     '1000 1.000\n')
         self.assertEqual(s.getvalue(), expected)
diff --git a/lib-python/3/unittest/test/testmock/testhelpers.py b/lib-python/3/unittest/test/testmock/testhelpers.py
--- a/lib-python/3/unittest/test/testmock/testhelpers.py
+++ b/lib-python/3/unittest/test/testmock/testhelpers.py
@@ -2,6 +2,8 @@
 import types
 import unittest
 
+from test.support import cpython_only
+
 from unittest.mock import (
     call, _Call, create_autospec, MagicMock,
     Mock, ANY, _CallList, patch, PropertyMock
@@ -873,7 +875,7 @@
         # plain data descriptor
         check_data_descriptor(foo.desc)
 
-
+    @cpython_only # PyPy can easily extract a spec from a builtin function
     def test_autospec_on_bound_builtin_function(self):
         meth = types.MethodType(time.ctime, time.time())
         self.assertIsInstance(meth(), str)
diff --git a/pypy/interpreter/argument.py b/pypy/interpreter/argument.py
--- a/pypy/interpreter/argument.py
+++ b/pypy/interpreter/argument.py
@@ -2,13 +2,20 @@
 Arguments objects.
 """
 from rpython.rlib.debug import make_sure_not_resized
-from rpython.rlib.objectmodel import not_rpython
+from rpython.rlib.objectmodel import not_rpython, specialize
 from rpython.rlib import jit
 from rpython.rlib.objectmodel import enforceargs
 from rpython.rlib.rstring import StringBuilder
 
 from pypy.interpreter.error import OperationError, oefmt
 
+ at specialize.arg(1)
+def raise_type_error(space, fnname_parens, msg, *args):
+    if fnname_parens is None:
+        raise oefmt(space.w_TypeError, msg, *args)
+    msg = "%s " + msg
+    raise oefmt(space.w_TypeError, msg, fnname_parens, *args)
+
 
 class Arguments(object):
     """
@@ -21,11 +28,9 @@
     semantics are complex, but calls occur everywhere.
     """
 
-    ###  Construction  ###
-    #@enforceargs(keywords=[unicode])
     def __init__(self, space, args_w, keywords=None, keywords_w=None,
                  w_stararg=None, w_starstararg=None, keyword_names_w=None,
-                 methodcall=False):
+                 methodcall=False, fnname_parens=None):
         self.space = space
         assert isinstance(args_w, list)
         self.arguments_w = args_w
@@ -41,7 +46,7 @@
             make_sure_not_resized(self.keywords_w)
 
         make_sure_not_resized(self.arguments_w)
-        self._combine_wrapped(w_stararg, w_starstararg)
+        self._combine_wrapped(w_stararg, w_starstararg, fnname_parens)
         # a flag that specifies whether the JIT can unroll loops that operate
         # on the keywords
         self._jit_few_keywords = self.keywords is None or jit.isconstant(len(self.keywords))
@@ -79,14 +84,14 @@
         "Return a new Arguments with a new argument inserted first."
         return self.replace_arguments([w_firstarg] + self.arguments_w)
 
-    def _combine_wrapped(self, w_stararg, w_starstararg):
+    def _combine_wrapped(self, w_stararg, w_starstararg, fnname_parens=None):
         "unpack the *arg and **kwd into arguments_w and keywords_w"
         if w_stararg is not None:
-            self._combine_starargs_wrapped(w_stararg)
+            self._combine_starargs_wrapped(w_stararg, fnname_parens)
         if w_starstararg is not None:
-            self._combine_starstarargs_wrapped(w_starstararg)
+            self._combine_starstarargs_wrapped(w_starstararg, fnname_parens)
 
-    def _combine_starargs_wrapped(self, w_stararg):
+    def _combine_starargs_wrapped(self, w_stararg, fnname_parens=None):
         # unpack the * arguments
         space = self.space
         try:
@@ -94,13 +99,13 @@
         except OperationError as e:
             if (e.match(space, space.w_TypeError) and
                     not space.is_iterable(w_stararg)):
-                raise oefmt(space.w_TypeError,
+                raise_type_error(space, fnname_parens,
                             "argument after * must be an iterable, not %T",
                             w_stararg)
             raise
         self.arguments_w = self.arguments_w + args_w
 
-    def _combine_starstarargs_wrapped(self, w_starstararg):
+    def _combine_starstarargs_wrapped(self, w_starstararg, fnname_parens=None):
         # unpack the ** arguments
         space = self.space
         keywords, values_w = space.view_as_kwargs(w_starstararg)
@@ -110,7 +115,8 @@
                 self.keywords_w = values_w
             else:
                 _check_not_duplicate_kwargs(
-                    self.space, self.keywords, keywords, values_w)
+                    self.space, self.keywords, keywords, values_w,
+                    fnname_parens)
                 self.keywords = self.keywords + keywords
                 self.keywords_w = self.keywords_w + values_w
             return
@@ -123,7 +129,7 @@
                 w_keys = space.call_method(w_starstararg, "keys")
             except OperationError as e:
                 if e.match(space, space.w_AttributeError):
-                    raise oefmt(space.w_TypeError,
+                    raise_type_error(space, fnname_parens,
                                 "argument after ** must be a mapping, not %T",
                                 w_starstararg)
                 raise
@@ -132,7 +138,7 @@
         keywords = [None] * len(keys_w)
         _do_combine_starstarargs_wrapped(
             space, keys_w, w_starstararg, keywords, keywords_w, self.keywords,
-            is_dict)
+            is_dict, fnname_parens)
         self.keyword_names_w = keys_w
         if self.keywords is None:
             self.keywords = keywords
@@ -349,8 +355,8 @@
     def parse_obj(self, w_firstarg,
                   fnname, signature, defaults_w=None, w_kw_defs=None,
                   blindargs=0):
-        """Parse args and kwargs to initialize a frame
-        according to the signature of code object.
+        """Parse args and kwargs into a list according to the signature of a
+        code object.
         """
         try:
             return self._parse(w_firstarg, signature, defaults_w, w_kw_defs,
@@ -387,28 +393,28 @@
 # look at. They should not get a self arguments, which makes the amount of
 # arguments annoying :-(
 
- at jit.look_inside_iff(lambda space, existingkeywords, keywords, keywords_w:
+ at jit.look_inside_iff(lambda space, existingkeywords, keywords, keywords_w, fnname_parens:
         jit.isconstant(len(keywords) and
         jit.isconstant(existingkeywords)))
-def _check_not_duplicate_kwargs(space, existingkeywords, keywords, keywords_w):
+def _check_not_duplicate_kwargs(space, existingkeywords, keywords, keywords_w, fnname_parens):
     # looks quadratic, but the JIT should remove all of it nicely.
     # Also, all the lists should be small
     for key in keywords:
         for otherkey in existingkeywords:
             if otherkey == key:
-                raise oefmt(space.w_TypeError,
+                raise_type_error(space, fnname_parens,
                             "got multiple values for keyword argument '%s'",
                             key)
 
 def _do_combine_starstarargs_wrapped(space, keys_w, w_starstararg, keywords,
-        keywords_w, existingkeywords, is_dict):
+        keywords_w, existingkeywords, is_dict, fnname_parens):
     i = 0
     for w_key in keys_w:
         try:
             key = space.text_w(w_key)
         except OperationError as e:
             if e.match(space, space.w_TypeError):
-                raise oefmt(space.w_TypeError,
+                raise_type_error(space, fnname_parens,
                             "keywords must be strings, not '%T'",
                             w_key)
             if e.match(space, space.w_UnicodeEncodeError):
@@ -418,7 +424,7 @@
                 raise
         else:
             if existingkeywords and key in existingkeywords:
-                raise oefmt(space.w_TypeError,
+                raise_type_error(space, fnname_parens,
                             "got multiple values for keyword argument '%s'",
                             key)
         keywords[i] = key
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1180,7 +1180,7 @@
         if frame.get_is_being_profiled() and is_builtin_code(w_func):
             # XXX: this code is copied&pasted :-( from the slow path below
             # call_valuestack().
-            args = frame.make_arguments(nargs)
+            args = frame.make_arguments(nargs, w_function=w_func)
             return self.call_args_and_c_profile(frame, w_func, args)
 
         if not self.config.objspace.disable_call_speedhacks:
@@ -1197,7 +1197,7 @@
                         nargs, frame, methodcall=methodcall)
             # end of hack for performance
 
-        args = frame.make_arguments(nargs)
+        args = frame.make_arguments(nargs, w_function=w_func)
         return self.call_args(w_func, args)
 
     def call_args_and_c_profile(self, frame, w_func, args):
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -172,10 +172,10 @@
         elif fast_natural_arity == Code.PASSTHROUGHARGS1 and nargs >= 1:
             assert isinstance(code, gateway.BuiltinCodePassThroughArguments1)
             w_obj = frame.peekvalue(nargs-1)
-            args = frame.make_arguments(nargs-1)
+            args = frame.make_arguments(nargs-1, w_function=self)
             return code.funcrun_obj(self, w_obj, args)
 
-        args = frame.make_arguments(nargs, methodcall=methodcall)
+        args = frame.make_arguments(nargs, methodcall=methodcall, w_function=self)
         return self.call_args(args)
 
     @jit.unroll_safe
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -490,14 +490,32 @@
             depth -= 1
         self.valuestackdepth = finaldepth
 
-    def make_arguments(self, nargs, methodcall=False):
+    def _guess_function_name_parens(self, fnname=None, w_function=None):
+        """ Returns 'funcname()' from either a function name fnname or a
+        wrapped callable w_function. If it's not a function or a method, returns
+        'Classname object'"""
+        # CPython has a similar function, PyEval_GetFuncName
+        from pypy.interpreter.function import Function, Method
+        if fnname is not None:
+            return fnname + '()'
+        if w_function is None:
+            return None
+        if isinstance(w_function, Function):
+            return w_function.name + '()'
+        if isinstance(w_function, Method):
+            return self._guess_function_name_parens(None, w_function.w_function)
+        return w_function.getname(self.space) + ' object'
+
+    def make_arguments(self, nargs, methodcall=False, w_function=None, fnname=None):
+        fnname_parens = self._guess_function_name_parens(fnname, w_function)
         return Arguments(
-                self.space, self.peekvalues(nargs), methodcall=methodcall)
+                self.space, self.peekvalues(nargs), methodcall=methodcall, fnname_parens=fnname_parens)
 
-    def argument_factory(self, arguments, keywords, keywords_w, w_star, w_starstar, methodcall=False):
+    def argument_factory(self, arguments, keywords, keywords_w, w_star, w_starstar, methodcall=False, w_function=None, fnname=None):
+        fnname_parens = self._guess_function_name_parens(fnname, w_function)
         return Arguments(
                 self.space, arguments, keywords, keywords_w, w_star,
-                w_starstar, methodcall=methodcall)
+                w_starstar, methodcall=methodcall, fnname_parens=fnname_parens)
 
     def hide(self):
         return self.pycode.hidden_applevel
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1307,9 +1307,9 @@
         else:
             w_star = None
         arguments = self.popvalues(n_arguments)
+        w_function  = self.popvalue()
         args = self.argument_factory(arguments, keywords, keywords_w, w_star,
-                                     w_starstar)
-        w_function  = self.popvalue()
+                                     w_starstar, w_function=w_function)
         if self.get_is_being_profiled() and function.is_builtin_code(w_function):
             w_result = self.space.call_args_and_c_profile(self, w_function,
                                                           args)
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
@@ -1,5 +1,6 @@
 # -*- coding: utf-8 -*-
 import py
+import pytest
 from pypy.interpreter.argument import (Arguments, ArgErr, ArgErrUnknownKwds,
         ArgErrMultipleValues, ArgErrMissing, ArgErrTooMany, ArgErrTooManyMethod)
 from pypy.interpreter.signature import Signature
@@ -138,6 +139,7 @@
         class Type:
             def getname(self, space):
                 return type(obj).__name__
+            name = type(obj).__name__
         return Type()
 
 
@@ -332,15 +334,17 @@
 
     def test_duplicate_kwds(self):
         space = DummySpace()
-        excinfo = py.test.raises(OperationError, Arguments, space, [], ["a"],
-                                 [1], w_starstararg={"a": 2})
+        with pytest.raises(OperationError) as excinfo:
+            Arguments(space, [], ["a"], [1], w_starstararg={"a": 2}, fnname_parens="foo()")
         assert excinfo.value.w_type is TypeError
+        assert excinfo.value.get_w_value(space) == "foo() got multiple values for keyword argument 'a'"
 
     def test_starstararg_wrong_type(self):
         space = DummySpace()
-        excinfo = py.test.raises(OperationError, Arguments, space, [], ["a"],
-                                 [1], w_starstararg="hello")
+        with pytest.raises(OperationError) as excinfo:
+            Arguments(space, [], ["a"], [1], w_starstararg="hello", fnname_parens="bar()")
         assert excinfo.value.w_type is TypeError
+        assert excinfo.value.get_w_value(space) == "bar() argument after ** must be a mapping, not str"
 
     def test_unwrap_error(self):
         space = DummySpace()
@@ -353,12 +357,12 @@
             return bytes(w, 'utf-8')
         space.utf8_w = utf8_w
         space.text_w = utf8_w
-        excinfo = py.test.raises(OperationError, Arguments, space, [],
-                                 ["a"], [1], w_starstararg={None: 1})
+        with py.test.raises(OperationError) as excinfo:
+            Arguments(space, [], ["a"], [1], w_starstararg={None: 1}, fnname_parens="f1()")
         assert excinfo.value.w_type is TypeError
         assert excinfo.value._w_value is None
-        excinfo = py.test.raises(OperationError, Arguments, space, [],
-                                 ["a"], [1], w_starstararg={valuedummy: 1})
+        with py.test.raises(OperationError) as excinfo:
+            Arguments(space, [], ["a"], [1], w_starstararg={valuedummy: 1}, fnname_parens="f2()")
         assert excinfo.value.w_type is ValueError
         assert excinfo.value._w_value is None
 
@@ -435,9 +439,9 @@
             raise FakeArgErr()
         args._match_signature = _match_signature
 
-
-        excinfo = py.test.raises(OperationError, args.parse_obj, "obj", "foo",
-                       Signature(["a", "b"], None, None))
+        with pytest.raises(OperationError) as excinfo:
+            args.parse_obj("obj", "foo",
+                           Signature(["a", "b"], None, None))
         assert excinfo.value.w_type is TypeError
         assert excinfo.value.get_w_value(space) == "foo() msg"
 
@@ -491,9 +495,9 @@
         args._match_signature = _match_signature
 
 
-        excinfo = py.test.raises(OperationError, args.parse_into_scope,
-                                 "obj", [None, None], "foo",
-                                 Signature(["a", "b"], None, None))
+        with pytest.raises(OperationError) as excinfo:
+            args.parse_into_scope("obj", [None, None], "foo",
+                                  Signature(["a", "b"], None, None))
         assert excinfo.value.w_type is TypeError
         assert excinfo.value.get_w_value(space) == "foo() msg"
 
@@ -568,9 +572,17 @@
             l = [None, None, None]
             args._match_signature(None, l, Signature(["a", "b"], None, "**"))
             assert l == [1, 2, {'c': 3}]
-        excinfo = py.test.raises(OperationError, Arguments, space, [], ["a"],
-                                 [1], w_starstararg=kwargs(["a"], [2]))
+        with pytest.raises(OperationError) as excinfo:
+            Arguments(space, [], ["a"],
+                      [1], w_starstararg=kwargs(["a"], [2]))
         assert excinfo.value.w_type is TypeError
+        assert excinfo.value.get_w_value(space) == "got multiple values for keyword argument 'a'"
+
+        with pytest.raises(OperationError) as excinfo:
+            Arguments(space, [], ["a"],
+                      [1], w_starstararg=kwargs(["a"], [2]), fnname_parens="foo()")
+        assert excinfo.value.w_type is TypeError
+        assert excinfo.value.get_w_value(space) == "foo() got multiple values for keyword argument 'a'"
 
 
 
@@ -671,20 +683,14 @@
 
     def test_bad_type_for_star(self):
         space = self.space
-        try:
-            Arguments(space, [], w_stararg=space.wrap(42))
-        except OperationError as e:
-            msg = space.text_w(space.str(e.get_w_value(space)))
-            assert msg == "argument after * must be an iterable, not int"
-        else:
-            assert 0, "did not raise"
-        try:
-            Arguments(space, [], w_starstararg=space.wrap(42))
-        except OperationError as e:
-            msg = space.text_w(space.str(e.get_w_value(space)))
-            assert msg == "argument after ** must be a mapping, not int"
-        else:
-            assert 0, "did not raise"
+        with pytest.raises(OperationError) as excinfo:
+            Arguments(space, [], w_stararg=space.wrap(42), fnname_parens="f1()")
+        msg = space.text_w(excinfo.value.get_w_value(space))
+        assert msg == "f1() argument after * must be an iterable, not int"
+        with pytest.raises(OperationError) as excinfo:
+            Arguments(space, [], w_starstararg=space.wrap(42), fnname_parens="f2()")
+        msg = space.text_w(excinfo.value.get_w_value(space))
+        assert msg == "f2() argument after ** must be a mapping, not int"
 
     def test_dont_count_default_arguments(self):
         space = self.space
@@ -889,7 +895,7 @@
             pass
         e = raises(TypeError, "f(*42)")
         assert str(e.value).endswith(
-            "argument after * must be an iterable, not int")
+            "f() argument after * must be an iterable, not int")
         e = raises(TypeError, "f(*X())")
         assert str(e.value) == "myerror"
 
@@ -904,8 +910,10 @@
         def f(x, y):
             pass
         e = raises(TypeError, "f(y=2, **{3: 5}, x=6)")
-        assert "keywords must be strings" in str(e.value)
+        assert "f() keywords must be strings" in str(e.value)
         e = raises(TypeError, "f(y=2, **{'x': 5}, x=6)")
+        # CPython figures out the name here, by peeking around in the stack in
+        # BUILD_MAP_UNPACK_WITH_CALL. we don't, too messy
         assert "got multiple values for keyword argument 'x'" in str(e.value)
 
     def test_dict_subclass_with_weird_getitem(self):
diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py
--- a/pypy/module/__builtin__/functional.py
+++ b/pypy/module/__builtin__/functional.py
@@ -203,20 +203,24 @@
                     implementation_of)
 
 def max(space, __args__):
-    """max(iterable[, key=func]) -> value
-    max(a, b, c, ...[, key=func]) -> value
+    """max(iterable, *[, default=obj, key=func]) -> value
+max(arg1, arg2, *args, *[, key=func]) -> value
 
-    With a single iterable argument, return its largest item.
-    With two or more arguments, return the largest argument.
+With a single iterable argument, return its biggest item. The
+default keyword-only argument specifies an object to return if
+the provided iterable is empty.
+With two or more arguments, return the largest argument.
     """
     return min_max(space, __args__, "max")
 
 def min(space, __args__):
-    """min(iterable[, key=func]) -> value
-    min(a, b, c, ...[, key=func]) -> value
+    """min(iterable, *[, default=obj, key=func]) -> value
+min(arg1, arg2, *args, *[, key=func]) -> value
 
-    With a single iterable argument, return its smallest item.
-    With two or more arguments, return the smallest argument.
+With a single iterable argument, return its smallest item. The
+default keyword-only argument specifies an object to return if
+the provided iterable is empty.
+With two or more arguments, return the smallest argument.
     """
     return min_max(space, __args__, "min")
 
diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -245,7 +245,11 @@
     except OSError as e:
         raise wrap_oserror(space, e)
 
- at unwrap_spec(name='fsencode_or_none')
+if _MS_WINDOWS:
+    name_spec = 'fsencode'
+else:
+    name_spec = 'fsencode_or_none'
+ at unwrap_spec(name=name_spec)
 def descr_new_cdll(space, w_type, name):
     cdll = open_cdll(space, name)
     return W_CDLL(space, name, cdll)
diff --git a/pypy/module/_rawffi/test/test__rawffi.py b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -262,14 +262,17 @@
             raise AssertionError("did not fail??")
 
     def test_libload_None(self):
-        if self.iswin32:
-            skip("unix specific")
         import _rawffi
         # this should return *all* loaded libs, dlopen(NULL)
-        dll = _rawffi.CDLL(None)
-        func = dll.ptr('rand', [], 'i')
-        res = func()
-        assert res[0] != 0
+        try:
+            dll = _rawffi.CDLL(None)
+        except TypeError:
+            if not self.iswin32:
+                raise
+        else:
+            func = dll.ptr('rand', [], 'i')
+            res = func()
+            assert res[0] != 0
 
     def test_libc_load(self):
         import _rawffi
diff --git a/pypy/module/select/interp_select.py b/pypy/module/select/interp_select.py
--- a/pypy/module/select/interp_select.py
+++ b/pypy/module/select/interp_select.py
@@ -30,11 +30,23 @@
 
     @unwrap_spec(events="c_ushort")
     def register(self, space, w_fd, events=defaultevents):
+        """
+        Register a file descriptor with the polling object.
+        fd -- either an integer, or an object with a fileno() method returning an
+              int.
+        events -- an optional bitmask describing the type of events to check for
+        """
         fd = space.c_filedescriptor_w(w_fd)
         self.fddict[fd] = events
 
     @unwrap_spec(events="c_ushort")
     def modify(self, space, w_fd, events):
+        """
+        Modify an already registered file descriptor.
+        fd -- either an integer, or an object with a fileno() method returning an
+          int.
+        events -- an optional bitmask describing the type of events to check for
+        """
         fd = space.c_filedescriptor_w(w_fd)
         if fd not in self.fddict:
             raise wrap_oserror(space, OSError(errno.ENOENT, "poll.modify"),
@@ -42,6 +54,9 @@
         self.fddict[fd] = events
 
     def unregister(self, space, w_fd):
+        """
+        Remove a file descriptor being tracked by the polling object.
+        """
         fd = space.c_filedescriptor_w(w_fd)
         try:
             del self.fddict[fd]
@@ -50,21 +65,24 @@
 
     @unwrap_spec(w_timeout=WrappedDefault(None))
     def poll(self, space, w_timeout):
-        """WARNING: the timeout parameter is in **milliseconds**!"""
+        """
+        Polls the set of registered file descriptors, returning a list containing
+        any descriptors that have events or errors to report.
+
+        the timeout parameter is in milliseconds"""
         if space.is_w(w_timeout, space.w_None):
             timeout = -1
             end_time = 0
+        elif space.isinstance_w(w_timeout, space.w_float) or space.isinstance_w(w_timeout, space.w_int):
+            if space.is_true(space.lt(w_timeout, space.newint(0))):
+                timeout = -1
+                end_time = 0
+            else:
+                timeout = space.c_int_w(space.int(w_timeout))
+                end_time = timeutils.monotonic(space) + timeout * 0.001
         else:
-            # we want to be compatible with cpython and also accept things
-            # that can be casted to integer (I think)
-            try:
-                # compute the integer
-                w_timeout = space.int(w_timeout)
-            except OperationError:
-                raise oefmt(space.w_TypeError,
-                            "timeout must be an integer or None")
-            timeout = space.c_int_w(w_timeout)
-            end_time = timeutils.monotonic(space) + timeout * 0.001
+            raise oefmt(space.w_TypeError,
+                        "timeout must be an integer or None")
 
         if self.running:
             raise oefmt(space.w_RuntimeError, "concurrent poll() invocation")
diff --git a/pypy/module/select/test/test_select.py b/pypy/module/select/test/test_select.py
--- a/pypy/module/select/test/test_select.py
+++ b/pypy/module/select/test/test_select.py
@@ -217,9 +217,25 @@
         readend, writeend = self.getpair()
         try:
             class A(object):
-                def __int__(self):
+                def fileno(self):
                     return readend.fileno()
-            select.poll().poll(A()) # assert did not crash
+            poll = select.poll()
+            poll.register(A())
+
+            res = poll.poll(10) # timeout in ms
+            assert res == []
+            res = poll.poll(1.1) # check floats
+            assert res == []
+
+            writeend.send(b"foo!")
+            # can't easily test actual blocking, is done in lib-python tests
+            res = poll.poll()
+            assert res == [(readend.fileno(), 1)]
+
+            # check negative timeout
+            # proper test in lib-python, test_poll_blocks_with_negative_ms
+            res = poll.poll(-0.001)
+            assert res == [(readend.fileno(), 1)]
         finally:
             readend.close()
             writeend.close()
@@ -238,7 +254,6 @@
         pollster.register(0, 65535) # USHRT_MAX
         raises(OverflowError, pollster.register, 0, 65536) # USHRT_MAX + 1
         raises(OverflowError, pollster.poll, 2147483648) # INT_MAX +  1
-        raises(OverflowError, pollster.poll, -2147483648 - 1)
         raises(OverflowError, pollster.poll, 4294967296) # UINT_MAX + 1
         exc = raises(TypeError, pollster.poll, '123')
         assert str(exc.value) == 'timeout must be an integer or None'
diff --git a/pypy/module/sys/interp_encoding.py b/pypy/module/sys/interp_encoding.py
--- a/pypy/module/sys/interp_encoding.py
+++ b/pypy/module/sys/interp_encoding.py
@@ -51,4 +51,6 @@
 
 
 def getfilesystemencodeerrors(space):
+    if sys.platform == "win32":
+        return space.newtext('strict')
     return space.newtext('surrogateescape')
diff --git a/pypy/objspace/std/callmethod.py b/pypy/objspace/std/callmethod.py
--- a/pypy/objspace/std/callmethod.py
+++ b/pypy/objspace/std/callmethod.py
@@ -111,12 +111,12 @@
             keywords_w[n_kwargs] = w_value
 
         arguments = f.popvalues(n)    # includes w_self if it is not None
-        args = f.argument_factory(
-                arguments, keywords, keywords_w, None, None,
-                methodcall=w_self is not None)
         if w_self is None:
             f.popvalue_maybe_none()    # removes w_self, which is None
         w_callable = f.popvalue()
+        args = f.argument_factory(
+                arguments, keywords, keywords_w, None, None,
+                methodcall=w_self is not None, w_function=w_callable)
         if f.get_is_being_profiled() and function.is_builtin_code(w_callable):
             w_result = f.space.call_args_and_c_profile(f, w_callable, args)
         else:
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -1235,9 +1235,11 @@
                 lgt -= 1
 
         if right:
-            while rpos > lpos and rutf8.isspace(value,
-                                         rutf8.prev_codepoint_pos(value, rpos)):
-                rpos = rutf8.prev_codepoint_pos(value, rpos)
+            while rpos > lpos:
+                prev = rutf8.prev_codepoint_pos(value, rpos)
+                if not rutf8.isspace(value, prev):
+                    break
+                rpos = prev
                 lgt -= 1
 
         assert rpos >= lpos    # annotator hint, don't remove
@@ -1258,9 +1260,11 @@
                 lgt -= 1
 
         if right:
-            while rpos > lpos and rutf8.utf8_in_chars(value,
-                    rutf8.prev_codepoint_pos(value, rpos), chars):
-                rpos = rutf8.prev_codepoint_pos(value, rpos)
+            while rpos > lpos:
+                prev = rutf8.prev_codepoint_pos(value, rpos)
+                if not rutf8.utf8_in_chars(value, prev, chars):
+                    break
+                rpos = prev
                 lgt -= 1
 
         assert rpos >= lpos    # annotator hint, don't remove


More information about the pypy-commit mailing list