Author: Armin Rigo <[email protected]>
Branch: remove-raisingops
Changeset: r84703:e431a60a7e4d
Date: 2016-05-26 09:23 +0200
http://bitbucket.org/pypy/pypy/changeset/e431a60a7e4d/

Log:    hg merge default

diff too long, truncating to 2000 out of 4033 lines

diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -22,3 +22,4 @@
 bbd45126bc691f669c4ebdfbd74456cd274c6b92 release-5.0.1
 3260adbeba4a8b6659d1cc0d0b41f266769b74da release-5.1
 b0a649e90b6642251fb4a765fe5b27a97b1319a9 release-5.1.1
+80ef432a32d9baa4b3c5a54c215e8ebe499f6374 release-5.1.2
diff --git a/lib-python/2.7/test/test_sys_settrace.py 
b/lib-python/2.7/test/test_sys_settrace.py
--- a/lib-python/2.7/test/test_sys_settrace.py
+++ b/lib-python/2.7/test/test_sys_settrace.py
@@ -328,8 +328,8 @@
 
     def test_13_genexp(self):
         if self.using_gc:
+            gc.enable()
             test_support.gc_collect()
-            gc.enable()
         try:
             self.run_test(generator_example)
             # issue1265: if the trace function contains a generator,
diff --git a/lib_pypy/cffi/commontypes.py b/lib_pypy/cffi/commontypes.py
--- a/lib_pypy/cffi/commontypes.py
+++ b/lib_pypy/cffi/commontypes.py
@@ -35,8 +35,11 @@
                                "you call ffi.set_unicode()" % (commontype,))
         else:
             if commontype == cdecl:
-                raise api.FFIError("Unsupported type: %r.  Please file a bug "
-                                   "if you think it should be." % 
(commontype,))
+                raise api.FFIError(
+                    "Unsupported type: %r.  Please look at "
+        "http://cffi.readthedocs.io/en/latest/cdef.html#ffi-cdef-limitations "
+                    "and file an issue if you think this type should really "
+                    "be supported." % (commontype,))
             result, quals = parser.parse_type_and_quals(cdecl)   # recursive
 
         assert isinstance(result, model.BaseTypeByIdentity)
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -89,3 +89,19 @@
 Use the new rgc.FinalizerQueue mechanism to clean up the handling of
 ``__del__`` methods.  Fixes notably issue #2287.  (All RPython
 subclasses of W_Root need to use FinalizerQueue now.)
+
+.. branch: ufunc-outer
+
+Implement ufunc.outer on numpypy
+
+.. branch: verbose-imports
+
+Support ``pypy -v``: verbose imports.  It does not log as much as
+cpython, but it should be enough to help when debugging package layout
+problems.
+
+.. branch: cpyext-macros-cast
+
+Fix some warnings when compiling CPython C extension modules
+
+.. branch: syntax_fix
diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py
--- a/pypy/interpreter/app_main.py
+++ b/pypy/interpreter/app_main.py
@@ -2,7 +2,7 @@
 # This is pure Python code that handles the main entry point into "pypy".
 # See test/test_app_main.
 
-# Missing vs CPython: -d, -t, -v, -x, -3
+# Missing vs CPython: -d, -t, -x, -3
 USAGE1 = __doc__ = """\
 Options and arguments (and corresponding environment variables):
 -B     : don't write .py[co] files on import; also PYTHONDONTWRITEBYTECODE=x
@@ -19,6 +19,8 @@
 -s     : don't add user site directory to sys.path; also PYTHONNOUSERSITE
 -S     : don't imply 'import site' on initialization
 -u     : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x
+-v     : verbose (trace import statements); also PYTHONVERBOSE=x
+         can be supplied multiple times to increase verbosity
 -V     : print the Python version number and exit (also --version)
 -W arg : warning control; arg is action:message:category:module:lineno
          also PYTHONWARNINGS=arg
@@ -529,6 +531,7 @@
                      warnoptions,
                      unbuffered,
                      ignore_environment,
+                     verbose,
                      **ignored):
     # with PyPy in top of CPython we can only have around 100
     # but we need more in the translated PyPy for the compiler package
@@ -663,6 +666,8 @@
                 inspect = True
             else:
                 # If not interactive, just read and execute stdin normally.
+                if verbose:
+                    print_banner(not no_site)
                 @hidden_applevel
                 def run_it():
                     co_stdin = compile(sys.stdin.read(), '<stdin>', 'exec',
@@ -724,10 +729,10 @@
     return status
 
 def print_banner(copyright):
-    print 'Python %s on %s' % (sys.version, sys.platform)
+    print >> sys.stderr, 'Python %s on %s' % (sys.version, sys.platform)
     if copyright:
-        print ('Type "help", "copyright", "credits" or '
-               '"license" for more information.')
+        print >> sys.stderr, ('Type "help", "copyright", "credits" or '
+                              '"license" for more information.')
 
 STDLIB_WARNING = """\
 debug: WARNING: Library path not found, using compiled-in sys.path.
diff --git a/pypy/interpreter/astcompiler/test/test_ast.py 
b/pypy/interpreter/astcompiler/test/test_ast.py
--- a/pypy/interpreter/astcompiler/test/test_ast.py
+++ b/pypy/interpreter/astcompiler/test/test_ast.py
@@ -1,8 +1,8 @@
 from pypy.interpreter.astcompiler import ast
 class TestAstToObject:
     def test_types(self, space):
-        assert space.is_true(space.issubtype(
-                ast.get(space).w_Module, ast.get(space).w_mod))
+        assert space.issubtype_w(
+                ast.get(space).w_Module, ast.get(space).w_mod)
                                   
     def test_num(self, space):
         value = space.wrap(42)
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1215,7 +1215,7 @@
 
     def abstract_issubclass_w(self, w_cls1, w_cls2):
         # Equivalent to 'issubclass(cls1, cls2)'.
-        return self.is_true(self.issubtype(w_cls1, w_cls2))
+        return self.issubtype_w(w_cls1, w_cls2)
 
     def abstract_isinstance_w(self, w_obj, w_cls):
         # Equivalent to 'isinstance(obj, cls)'.
@@ -1237,16 +1237,16 @@
     def exception_is_valid_obj_as_class_w(self, w_obj):
         if not self.isinstance_w(w_obj, self.w_type):
             return False
-        return self.is_true(self.issubtype(w_obj, self.w_BaseException))
+        return self.issubtype_w(w_obj, self.w_BaseException)
 
     def exception_is_valid_class_w(self, w_cls):
-        return self.is_true(self.issubtype(w_cls, self.w_BaseException))
+        return self.issubtype_w(w_cls, self.w_BaseException)
 
     def exception_getclass(self, w_obj):
         return self.type(w_obj)
 
     def exception_issubclass_w(self, w_cls1, w_cls2):
-        return self.is_true(self.issubtype(w_cls1, w_cls2))
+        return self.issubtype_w(w_cls1, w_cls2)
 
     def new_exception_class(self, *args, **kwargs):
         "NOT_RPYTHON; convenience method to create excceptions in modules"
diff --git a/pypy/module/__builtin__/__init__.py 
b/pypy/module/__builtin__/__init__.py
--- a/pypy/module/__builtin__/__init__.py
+++ b/pypy/module/__builtin__/__init__.py
@@ -86,8 +86,8 @@
         'max'           : 'functional.max',
         'reversed'      : 'functional.reversed',
         'super'         : 'descriptor.W_Super',
-        'staticmethod'  : 'descriptor.StaticMethod',
-        'classmethod'   : 'descriptor.ClassMethod',
+        'staticmethod'  : 'pypy.interpreter.function.StaticMethod',
+        'classmethod'   : 'pypy.interpreter.function.ClassMethod',
         'property'      : 'descriptor.W_Property',
 
         'globals'       : 'interp_inspect.globals',
diff --git a/pypy/module/__builtin__/abstractinst.py 
b/pypy/module/__builtin__/abstractinst.py
--- a/pypy/module/__builtin__/abstractinst.py
+++ b/pypy/module/__builtin__/abstractinst.py
@@ -76,11 +76,10 @@
             w_pretendtype = space.getattr(w_obj, space.wrap('__class__'))
             if space.is_w(w_pretendtype, space.type(w_obj)):
                 return False     # common case: obj.__class__ is type(obj)
-            if allow_override:
-                w_result = space.issubtype_allow_override(w_pretendtype,
-                                                          w_klass_or_tuple)
-            else:
-                w_result = space.issubtype(w_pretendtype, w_klass_or_tuple)
+            if not allow_override:
+                return space.issubtype_w(w_pretendtype, w_klass_or_tuple)
+            w_result = space.issubtype_allow_override(w_pretendtype,
+                                                      w_klass_or_tuple)
         except OperationError as e:
             if e.async(space):
                 raise
@@ -137,11 +136,9 @@
 
     # -- case (type, type)
     try:
-        if allow_override:
-            w_result = space.issubtype_allow_override(w_derived,
-                                                      w_klass_or_tuple)
-        else:
-            w_result = space.issubtype(w_derived, w_klass_or_tuple)
+        if not allow_override:
+            return space.issubtype_w(w_derived, w_klass_or_tuple)
+        w_result = space.issubtype_allow_override(w_derived, w_klass_or_tuple)
     except OperationError as e:   # if one of the args was not a type, ignore 
it
         if not e.match(space, space.w_TypeError):
             raise       # propagate other errors
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
@@ -1,31 +1,39 @@
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError, oefmt
-from pypy.interpreter.function import StaticMethod, ClassMethod
-from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
-from pypy.interpreter.typedef import (TypeDef, interp_attrproperty_w,
-    generic_new_descr)
+from pypy.interpreter.gateway import WrappedDefault, interp2app, unwrap_spec
+from pypy.interpreter.typedef import (
+    TypeDef, generic_new_descr, interp_attrproperty_w)
 from pypy.objspace.descroperation import object_getattribute
 
 
 class W_Super(W_Root):
-    def __init__(self, space, w_starttype, w_objtype, w_self):
+
+    def __init__(self, space):
+        self.w_starttype = None
+        self.w_objtype = None
+        self.w_self = None
+
+    def descr_init(self, space, w_starttype, w_obj_or_type=None):
+        if space.is_none(w_obj_or_type):
+            w_type = None  # unbound super object
+            w_obj_or_type = space.w_None
+        else:
+            w_type = _super_check(space, w_starttype, w_obj_or_type)
         self.w_starttype = w_starttype
-        self.w_objtype = w_objtype
-        self.w_self = w_self
+        self.w_objtype = w_type
+        self.w_self = w_obj_or_type
 
     def get(self, space, w_obj, w_type=None):
-        w = space.wrap
         if self.w_self is None or space.is_w(w_obj, space.w_None):
-            return w(self)
+            return self
         else:
             # if type(self) is W_Super:
             #     XXX write a fast path for this common case
-            w_selftype = space.type(w(self))
+            w_selftype = space.type(self)
             return space.call_function(w_selftype, self.w_starttype, w_obj)
 
-    @unwrap_spec(name=str)
-    def getattribute(self, space, name):
-        w = space.wrap
+    def getattribute(self, space, w_name):
+        name = space.str_w(w_name)
         # 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__':
@@ -45,44 +53,42 @@
                 return space.get_and_call_function(w_get, w_value,
                                                    w_obj, self.w_objtype)
         # fallback to object.__getattribute__()
-        return space.call_function(object_getattribute(space),
-                                   w(self), w(name))
+        return space.call_function(object_getattribute(space), self, w_name)
 
-def descr_new_super(space, w_subtype, w_starttype, w_obj_or_type=None):
-    if space.is_none(w_obj_or_type):
-        w_type = None  # unbound super object
-        w_obj_or_type = space.w_None
-    else:
-        w_objtype = space.type(w_obj_or_type)
-        if space.is_true(space.issubtype(w_objtype, space.w_type)) and \
-            space.is_true(space.issubtype(w_obj_or_type, w_starttype)):
-            w_type = w_obj_or_type # special case for class methods
-        elif space.is_true(space.issubtype(w_objtype, w_starttype)):
-            w_type = w_objtype # normal case
-        else:
-            try:
-                w_type = space.getattr(w_obj_or_type, space.wrap('__class__'))
-            except OperationError as o:
-                if not o.match(space, space.w_AttributeError):
-                    raise
-                w_type = w_objtype
-            if not space.is_true(space.issubtype(w_type, w_starttype)):
-                raise oefmt(space.w_TypeError,
-                            "super(type, obj): obj must be an instance or "
-                            "subtype of type")
-    # XXX the details of how allocate_instance() should be used are not
-    # really well defined
-    w_result = space.allocate_instance(W_Super, w_subtype)
-    W_Super.__init__(w_result, space, w_starttype, w_type, w_obj_or_type)
-    return w_result
+def _super_check(space, w_starttype, w_obj_or_type):
+    """Check that the super() call makes sense. Returns a type"""
+    w_objtype = space.type(w_obj_or_type)
+
+    if (space.issubtype_w(w_objtype, space.w_type) and
+        space.issubtype_w(w_obj_or_type, w_starttype)):
+        # special case for class methods
+        return w_obj_or_type
+
+    if space.issubtype_w(w_objtype, w_starttype):
+        # normal case
+        return w_objtype
+
+    try:
+        w_type = space.getattr(w_obj_or_type, space.wrap('__class__'))
+    except OperationError as e:
+        if not e.match(space, space.w_AttributeError):
+            raise
+        w_type = w_objtype
+
+    if space.issubtype_w(w_type, w_starttype):
+        return w_type
+    raise oefmt(space.w_TypeError,
+                "super(type, obj): obj must be an instance or subtype of type")
 
 W_Super.typedef = TypeDef(
     'super',
-    __new__          = interp2app(descr_new_super),
+    __new__          = generic_new_descr(W_Super),
+    __init__         = interp2app(W_Super.descr_init),
     __thisclass__    = interp_attrproperty_w("w_starttype", W_Super),
     __getattribute__ = interp2app(W_Super.getattribute),
     __get__          = interp2app(W_Super.get),
-    __doc__          =     """super(type) -> unbound super object
+    __doc__          =     """\
+super(type) -> unbound super object
 super(type, obj) -> bound super object; requires isinstance(obj, type)
 super(type, type2) -> bound super object; requires issubclass(type2, type)
 
@@ -100,10 +106,10 @@
     def __init__(self, space):
         pass
 
-    @unwrap_spec(w_fget = WrappedDefault(None),
-                 w_fset = WrappedDefault(None),
-                 w_fdel = WrappedDefault(None),
-                 w_doc = WrappedDefault(None))
+    @unwrap_spec(w_fget=WrappedDefault(None),
+                 w_fset=WrappedDefault(None),
+                 w_fdel=WrappedDefault(None),
+                 w_doc=WrappedDefault(None))
     def init(self, space, w_fget=None, w_fset=None, w_fdel=None, w_doc=None):
         self.w_fget = w_fget
         self.w_fset = w_fset
@@ -113,18 +119,17 @@
         # our __doc__ comes from the getter if we don't have an explicit one
         if (space.is_w(self.w_doc, space.w_None) and
             not space.is_w(self.w_fget, space.w_None)):
-            w_getter_doc = space.findattr(self.w_fget, space.wrap("__doc__"))
+            w_getter_doc = space.findattr(self.w_fget, space.wrap('__doc__'))
             if w_getter_doc is not None:
                 if type(self) is W_Property:
                     self.w_doc = w_getter_doc
                 else:
-                    space.setattr(space.wrap(self), space.wrap("__doc__"),
-                                  w_getter_doc)
+                    space.setattr(self, space.wrap('__doc__'), w_getter_doc)
                 self.getter_doc = True
 
     def get(self, space, w_obj, w_objtype=None):
         if space.is_w(w_obj, space.w_None):
-            return space.wrap(self)
+            return self
         if space.is_w(self.w_fget, space.w_None):
             raise oefmt(space.w_AttributeError, "unreadable attribute")
         return space.call_function(self.w_fget, w_obj)
@@ -162,11 +167,13 @@
         else:
             w_doc = self.w_doc
         w_type = self.getclass(space)
-        return space.call_function(w_type, w_getter, w_setter, w_deleter, 
w_doc)
+        return space.call_function(w_type, w_getter, w_setter, w_deleter,
+                                   w_doc)
 
 W_Property.typedef = TypeDef(
     'property',
-    __doc__ = '''property(fget=None, fset=None, fdel=None, doc=None) -> 
property attribute
+    __doc__ = '''\
+property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
 
 fget is a function to be used for getting an attribute value, and likewise
 fset is a function for setting, and fdel a function for deleting, an
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
@@ -145,8 +145,17 @@
         else:
             compare = space.lt
             jitdriver = min_jitdriver
+        any_kwds = bool(args.keywords)
         args_w = args.arguments_w
         if len(args_w) > 1:
+            if unroll and len(args_w) == 2 and not any_kwds:
+                # a fast path for the common case, useful for interpreted
+                # mode and to reduce the length of the jit trace
+                w0, w1 = args_w
+                if space.is_true(compare(w1, w0)):
+                    return w1
+                else:
+                    return w0
             w_sequence = space.newtuple(args_w)
         elif len(args_w):
             w_sequence = args_w[0]
@@ -155,8 +164,8 @@
                         "%s() expects at least one argument",
                         implementation_of)
         w_key = None
-        kwds = args.keywords
-        if kwds:
+        if any_kwds:
+            kwds = args.keywords
             if kwds[0] == "key" and len(kwds) == 1:
                 w_key = args.keywords_w[0]
             else:
diff --git a/pypy/module/__builtin__/test/test_functional.py 
b/pypy/module/__builtin__/test/test_functional.py
--- a/pypy/module/__builtin__/test/test_functional.py
+++ b/pypy/module/__builtin__/test/test_functional.py
@@ -296,6 +296,11 @@
         assert min([1, 2, 3]) == 1
         raises(TypeError, min, 1, 2, bar=2)
         raises(TypeError, min, 1, 2, key=lambda x: x, bar=2)
+        assert type(min(1, 1.0)) is int
+        assert type(min(1.0, 1)) is float
+        assert type(min(1, 1.0, 1L)) is int
+        assert type(min(1.0, 1L, 1)) is float
+        assert type(min(1L, 1, 1.0)) is long
 
     def test_max(self):
         assert max(1, 2) == 2
@@ -303,3 +308,8 @@
         assert max([1, 2, 3]) == 3
         raises(TypeError, max, 1, 2, bar=2)
         raises(TypeError, max, 1, 2, key=lambda x: x, bar=2)
+        assert type(max(1, 1.0)) is int
+        assert type(max(1.0, 1)) is float
+        assert type(max(1, 1.0, 1L)) is int
+        assert type(max(1.0, 1L, 1)) is float
+        assert type(max(1L, 1, 1.0)) is long
diff --git a/pypy/module/__pypy__/interp_magic.py 
b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -51,6 +51,11 @@
                            space.newint(cache.misses.get(name, 0))])
 
 def builtinify(space, w_func):
+    """To implement at app-level modules that are, in CPython,
+    implemented in C: this decorator protects a function from being ever
+    bound like a method.  Useful because some tests do things like put
+    a "built-in" function on a class and access it via the instance.
+    """
     from pypy.interpreter.function import Function, BuiltinFunction
     func = space.interp_w(Function, w_func)
     bltn = BuiltinFunction(func)
diff --git a/pypy/module/_cffi_backend/ctypeobj.py 
b/pypy/module/_cffi_backend/ctypeobj.py
--- a/pypy/module/_cffi_backend/ctypeobj.py
+++ b/pypy/module/_cffi_backend/ctypeobj.py
@@ -233,10 +233,9 @@
     # __________ app-level attributes __________
     def dir(self):
         space = self.space
-        w_self = space.wrap(self)
         lst = [space.wrap(name)
                   for name in _name_of_attributes
-                  if space.findattr(w_self, space.wrap(name)) is not None]
+                  if space.findattr(self, space.wrap(name)) is not None]
         return space.newlist(lst)
 
     def _fget(self, attrchar):
diff --git a/pypy/module/_cffi_backend/lib_obj.py 
b/pypy/module/_cffi_backend/lib_obj.py
--- a/pypy/module/_cffi_backend/lib_obj.py
+++ b/pypy/module/_cffi_backend/lib_obj.py
@@ -196,9 +196,13 @@
                 if is_getattr and attr == '__dict__':
                     return self.full_dict_copy()
                 if is_getattr and attr == '__class__':
-                    return self.space.type(self)
+                    # used to be space.type(self).  But HAAAAAACK!
+                    # That makes help() behave correctly.  I couldn't
+                    # find a more reasonable way.  Urgh.
+                    from pypy.interpreter.module import Module
+                    return self.space.gettypeobject(Module.typedef)
                 if is_getattr and attr == '__name__':
-                    return self.descr_repr()
+                    return self.space.wrap("%s.lib" % self.libname)
                 raise oefmt(self.space.w_AttributeError,
                             "cffi library '%s' has no function, constant "
                             "or global variable named '%s'",
diff --git a/pypy/module/_cffi_backend/test/test_recompiler.py 
b/pypy/module/_cffi_backend/test/test_recompiler.py
--- a/pypy/module/_cffi_backend/test/test_recompiler.py
+++ b/pypy/module/_cffi_backend/test/test_recompiler.py
@@ -1039,8 +1039,8 @@
         assert MYFOO == 42
         assert hasattr(lib, '__dict__')
         assert lib.__all__ == ['MYFOO', 'mybar']   # but not 'myvar'
-        assert lib.__name__ == repr(lib)
-        assert lib.__class__ is type(lib)
+        assert lib.__name__ == '_CFFI_test_import_from_lib.lib'
+        assert lib.__class__ is type(sys)   # !! hack for help()
 
     def test_macro_var_callback(self):
         ffi, lib = self.prepare(
diff --git a/pypy/module/_collections/interp_deque.py 
b/pypy/module/_collections/interp_deque.py
--- a/pypy/module/_collections/interp_deque.py
+++ b/pypy/module/_collections/interp_deque.py
@@ -389,20 +389,18 @@
     def copy(self):
         "Return a shallow copy of a deque."
         space = self.space
-        w_self = space.wrap(self)
         if self.maxlen == sys.maxint:
-            return space.call_function(space.type(w_self), w_self)
+            return space.call_function(space.type(self), self)
         else:
-            return space.call_function(space.type(w_self), w_self,
+            return space.call_function(space.type(self), self,
                                        space.wrap(self.maxlen))
 
     def reduce(self):
         "Return state information for pickling."
         space = self.space
-        w_self = space.wrap(self)
-        w_type = space.type(w_self)
-        w_dict = space.findattr(w_self, space.wrap('__dict__'))
-        w_list = space.call_function(space.w_list, w_self)
+        w_type = space.type(self)
+        w_dict = space.findattr(self, space.wrap('__dict__'))
+        w_list = space.call_function(space.w_list, self)
         if w_dict is None:
             if self.maxlen == sys.maxint:
                 result = [
diff --git a/pypy/module/_weakref/interp__weakref.py 
b/pypy/module/_weakref/interp__weakref.py
--- a/pypy/module/_weakref/interp__weakref.py
+++ b/pypy/module/_weakref/interp__weakref.py
@@ -156,12 +156,12 @@
 
 
 class W_WeakrefBase(W_Root):
-    def __init__(w_self, space, w_obj, w_callable):
+    def __init__(self, space, w_obj, w_callable):
         assert w_callable is not space.w_None    # should be really None
-        w_self.space = space
+        self.space = space
         assert w_obj is not None
-        w_self.w_obj_weak = weakref.ref(w_obj)
-        w_self.w_callable = w_callable
+        self.w_obj_weak = weakref.ref(w_obj)
+        self.w_callable = w_callable
 
     @jit.dont_look_inside
     def dereference(self):
@@ -171,8 +171,8 @@
     def clear(self):
         self.w_obj_weak = dead_ref
 
-    def activate_callback(w_self):
-        w_self.space.call_function(w_self.w_callable, w_self)
+    def activate_callback(self):
+        self.space.call_function(self.w_callable, self)
 
     def descr__repr__(self, space):
         w_obj = self.dereference()
@@ -189,9 +189,9 @@
 
 
 class W_Weakref(W_WeakrefBase):
-    def __init__(w_self, space, w_obj, w_callable):
-        W_WeakrefBase.__init__(w_self, space, w_obj, w_callable)
-        w_self.w_hash = None
+    def __init__(self, space, w_obj, w_callable):
+        W_WeakrefBase.__init__(self, space, w_obj, w_callable)
+        self.w_hash = None
 
     def descr__init__weakref(self, space, w_obj, w_callable=None,
                              __args__=None):
diff --git a/pypy/module/_winreg/interp_winreg.py 
b/pypy/module/_winreg/interp_winreg.py
--- a/pypy/module/_winreg/interp_winreg.py
+++ b/pypy/module/_winreg/interp_winreg.py
@@ -16,10 +16,11 @@
 class W_HKEY(W_Root):
     def __init__(self, space, hkey):
         self.hkey = hkey
+        self.space = space
         self.register_finalizer(space)
 
-    def _finalize_(self, space):
-        self.Close(space)
+    def _finalize_(self):
+        self.Close(self.space)
 
     def as_int(self):
         return rffi.cast(rffi.SIZE_T, self.hkey)
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -203,46 +203,46 @@
 # id.  Invariant: this variable always contain 0 when the PyPy GIL is
 # released.  It should also contain 0 when regular RPython code
 # executes.  In non-cpyext-related code, it will thus always be 0.
-# 
+#
 # **make_generic_cpy_call():** RPython to C, with the GIL held.  Before
 # the call, must assert that the global variable is 0 and set the
 # current thread identifier into the global variable.  After the call,
 # assert that the global variable still contains the current thread id,
 # and reset it to 0.
-# 
+#
 # **make_wrapper():** C to RPython; by default assume that the GIL is
 # held, but accepts gil="acquire", "release", "around",
 # "pygilstate_ensure", "pygilstate_release".
-# 
+#
 # When a wrapper() is called:
-# 
+#
 # * "acquire": assert that the GIL is not currently held, i.e. the
 #   global variable does not contain the current thread id (otherwise,
 #   deadlock!).  Acquire the PyPy GIL.  After we acquired it, assert
 #   that the global variable is 0 (it must be 0 according to the
 #   invariant that it was 0 immediately before we acquired the GIL,
 #   because the GIL was released at that point).
-# 
+#
 # * gil=None: we hold the GIL already.  Assert that the current thread
 #   identifier is in the global variable, and replace it with 0.
-# 
+#
 # * "pygilstate_ensure": if the global variable contains the current
 #   thread id, replace it with 0 and set the extra arg to 0.  Otherwise,
 #   do the "acquire" and set the extra arg to 1.  Then we'll call
 #   pystate.py:PyGILState_Ensure() with this extra arg, which will do
 #   the rest of the logic.
-# 
+#
 # When a wrapper() returns, first assert that the global variable is
 # still 0, and then:
-# 
+#
 # * "release": release the PyPy GIL.  The global variable was 0 up to
 #   and including at the point where we released the GIL, but afterwards
 #   it is possible that the GIL is acquired by a different thread very
 #   quickly.
-# 
+#
 # * gil=None: we keep holding the GIL.  Set the current thread
 #   identifier into the global variable.
-# 
+#
 # * "pygilstate_release": if the argument is PyGILState_UNLOCKED,
 #   release the PyPy GIL; otherwise, set the current thread identifier
 #   into the global variable.  The rest of the logic of
@@ -254,7 +254,7 @@
 
 cpyext_namespace = NameManager('cpyext_')
 
-class ApiFunction:
+class ApiFunction(object):
     def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED,
                  c_name=None, gil=None, result_borrowed=False, 
result_is_ll=False):
         self.argtypes = argtypes
@@ -292,11 +292,48 @@
     def get_wrapper(self, space):
         wrapper = getattr(self, '_wrapper', None)
         if wrapper is None:
-            wrapper = make_wrapper(space, self.callable, self.gil)
-            self._wrapper = wrapper
-            wrapper.relax_sig_check = True
-            if self.c_name is not None:
-                wrapper.c_name = cpyext_namespace.uniquename(self.c_name)
+            wrapper = self._wrapper = self._make_wrapper(space)
+        return wrapper
+
+    # Make the wrapper for the cases (1) and (2)
+    def _make_wrapper(self, space):
+        "NOT_RPYTHON"
+        # This logic is obscure, because we try to avoid creating one
+        # big wrapper() function for every callable.  Instead we create
+        # only one per "signature".
+
+        argtypesw = zip(self.argtypes,
+                        [_name.startswith("w_") for _name in self.argnames])
+        error_value = getattr(self, "error_value", CANNOT_FAIL)
+        if (isinstance(self.restype, lltype.Ptr)
+                and error_value is not CANNOT_FAIL):
+            assert lltype.typeOf(error_value) == self.restype
+            assert not error_value    # only support error=NULL
+            error_value = 0    # because NULL is not hashable
+
+        if self.result_is_ll:
+            result_kind = "L"
+        elif self.result_borrowed:
+            result_kind = "B"     # note: 'result_borrowed' is ignored if we 
also
+        else:                     #  say 'result_is_ll=True' (in this case it's
+            result_kind = "."     #  up to you to handle refcounting anyway)
+
+        signature = (tuple(argtypesw),
+                    self.restype,
+                    result_kind,
+                    error_value,
+                    self.gil)
+
+        cache = space.fromcache(WrapperCache)
+        try:
+            wrapper_gen = cache.wrapper_gens[signature]
+        except KeyError:
+            wrapper_gen = WrapperGen(space, signature)
+            cache.wrapper_gens[signature] = wrapper_gen
+        wrapper = wrapper_gen.make_wrapper(self.callable)
+        wrapper.relax_sig_check = True
+        if self.c_name is not None:
+            wrapper.c_name = cpyext_namespace.uniquename(self.c_name)
         return wrapper
 
 DEFAULT_HEADER = 'pypy_decl.h'
@@ -373,7 +410,16 @@
                             arg = rffi.cast(ARG, as_pyobj(space, input_arg))
                         else:
                             arg = rffi.cast(ARG, input_arg)
-                    elif is_PyObject(ARG) and is_wrapped:
+                    elif ARG == rffi.VOIDP and not is_wrapped:
+                        # unlike is_PyObject case above, we allow any kind of
+                        # argument -- just, if it's an object, we assume the
+                        # caller meant for it to become a PyObject*.
+                        if input_arg is None or isinstance(input_arg, W_Root):
+                            keepalives += (input_arg,)
+                            arg = rffi.cast(ARG, as_pyobj(space, input_arg))
+                        else:
+                            arg = rffi.cast(ARG, input_arg)
+                    elif (is_PyObject(ARG) or ARG == rffi.VOIDP) and 
is_wrapped:
                         # build a W_Root, possibly from a 'PyObject *'
                         if is_pyobj(input_arg):
                             arg = from_ref(space, input_arg)
@@ -660,7 +706,7 @@
         w_obj_type = space.type(w_obj)
         w_type = get_w_type(space)
         return (space.is_w(w_obj_type, w_type) or
-                space.is_true(space.issubtype(w_obj_type, w_type)))
+                space.issubtype_w(w_obj_type, w_type))
     def check_exact(space, w_obj):
         "Implements the Py_Xxx_CheckExact function"
         w_obj_type = space.type(w_obj)
@@ -683,92 +729,61 @@
     def __init__(self, space):
         self.space = space
         self.wrapper_gens = {}    # {signature: WrapperGen()}
-        self.stats = [0, 0]
 
 class WrapperGen(object):
     wrapper_second_level = None
+    A = lltype.Array(lltype.Char)
 
     def __init__(self, space, signature):
         self.space = space
         self.signature = signature
-        self.callable2name = []
 
     def make_wrapper(self, callable):
-        self.callable2name.append((callable, callable.__name__))
         if self.wrapper_second_level is None:
             self.wrapper_second_level = make_wrapper_second_level(
-                self.space, self.callable2name, *self.signature)
+                self.space, *self.signature)
         wrapper_second_level = self.wrapper_second_level
 
+        name = callable.__name__
+        pname = lltype.malloc(self.A, len(name), flavor='raw', immortal=True)
+        for i in range(len(name)):
+            pname[i] = name[i]
+
         def wrapper(*args):
             # no GC here, not even any GC object
-            args += (callable,)
-            return wrapper_second_level(*args)
+            return wrapper_second_level(callable, pname, *args)
 
         wrapper.__name__ = "wrapper for %r" % (callable, )
         return wrapper
 
 
-# Make the wrapper for the cases (1) and (2)
-def make_wrapper(space, callable, gil=None):
-    "NOT_RPYTHON"
-    # This logic is obscure, because we try to avoid creating one
-    # big wrapper() function for every callable.  Instead we create
-    # only one per "signature".
 
-    argnames = callable.api_func.argnames
-    argtypesw = zip(callable.api_func.argtypes,
-                    [_name.startswith("w_") for _name in argnames])
-    error_value = getattr(callable.api_func, "error_value", CANNOT_FAIL)
-    if (isinstance(callable.api_func.restype, lltype.Ptr)
-            and error_value is not CANNOT_FAIL):
-        assert lltype.typeOf(error_value) == callable.api_func.restype
-        assert not error_value    # only support error=NULL
-        error_value = 0    # because NULL is not hashable
-
-    if callable.api_func.result_is_ll:
-        result_kind = "L"
-    elif callable.api_func.result_borrowed:
-        result_kind = "B"     # note: 'result_borrowed' is ignored if we also
-    else:                     #  say 'result_is_ll=True' (in this case it's
-        result_kind = "."     #  up to you to handle refcounting anyway)
-
-    signature = (tuple(argtypesw),
-                 callable.api_func.restype,
-                 result_kind,
-                 error_value,
-                 gil)
-
-    cache = space.fromcache(WrapperCache)
-    cache.stats[1] += 1
-    try:
-        wrapper_gen = cache.wrapper_gens[signature]
-    except KeyError:
-        #print signature
-        wrapper_gen = cache.wrapper_gens[signature] = WrapperGen(space,
-                                                                 signature)
-        cache.stats[0] += 1
-    #print 'Wrapper cache [wrappers/total]:', cache.stats
-    return wrapper_gen.make_wrapper(callable)
-
+@dont_inline
+def _unpack_name(pname):
+    return ''.join([pname[i] for i in range(len(pname))])
 
 @dont_inline
 def deadlock_error(funcname):
+    funcname = _unpack_name(funcname)
     fatalerror_notb("GIL deadlock detected when a CPython C extension "
                     "module calls '%s'" % (funcname,))
 
 @dont_inline
 def no_gil_error(funcname):
+    funcname = _unpack_name(funcname)
     fatalerror_notb("GIL not held when a CPython C extension "
                     "module calls '%s'" % (funcname,))
 
 @dont_inline
 def not_supposed_to_fail(funcname):
-    raise SystemError("The function '%s' was not supposed to fail"
-                      % (funcname,))
+    funcname = _unpack_name(funcname)
+    print "Error in cpyext, CPython compatibility layer:"
+    print "The function", funcname, "was not supposed to fail"
+    raise SystemError
 
 @dont_inline
 def unexpected_exception(funcname, e, tb):
+    funcname = _unpack_name(funcname)
     print 'Fatal error in cpyext, CPython compatibility layer, 
calling',funcname
     print 'Either report a bug or consider not using this particular extension'
     if not we_are_translated():
@@ -784,7 +799,7 @@
         pypy_debug_catch_fatal_exception()
         assert False
 
-def make_wrapper_second_level(space, callable2name, argtypesw, restype,
+def make_wrapper_second_level(space, argtypesw, restype,
                               result_kind, error_value, gil):
     from rpython.rlib import rgil
     argtypes_enum_ui = unrolling_iterable(enumerate(argtypesw))
@@ -807,29 +822,19 @@
     def invalid(err):
         "NOT_RPYTHON: translation-time crash if this ends up being called"
         raise ValueError(err)
-    invalid.__name__ = 'invalid_%s' % (callable2name[0][1],)
 
-    def nameof(callable):
-        for c, n in callable2name:
-            if c is callable:
-                return n
-        return '<unknown function>'
-    nameof._dont_inline_ = True
-
-    def wrapper_second_level(*args):
+    def wrapper_second_level(callable, pname, *args):
         from pypy.module.cpyext.pyobject import make_ref, from_ref, is_pyobj
         from pypy.module.cpyext.pyobject import as_pyobj
         # we hope that malloc removal removes the newtuple() that is
         # inserted exactly here by the varargs specializer
-        callable = args[-1]
-        args = args[:-1]
 
         # see "Handling of the GIL" above (careful, we don't have the GIL here)
         tid = rthread.get_or_make_ident()
         _gil_auto = (gil_auto_workaround and cpyext_glob_tid_ptr[0] != tid)
         if gil_acquire or _gil_auto:
             if cpyext_glob_tid_ptr[0] == tid:
-                deadlock_error(nameof(callable))
+                deadlock_error(pname)
             rgil.acquire()
             assert cpyext_glob_tid_ptr[0] == 0
         elif pygilstate_ensure:
@@ -842,7 +847,7 @@
                 args += (pystate.PyGILState_UNLOCKED,)
         else:
             if cpyext_glob_tid_ptr[0] != tid:
-                no_gil_error(nameof(callable))
+                no_gil_error(pname)
             cpyext_glob_tid_ptr[0] = 0
 
         rffi.stackcounter.stacks_counter += 1
@@ -859,6 +864,10 @@
                 if is_PyObject(typ) and is_wrapped:
                     assert is_pyobj(arg)
                     arg_conv = from_ref(space, rffi.cast(PyObject, arg))
+                elif typ == rffi.VOIDP and is_wrapped:
+                    # Many macros accept a void* so that one can pass a
+                    # PyObject* or a PySomeSubtype*.
+                    arg_conv = from_ref(space, rffi.cast(PyObject, arg))
                 else:
                     arg_conv = arg
                 boxed_args += (arg_conv, )
@@ -888,7 +897,7 @@
 
             if failed:
                 if error_value is CANNOT_FAIL:
-                    raise not_supposed_to_fail(nameof(callable))
+                    raise not_supposed_to_fail(pname)
                 retval = error_value
 
             elif is_PyObject(restype):
@@ -908,7 +917,7 @@
                 retval = rffi.cast(restype, result)
 
         except Exception as e:
-            unexpected_exception(nameof(callable), e, tb)
+            unexpected_exception(pname, e, tb)
             return fatal_value
 
         assert lltype.typeOf(retval) == restype
@@ -1019,7 +1028,7 @@
     structindex = {}
     for header, header_functions in FUNCTIONS_BY_HEADER.iteritems():
         for name, func in header_functions.iteritems():
-            if not func: 
+            if not func:
                 # added only for the macro, not the decl
                 continue
             restype, args = c_function_signature(db, func)
@@ -1033,7 +1042,7 @@
     RPY_EXTERN struct PyPyAPI* pypyAPI = &_pypyAPI;
     """ % dict(members=structmembers)
 
-    functions = generate_decls_and_callbacks(db, export_symbols, 
+    functions = generate_decls_and_callbacks(db, export_symbols,
                                             prefix='cpyexttest')
 
     global_objects = []
@@ -1415,7 +1424,7 @@
 
     generate_macros(export_symbols, prefix=prefix)
 
-    functions = generate_decls_and_callbacks(db, [], api_struct=False, 
+    functions = generate_decls_and_callbacks(db, [], api_struct=False,
                                             prefix=prefix)
     code = "#include <Python.h>\n"
     if use_micronumpy:
@@ -1471,7 +1480,7 @@
             if not func:
                 continue
             newname = mangle_name('PyPy', name) or name
-            deco = entrypoint_lowlevel("cpyext", func.argtypes, newname, 
+            deco = entrypoint_lowlevel("cpyext", func.argtypes, newname,
                                         relax=True)
             deco(func.get_wrapper(space))
 
diff --git a/pypy/module/cpyext/cdatetime.py b/pypy/module/cpyext/cdatetime.py
--- a/pypy/module/cpyext/cdatetime.py
+++ b/pypy/module/cpyext/cdatetime.py
@@ -1,4 +1,5 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rtyper.annlowlevel import llhelper
 from pypy.module.cpyext.pyobject import PyObject, make_ref
 from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, cpython_struct,
     PyObjectFields)
@@ -16,6 +17,23 @@
      ('TimeType', PyTypeObjectPtr),
      ('DeltaType', PyTypeObjectPtr),
      ('TZInfoType', PyTypeObjectPtr),
+
+     ('Date_FromDate', lltype.Ptr(lltype.FuncType(
+         [rffi.INT_real, rffi.INT_real, rffi.INT_real, PyTypeObjectPtr],
+         PyObject))),
+     ('Time_FromTime', lltype.Ptr(lltype.FuncType(
+         [rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real,
+          PyObject, PyTypeObjectPtr],
+         PyObject))),
+     ('DateTime_FromDateAndTime', lltype.Ptr(lltype.FuncType(
+         [rffi.INT_real, rffi.INT_real, rffi.INT_real,
+          rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real,
+          PyObject, PyTypeObjectPtr],
+         PyObject))),
+     ('Delta_FromDelta', lltype.Ptr(lltype.FuncType(
+         [rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real,
+          PyTypeObjectPtr],
+         PyObject))),
      ))
 
 @cpython_api([], lltype.Ptr(PyDateTime_CAPI))
@@ -45,6 +63,19 @@
     datetimeAPI.c_TZInfoType = rffi.cast(
         PyTypeObjectPtr, make_ref(space, w_type))
 
+    datetimeAPI.c_Date_FromDate = llhelper(
+        _PyDate_FromDate.api_func.functype,
+        _PyDate_FromDate.api_func.get_wrapper(space))
+    datetimeAPI.c_Time_FromTime = llhelper(
+        _PyTime_FromTime.api_func.functype,
+        _PyTime_FromTime.api_func.get_wrapper(space))
+    datetimeAPI.c_DateTime_FromDateAndTime = llhelper(
+        _PyDateTime_FromDateAndTime.api_func.functype,
+        _PyDateTime_FromDateAndTime.api_func.get_wrapper(space))
+    datetimeAPI.c_Delta_FromDelta = llhelper(
+        _PyDelta_FromDelta.api_func.functype,
+        _PyDelta_FromDelta.api_func.get_wrapper(space))
+
     return datetimeAPI
 
 PyDateTime_DateStruct = lltype.ForwardReference()
@@ -94,36 +125,40 @@
 make_check_function("PyDelta_Check", "timedelta")
 make_check_function("PyTZInfo_Check", "tzinfo")
 
-# Constructors
+# Constructors. They are better used as macros.
 
-@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject)
-def PyDate_FromDate(space, year, month, day):
+@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, PyTypeObjectPtr],
+             PyObject)
+def _PyDate_FromDate(space, year, month, day, w_type):
     """Return a datetime.date object with the specified year, month and day.
     """
     year = rffi.cast(lltype.Signed, year)
     month = rffi.cast(lltype.Signed, month)
     day = rffi.cast(lltype.Signed, day)
-    w_datetime = PyImport_Import(space, space.wrap("datetime"))
-    return space.call_method(
-        w_datetime, "date",
+    return space.call_function(
+        w_type,
         space.wrap(year), space.wrap(month), space.wrap(day))
 
-@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real], 
PyObject)
-def PyTime_FromTime(space, hour, minute, second, usecond):
+@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real,
+              PyObject, PyTypeObjectPtr], PyObject)
+def _PyTime_FromTime(space, hour, minute, second, usecond, w_tzinfo, w_type):
     """Return a ``datetime.time`` object with the specified hour, minute, 
second and
     microsecond."""
     hour = rffi.cast(lltype.Signed, hour)
     minute = rffi.cast(lltype.Signed, minute)
     second = rffi.cast(lltype.Signed, second)
     usecond = rffi.cast(lltype.Signed, usecond)
-    w_datetime = PyImport_Import(space, space.wrap("datetime"))
-    return space.call_method(
-        w_datetime, "time",
+    return space.call_function(
+        w_type,
         space.wrap(hour), space.wrap(minute), space.wrap(second),
-        space.wrap(usecond))
+        space.wrap(usecond), w_tzinfo)
 
-@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, 
rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject)
-def PyDateTime_FromDateAndTime(space, year, month, day, hour, minute, second, 
usecond):
+@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real,
+              rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real,
+              PyObject, PyTypeObjectPtr], PyObject)
+def _PyDateTime_FromDateAndTime(space, year, month, day,
+                                hour, minute, second, usecond,
+                                w_tzinfo, w_type):
     """Return a datetime.datetime object with the specified year, month, day, 
hour,
     minute, second and microsecond.
     """
@@ -134,12 +169,11 @@
     minute = rffi.cast(lltype.Signed, minute)
     second = rffi.cast(lltype.Signed, second)
     usecond = rffi.cast(lltype.Signed, usecond)
-    w_datetime = PyImport_Import(space, space.wrap("datetime"))
-    return space.call_method(
-        w_datetime, "datetime",
+    return space.call_function(
+        w_type,
         space.wrap(year), space.wrap(month), space.wrap(day),
         space.wrap(hour), space.wrap(minute), space.wrap(second),
-        space.wrap(usecond))
+        space.wrap(usecond), w_tzinfo)
 
 @cpython_api([PyObject], PyObject)
 def PyDateTime_FromTimestamp(space, w_args):
@@ -161,8 +195,10 @@
     w_method = space.getattr(w_type, space.wrap("fromtimestamp"))
     return space.call(w_method, w_args)
 
-@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real], PyObject)
-def PyDelta_FromDSU(space, days, seconds, useconds):
+@cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real,
+              PyTypeObjectPtr],
+             PyObject)
+def _PyDelta_FromDelta(space, days, seconds, useconds, normalize, w_type):
     """Return a datetime.timedelta object representing the given number of 
days,
     seconds and microseconds.  Normalization is performed so that the resulting
     number of microseconds and seconds lie in the ranges documented for
@@ -171,74 +207,73 @@
     days = rffi.cast(lltype.Signed, days)
     seconds = rffi.cast(lltype.Signed, seconds)
     useconds = rffi.cast(lltype.Signed, useconds)
-    w_datetime = PyImport_Import(space, space.wrap("datetime"))
-    return space.call_method(
-        w_datetime, "timedelta",
+    return space.call_function(
+        w_type,
         space.wrap(days), space.wrap(seconds), space.wrap(useconds))
 
 # Accessors
 
-@cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_GET_YEAR(space, w_obj):
     """Return the year, as a positive int.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("year")))
 
-@cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_GET_MONTH(space, w_obj):
     """Return the month, as an int from 1 through 12.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("month")))
 
-@cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_GET_DAY(space, w_obj):
     """Return the day, as an int from 1 through 31.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("day")))
 
-@cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DATE_GET_HOUR(space, w_obj):
     """Return the hour, as an int from 0 through 23.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("hour")))
 
-@cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DATE_GET_MINUTE(space, w_obj):
     """Return the minute, as an int from 0 through 59.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("minute")))
 
-@cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DATE_GET_SECOND(space, w_obj):
     """Return the second, as an int from 0 through 59.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("second")))
 
-@cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DATE_GET_MICROSECOND(space, w_obj):
     """Return the microsecond, as an int from 0 through 999999.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("microsecond")))
 
-@cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_TIME_GET_HOUR(space, w_obj):
     """Return the hour, as an int from 0 through 23.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("hour")))
 
-@cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_TIME_GET_MINUTE(space, w_obj):
     """Return the minute, as an int from 0 through 59.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("minute")))
 
-@cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_TIME_GET_SECOND(space, w_obj):
     """Return the second, as an int from 0 through 59.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("second")))
 
-@cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_TIME_GET_MICROSECOND(space, w_obj):
     """Return the microsecond, as an int from 0 through 999999.
     """
@@ -248,14 +283,14 @@
 # But it does not seem possible to expose a different structure
 # for types defined in a python module like lib/datetime.py.
 
-@cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DELTA_GET_DAYS(space, w_obj):
     return space.int_w(space.getattr(w_obj, space.wrap("days")))
 
-@cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DELTA_GET_SECONDS(space, w_obj):
     return space.int_w(space.getattr(w_obj, space.wrap("seconds")))
 
-@cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DELTA_GET_MICROSECONDS(space, w_obj):
     return space.int_w(space.getattr(w_obj, space.wrap("microseconds")))
diff --git a/pypy/module/cpyext/floatobject.py 
b/pypy/module/cpyext/floatobject.py
--- a/pypy/module/cpyext/floatobject.py
+++ b/pypy/module/cpyext/floatobject.py
@@ -48,7 +48,7 @@
 def PyFloat_AsDouble(space, w_obj):
     return space.float_w(space.float(w_obj))
 
-@cpython_api([PyObject], lltype.Float, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], lltype.Float, error=CANNOT_FAIL)
 def PyFloat_AS_DOUBLE(space, w_float):
     """Return a C double representation of the contents of w_float, but
     without error checking."""
diff --git a/pypy/module/cpyext/include/datetime.h 
b/pypy/module/cpyext/include/datetime.h
--- a/pypy/module/cpyext/include/datetime.h
+++ b/pypy/module/cpyext/include/datetime.h
@@ -12,6 +12,13 @@
     PyTypeObject *TimeType;
     PyTypeObject *DeltaType;
     PyTypeObject *TZInfoType;
+
+    /* constructors */
+    PyObject *(*Date_FromDate)(int, int, int, PyTypeObject*);
+    PyObject *(*DateTime_FromDateAndTime)(int, int, int, int, int, int, int,
+        PyObject*, PyTypeObject*);
+    PyObject *(*Time_FromTime)(int, int, int, int, PyObject*, PyTypeObject*);
+    PyObject *(*Delta_FromDelta)(int, int, int, int, PyTypeObject*);
 } PyDateTime_CAPI;
 
 PyAPI_DATA(PyDateTime_CAPI*) PyDateTimeAPI;
@@ -41,6 +48,22 @@
     PyObject_HEAD
 } PyDateTime_TZInfo;
 
+/* Macros for accessing constructors in a simplified fashion. */
+#define PyDate_FromDate(year, month, day) \
+    PyDateTimeAPI->Date_FromDate(year, month, day, PyDateTimeAPI->DateType)
+
+#define PyDateTime_FromDateAndTime(year, month, day, hour, min, sec, usec) \
+    PyDateTimeAPI->DateTime_FromDateAndTime(year, month, day, hour, \
+        min, sec, usec, Py_None, PyDateTimeAPI->DateTimeType)
+
+#define PyTime_FromTime(hour, minute, second, usecond) \
+    PyDateTimeAPI->Time_FromTime(hour, minute, second, usecond, \
+        Py_None, PyDateTimeAPI->TimeType)
+
+#define PyDelta_FromDSU(days, seconds, useconds) \
+    PyDateTimeAPI->Delta_FromDelta(days, seconds, useconds, 1, \
+        PyDateTimeAPI->DeltaType)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/pypy/module/cpyext/include/listobject.h 
b/pypy/module/cpyext/include/listobject.h
--- a/pypy/module/cpyext/include/listobject.h
+++ b/pypy/module/cpyext/include/listobject.h
@@ -1,1 +1,1 @@
-#define PyList_GET_ITEM PyList_GetItem
+#define PyList_GET_ITEM(o, i) PyList_GetItem((PyObject*)(o), (i))
diff --git a/pypy/module/cpyext/intobject.py b/pypy/module/cpyext/intobject.py
--- a/pypy/module/cpyext/intobject.py
+++ b/pypy/module/cpyext/intobject.py
@@ -104,7 +104,7 @@
         num = space.bigint_w(w_int)
         return num.ulonglongmask()
 
-@cpython_api([PyObject], lltype.Signed, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], lltype.Signed, error=CANNOT_FAIL)
 def PyInt_AS_LONG(space, w_int):
     """Return the value of the object w_int. No error checking is performed."""
     return space.int_w(w_int)
diff --git a/pypy/module/cpyext/listobject.py b/pypy/module/cpyext/listobject.py
--- a/pypy/module/cpyext/listobject.py
+++ b/pypy/module/cpyext/listobject.py
@@ -21,7 +21,7 @@
     """
     return space.newlist([None] * len)
 
-@cpython_api([PyObject, Py_ssize_t, PyObject], PyObject, error=CANNOT_FAIL,
+@cpython_api([rffi.VOIDP, Py_ssize_t, PyObject], PyObject, error=CANNOT_FAIL,
              result_borrowed=True)
 def PyList_SET_ITEM(space, w_list, index, w_item):
     """Macro form of PyList_SetItem() without error checking. This is normally
@@ -87,7 +87,7 @@
     space.call_method(space.w_list, "insert", w_list, space.wrap(index), 
w_item)
     return 0
 
-@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], Py_ssize_t, error=CANNOT_FAIL)
 def PyList_GET_SIZE(space, w_list):
     """Macro form of PyList_Size() without error checking.
     """
diff --git a/pypy/module/cpyext/modsupport.py b/pypy/module/cpyext/modsupport.py
--- a/pypy/module/cpyext/modsupport.py
+++ b/pypy/module/cpyext/modsupport.py
@@ -113,7 +113,7 @@
     w_type = space.gettypeobject(Module.typedef)
     w_obj_type = space.type(w_obj)
     return int(space.is_w(w_type, w_obj_type) or
-               space.is_true(space.issubtype(w_obj_type, w_type)))
+               space.issubtype_w(w_obj_type, w_type))
 
 @cpython_api([PyObject], PyObject, result_borrowed=True)
 def PyModule_GetDict(space, w_mod):
diff --git a/pypy/module/cpyext/ndarrayobject.py 
b/pypy/module/cpyext/ndarrayobject.py
--- a/pypy/module/cpyext/ndarrayobject.py
+++ b/pypy/module/cpyext/ndarrayobject.py
@@ -35,7 +35,7 @@
     w_obj_type = space.type(w_obj)
     w_type = space.gettypeobject(W_NDimArray.typedef)
     return (space.is_w(w_obj_type, w_type) or
-            space.is_true(space.issubtype(w_obj_type, w_type)))
+            space.issubtype_w(w_obj_type, w_type))
 
 @cpython_api([PyObject], rffi.INT_real, error=CANNOT_FAIL, header=HEADER)
 def _PyArray_CheckExact(space, w_obj):
diff --git a/pypy/module/cpyext/pyfile.py b/pypy/module/cpyext/pyfile.py
--- a/pypy/module/cpyext/pyfile.py
+++ b/pypy/module/cpyext/pyfile.py
@@ -1,10 +1,10 @@
 from rpython.rtyper.lltypesystem import rffi, lltype
 from pypy.module.cpyext.api import (
-    cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, build_type_checkers, fdopen,
-    fileno)
+    cpython_api, CANNOT_FAIL, CONST_STRING, FILEP, build_type_checkers, fdopen)
 from pypy.module.cpyext.pyobject import PyObject
 from pypy.module.cpyext.object import Py_PRINT_RAW
-from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.error import (OperationError, oefmt, 
+    exception_from_saved_errno)
 from pypy.module._file.interp_file import W_File
 
 PyFile_Check, PyFile_CheckExact = build_type_checkers("File", W_File)
@@ -45,16 +45,29 @@
     w_mode = space.wrap(rffi.charp2str(mode))
     return space.call_method(space.builtin, 'file', w_filename, w_mode)
 
-@cpython_api([PyObject], FILEP, error=CANNOT_FAIL)
+@cpython_api([PyObject], FILEP, error=lltype.nullptr(FILEP.TO))
 def PyFile_AsFile(space, w_p):
     """Return the file object associated with p as a FILE*.
     
     If the caller will ever use the returned FILE* object while
     the GIL is released it must also call the PyFile_IncUseCount() and
     PyFile_DecUseCount() functions as appropriate."""
+    if not PyFile_Check(space, w_p):
+        raise oefmt(space.w_IOError, 'first argument must be an open file')
     assert isinstance(w_p, W_File)
-    return fdopen(space.int_w(space.call_method(w_p, 'fileno')), 
-                     w_p.mode)
+    try:
+        fd = space.int_w(space.call_method(w_p, 'fileno'))
+        mode = w_p.mode
+    except OperationError as e:
+        raise oefmt(space.w_IOError, 'could not call fileno') 
+    if (fd < 0 or not mode or mode[0] not in ['r', 'w', 'a', 'U'] or
+        ('U' in mode and ('w' in mode or 'a' in mode))):
+        raise oefmt(space.w_IOError, 'invalid fileno or mode') 
+    ret = fdopen(fd, mode)
+    if not ret:
+        raise exception_from_saved_errno(space, space.w_IOError)
+    return ret
+        
 
 @cpython_api([FILEP, CONST_STRING, CONST_STRING, rffi.VOIDP], PyObject)
 def PyFile_FromFile(space, fp, name, mode, close):
diff --git a/pypy/module/cpyext/sequence.py b/pypy/module/cpyext/sequence.py
--- a/pypy/module/cpyext/sequence.py
+++ b/pypy/module/cpyext/sequence.py
@@ -54,7 +54,7 @@
     except OperationError:
         raise OperationError(space.w_TypeError, space.wrap(rffi.charp2str(m)))
 
-@cpython_api([PyObject, Py_ssize_t], PyObject, result_borrowed=True)
+@cpython_api([rffi.VOIDP, Py_ssize_t], PyObject, result_borrowed=True)
 def PySequence_Fast_GET_ITEM(space, w_obj, index):
     """Return the ith element of o, assuming that o was returned by
     PySequence_Fast(), o is not NULL, and that i is within bounds.
@@ -67,7 +67,7 @@
                 "PySequence_Fast_GET_ITEM called but object is not a list or "
                 "sequence")
 
-@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], Py_ssize_t, error=CANNOT_FAIL)
 def PySequence_Fast_GET_SIZE(space, w_obj):
     """Returns the length of o, assuming that o was returned by
     PySequence_Fast() and that o is not NULL.  The size can also be
@@ -82,7 +82,7 @@
                 "PySequence_Fast_GET_SIZE called but object is not a list or "
                 "sequence")
 
-@cpython_api([PyObject], PyObjectP)
+@cpython_api([rffi.VOIDP], PyObjectP)
 def PySequence_Fast_ITEMS(space, w_obj):
     """Return the underlying array of PyObject pointers.  Assumes that o was 
returned
     by PySequence_Fast() and o is not NULL.
@@ -119,7 +119,7 @@
     space.delslice(w_obj, space.wrap(start), space.wrap(end))
     return 0
 
-@cpython_api([PyObject, Py_ssize_t], PyObject)
+@cpython_api([rffi.VOIDP, Py_ssize_t], PyObject)
 def PySequence_ITEM(space, w_obj, i):
     """Return the ith element of o or NULL on failure. Macro form of
     PySequence_GetItem() but without checking that
diff --git a/pypy/module/cpyext/setobject.py b/pypy/module/cpyext/setobject.py
--- a/pypy/module/cpyext/setobject.py
+++ b/pypy/module/cpyext/setobject.py
@@ -74,7 +74,7 @@
     space.call_method(space.w_set, 'clear', w_set)
     return 0
 
-@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], Py_ssize_t, error=CANNOT_FAIL)
 def PySet_GET_SIZE(space, w_s):
     """Macro form of PySet_Size() without error checking."""
     return space.int_w(space.len(w_s))
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -78,8 +78,7 @@
     args_w = space.fixedview(w_args)
     ref = make_ref(space, w_self)
     if (not ref.c_ob_type.c_tp_flags & Py_TPFLAGS_CHECKTYPES and
-        not space.is_true(space.issubtype(space.type(args_w[0]),
-                                         space.type(w_self)))):
+        not space.issubtype_w(space.type(args_w[0]), space.type(w_self))):
         return space.w_NotImplemented
     Py_DecRef(space, ref)
     return generic_cpy_call(space, func_binary, w_self, args_w[0])
@@ -90,8 +89,7 @@
     args_w = space.fixedview(w_args)
     ref = make_ref(space, w_self)
     if (not ref.c_ob_type.c_tp_flags & Py_TPFLAGS_CHECKTYPES and
-        not space.is_true(space.issubtype(space.type(args_w[0]),
-                                         space.type(w_self)))):
+        not space.issubtype_w(space.type(args_w[0]), space.type(w_self))):
         return space.w_NotImplemented
     Py_DecRef(space, ref)
     return generic_cpy_call(space, func_binary, args_w[0], w_self)
@@ -113,8 +111,7 @@
     args_w = space.fixedview(w_args)
     ref = make_ref(space, w_self)
     if (not ref.c_ob_type.c_tp_flags & Py_TPFLAGS_CHECKTYPES and
-        not space.is_true(space.issubtype(space.type(args_w[0]),
-                                         space.type(w_self)))):
+        not space.issubtype_w(space.type(args_w[0]), space.type(w_self))):
         return space.w_NotImplemented
     Py_DecRef(space, ref)
     arg3 = space.w_None
@@ -346,8 +343,7 @@
     check_num_args(space, w_args, 1)
     w_other, = space.fixedview(w_args)
 
-    if not space.is_true(space.issubtype(space.type(w_self),
-                                         space.type(w_other))):
+    if not space.issubtype_w(space.type(w_self), space.type(w_other)):
         raise oefmt(space.w_TypeError,
                     "%T.__cmp__(x,y) requires y to be a '%T', not a '%T'",
                     w_self, w_self, w_other)
diff --git a/pypy/module/cpyext/test/test_bytesobject.py 
b/pypy/module/cpyext/test/test_bytesobject.py
--- a/pypy/module/cpyext/test/test_bytesobject.py
+++ b/pypy/module/cpyext/test/test_bytesobject.py
@@ -288,6 +288,24 @@
         # This does not test much, but at least the refcounts are checked.
         assert module.test_intern_inplace('s') == 's'
 
+    def test_bytes_macros(self):
+        """The PyString_* macros cast, and calls expecting that build."""
+        module = self.import_extension('foo', [
+             ("test_macro_invocations", "METH_NOARGS",
+             """
+                PyObject* o = PyString_FromString("");
+                PyStringObject* u = (PyStringObject*)o;
+
+                PyString_GET_SIZE(u);
+                PyString_GET_SIZE(o);
+
+                PyString_AS_STRING(o);
+                PyString_AS_STRING(u);
+
+                return o;
+             """)])
+        assert module.test_macro_invocations() == ''
+
     def test_hash_and_state(self):
         module = self.import_extension('foo', [
             ("test_hash", "METH_VARARGS",
diff --git a/pypy/module/cpyext/test/test_datetime.py 
b/pypy/module/cpyext/test/test_datetime.py
--- a/pypy/module/cpyext/test/test_datetime.py
+++ b/pypy/module/cpyext/test/test_datetime.py
@@ -4,7 +4,8 @@
 
 class TestDatetime(BaseApiTest):
     def test_date(self, space, api):
-        w_date = api.PyDate_FromDate(2010, 06, 03)
+        date_api = api._PyDateTime_Import()
+        w_date = api._PyDate_FromDate(2010, 06, 03, date_api.c_DateType)
         assert space.unwrap(space.str(w_date)) == '2010-06-03'
 
         assert api.PyDate_Check(w_date)
@@ -15,7 +16,9 @@
         assert api.PyDateTime_GET_DAY(w_date) == 3
 
     def test_time(self, space, api):
-        w_time = api.PyTime_FromTime(23, 15, 40, 123456)
+        date_api = api._PyDateTime_Import()
+        w_time = api._PyTime_FromTime(23, 15, 40, 123456,
+                                      space.w_None, date_api.c_TimeType)
         assert space.unwrap(space.str(w_time)) == '23:15:40.123456'
 
         assert api.PyTime_Check(w_time)
@@ -27,8 +30,10 @@
         assert api.PyDateTime_TIME_GET_MICROSECOND(w_time) == 123456
 
     def test_datetime(self, space, api):
-        w_date = api.PyDateTime_FromDateAndTime(
-            2010, 06, 03, 23, 15, 40, 123456)
+        date_api = api._PyDateTime_Import()
+        w_date = api._PyDateTime_FromDateAndTime(
+            2010, 06, 03, 23, 15, 40, 123456,
+            space.w_None, date_api.c_DateTimeType)
         assert space.unwrap(space.str(w_date)) == '2010-06-03 23:15:40.123456'
 
         assert api.PyDateTime_Check(w_date)
@@ -45,6 +50,7 @@
         assert api.PyDateTime_DATE_GET_MICROSECOND(w_date) == 123456
 
     def test_delta(self, space, api):
+        date_api = api._PyDateTime_Import()
         w_delta = space.appexec(
             [space.wrap(3), space.wrap(15)], """(days, seconds):
             from datetime import timedelta
@@ -53,7 +59,7 @@
         assert api.PyDelta_Check(w_delta)
         assert api.PyDelta_CheckExact(w_delta)
 
-        w_delta = api.PyDelta_FromDSU(10, 20, 30)
+        w_delta = api._PyDelta_FromDelta(10, 20, 30, True, 
date_api.c_DeltaType)
         assert api.PyDelta_Check(w_delta)
         assert api.PyDelta_CheckExact(w_delta)
 
@@ -117,3 +123,139 @@
                                       datetime.timedelta,
                                       datetime.tzinfo)
         module.clear_types()
+
+    def test_constructors(self):
+        module = self.import_extension('foo', [
+            ("new_date", "METH_NOARGS",
+             """ PyDateTime_IMPORT;
+                 return PyDateTimeAPI->Date_FromDate(
+                    2000, 6, 6, PyDateTimeAPI->DateType);
+             """),
+            ("new_time", "METH_NOARGS",
+             """ PyDateTime_IMPORT;
+                 return PyDateTimeAPI->Time_FromTime(
+                    6, 6, 6, 6, Py_None, PyDateTimeAPI->TimeType);
+             """),
+            ("new_datetime", "METH_NOARGS",
+             """ PyDateTime_IMPORT;
+                 return PyDateTimeAPI->DateTime_FromDateAndTime(
+                    2000, 6, 6, 6, 6, 6, 6, Py_None,
+                    PyDateTimeAPI->DateTimeType);
+             """),
+        ])
+        import datetime
+        assert module.new_date() == datetime.date(2000, 6, 6)
+        assert module.new_time() == datetime.time(6, 6, 6, 6)
+        assert module.new_datetime() == datetime.datetime(
+            2000, 6, 6, 6, 6, 6, 6)
+
+    def test_macros(self):
+        module = self.import_extension('foo', [
+            ("test_date_macros", "METH_NOARGS",
+             """
+                 PyObject* obj;
+                 PyDateTime_Date* d;
+                 PyDateTime_IMPORT;
+                 if (!PyDateTimeAPI) {
+                     PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
+                     return NULL;
+                 }
+                 obj = PyDate_FromDate(2000, 6, 6);
+                 d = (PyDateTime_Date*)obj;
+
+                 PyDateTime_GET_YEAR(obj);
+                 PyDateTime_GET_YEAR(d);
+
+                 PyDateTime_GET_MONTH(obj);
+                 PyDateTime_GET_MONTH(d);
+
+                 PyDateTime_GET_DAY(obj);
+                 PyDateTime_GET_DAY(d);
+
+                 return obj;
+             """),
+            ("test_datetime_macros", "METH_NOARGS",
+             """
+                 PyDateTime_IMPORT;
+                 if (!PyDateTimeAPI) {
+                     PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
+                     return NULL;
+                 }
+                 PyObject* obj = PyDateTime_FromDateAndTime(2000, 6, 6, 6, 6, 
6, 6);
+                 PyDateTime_DateTime* dt = (PyDateTime_DateTime*)obj;
+
+                 PyDateTime_GET_YEAR(obj);
+                 PyDateTime_GET_YEAR(dt);
+
+                 PyDateTime_GET_MONTH(obj);
+                 PyDateTime_GET_MONTH(dt);
+
+                 PyDateTime_GET_DAY(obj);
+                 PyDateTime_GET_DAY(dt);
+
+                 PyDateTime_DATE_GET_HOUR(obj);
+                 PyDateTime_DATE_GET_HOUR(dt);
+
+                 PyDateTime_DATE_GET_MINUTE(obj);
+                 PyDateTime_DATE_GET_MINUTE(dt);
+
+                 PyDateTime_DATE_GET_SECOND(obj);
+                 PyDateTime_DATE_GET_SECOND(dt);
+
+                 PyDateTime_DATE_GET_MICROSECOND(obj);
+                 PyDateTime_DATE_GET_MICROSECOND(dt);
+
+                 return obj;
+             """),
+            ("test_time_macros", "METH_NOARGS",
+             """
+                 PyDateTime_IMPORT;
+                 if (!PyDateTimeAPI) {
+                     PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
+                     return NULL;
+                 }
+                 PyObject* obj = PyTime_FromTime(6, 6, 6, 6);
+                 PyDateTime_Time* t = (PyDateTime_Time*)obj;
+
+                 PyDateTime_TIME_GET_HOUR(obj);
+                 PyDateTime_TIME_GET_HOUR(t);
+
+                 PyDateTime_TIME_GET_MINUTE(obj);
+                 PyDateTime_TIME_GET_MINUTE(t);
+
+                 PyDateTime_TIME_GET_SECOND(obj);
+                 PyDateTime_TIME_GET_SECOND(t);
+
+                 PyDateTime_TIME_GET_MICROSECOND(obj);
+                 PyDateTime_TIME_GET_MICROSECOND(t);
+
+                 return obj;
+             """),
+            ("test_delta_macros", "METH_NOARGS",
+             """
+                 PyDateTime_IMPORT;
+                 if (!PyDateTimeAPI) {
+                     PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
+                     return NULL;
+                 }
+                 PyObject* obj = PyDelta_FromDSU(6, 6, 6);
+                 PyDateTime_Delta* delta = (PyDateTime_Delta*)obj;
+
+                 PyDateTime_DELTA_GET_DAYS(obj);
+                 PyDateTime_DELTA_GET_DAYS(delta);
+
+                 PyDateTime_DELTA_GET_SECONDS(obj);
+                 PyDateTime_DELTA_GET_SECONDS(delta);
+
+                 PyDateTime_DELTA_GET_MICROSECONDS(obj);
+                 PyDateTime_DELTA_GET_MICROSECONDS(delta);
+
+                 return obj;
+             """),
+            ])
+        import datetime
+        assert module.test_date_macros() == datetime.date(2000, 6, 6)
+        assert module.test_datetime_macros() == datetime.datetime(
+            2000, 6, 6, 6, 6, 6, 6)
+        assert module.test_time_macros() == datetime.time(6, 6, 6, 6)
+        assert module.test_delta_macros() == datetime.timedelta(6, 6, 6)
diff --git a/pypy/module/cpyext/test/test_floatobject.py 
b/pypy/module/cpyext/test/test_floatobject.py
--- a/pypy/module/cpyext/test/test_floatobject.py
+++ b/pypy/module/cpyext/test/test_floatobject.py
@@ -77,3 +77,19 @@
         neginf = module.return_neginf()
         assert neginf < 0
         assert math.isinf(neginf)
+
+    def test_macro_accepts_wrong_pointer_type(self):
+        import math
+
+        module = self.import_extension('foo', [
+            ("test_macros", "METH_NOARGS",
+             """
+             PyObject* o = PyFloat_FromDouble(1.0);
+             // no PyFloatObject
+             char* dumb_pointer = (char*)o;
+
+             PyFloat_AS_DOUBLE(o);
+             PyFloat_AS_DOUBLE(dumb_pointer);
+
+             Py_RETURN_NONE;"""),
+            ])
diff --git a/pypy/module/cpyext/test/test_intobject.py 
b/pypy/module/cpyext/test/test_intobject.py
--- a/pypy/module/cpyext/test/test_intobject.py
+++ b/pypy/module/cpyext/test/test_intobject.py
@@ -191,3 +191,17 @@
         i = mod.test_int()
         assert isinstance(i, int)
         assert i == 42
+
+    def test_int_macros(self):
+        mod = self.import_extension('foo', [
+                ("test_macros", "METH_NOARGS",
+                """
+                PyObject * obj = PyInt_FromLong(42);
+                PyIntObject * i = (PyIntObject*)obj;
+                PyInt_AS_LONG(obj);
+                PyInt_AS_LONG(i);
+                Py_RETURN_NONE;
+                """
+                ),
+                ])
+
diff --git a/pypy/module/cpyext/test/test_listobject.py 
b/pypy/module/cpyext/test/test_listobject.py
--- a/pypy/module/cpyext/test/test_listobject.py
+++ b/pypy/module/cpyext/test/test_listobject.py
@@ -137,6 +137,33 @@
         module.setlistitem(l,0)
         assert l == [None, 2, 3]
 
+    def test_list_macros(self):
+        """The PyList_* macros cast, and calls expecting that build."""
+        module = self.import_extension('foo', [
+            ("test_macro_invocations", "METH_NOARGS",
+             """
+             PyObject* o = PyList_New(2);
+             PyListObject* l = (PyListObject*)o;
+
+
+             Py_INCREF(o);
+             PyList_SET_ITEM(o, 0, o);
+             Py_INCREF(o);
+             PyList_SET_ITEM(l, 1, o);
+
+             PyList_GET_ITEM(o, 0);
+             PyList_GET_ITEM(l, 1);
+
+             PyList_GET_SIZE(o);
+             PyList_GET_SIZE(l);
+
+             return o;
+             """
+            )
+        ])
+        x = module.test_macro_invocations()
+        assert x[0] is x[1] is x
+
     def test_get_item_macro(self):
         module = self.import_extension('foo', [
              ("test_get_item", "METH_NOARGS",
diff --git a/pypy/module/cpyext/test/test_sequence.py 
b/pypy/module/cpyext/test/test_sequence.py
--- a/pypy/module/cpyext/test/test_sequence.py
+++ b/pypy/module/cpyext/test/test_sequence.py
@@ -155,6 +155,29 @@
         result = api.PySequence_Index(w_gen, w_tofind)
         assert result == 4
 
+class AppTestSetObject(AppTestCpythonExtensionBase):
+    def test_sequence_macro_cast(self):
+        module = self.import_extension('foo', [
+            ("test_macro_cast", "METH_NOARGS",
+             """
+             PyObject *o = PyList_New(0);
+             PyListObject* l;
+             PyList_Append(o, o);
+             l = (PyListObject*)o;
+
+             PySequence_Fast_GET_ITEM(o, 0);
+             PySequence_Fast_GET_ITEM(l, 0);
+
+             PySequence_Fast_GET_SIZE(o);
+             PySequence_Fast_GET_SIZE(l);
+
+             PySequence_ITEM(o, 0);
+             PySequence_ITEM(l, 0);
+
+             return o;
+             """
+            )
+        ])
 class TestCPyListStrategy(BaseApiTest):
     def test_getitem_setitem(self, space, api):
         w_l = space.wrap([1, 2, 3, 4])
diff --git a/pypy/module/cpyext/test/test_setobject.py 
b/pypy/module/cpyext/test/test_setobject.py
--- a/pypy/module/cpyext/test/test_setobject.py
+++ b/pypy/module/cpyext/test/test_setobject.py
@@ -2,6 +2,7 @@
 
 from pypy.module.cpyext.pyobject import PyObject, PyObjectP, make_ref, from_ref
 from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 from rpython.rtyper.lltypesystem import rffi, lltype
 
 
@@ -45,3 +46,20 @@
         w_frozenset = space.newfrozenset([space.wrap(i) for i in [1, 2, 3, 4]])
         assert api.PyAnySet_CheckExact(w_set)
         assert api.PyAnySet_CheckExact(w_frozenset)
+
+class AppTestSetObject(AppTestCpythonExtensionBase):
+    def test_set_macro_cast(self):
+        module = self.import_extension('foo', [
+            ("test_macro_cast", "METH_NOARGS",
+             """
+             PyObject* o = PySet_New(NULL);
+             // no PySetObject
+             char* dumb_pointer = (char*) o;
+
+             PySet_GET_SIZE(o);
+             PySet_GET_SIZE(dumb_pointer);
+
+             return o;
+             """
+            )
+        ])
diff --git a/pypy/module/cpyext/test/test_translate.py 
b/pypy/module/cpyext/test/test_translate.py
--- a/pypy/module/cpyext/test/test_translate.py
+++ b/pypy/module/cpyext/test/test_translate.py
@@ -11,11 +11,11 @@
     FT = lltype.FuncType([], lltype.Signed)
     FTPTR = lltype.Ptr(FT)
 
-    def make_wrapper(space, func, gil=None):
+    def make_wrapper(self, space):
         def wrapper():
-            return func(space)
+            return self.callable(space)
         return wrapper
-    monkeypatch.setattr(pypy.module.cpyext.api, 'make_wrapper', make_wrapper)
+    monkeypatch.setattr(pypy.module.cpyext.api.ApiFunction, '_make_wrapper', 
make_wrapper)
 
     @specialize.memo()
     def get_tp_function(space, typedef):
diff --git a/pypy/module/cpyext/test/test_typeobject.py 
b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -744,7 +744,7 @@
                 int intval;
                 PyObject *name;
 
-                if (!PyArg_ParseTuple(args, "l", &intval))
+                if (!PyArg_ParseTuple(args, "i", &intval))
                     return NULL;
 
                 IntLike_Type.tp_flags |= Py_TPFLAGS_DEFAULT;
diff --git a/pypy/module/cpyext/test/test_unicodeobject.py 
b/pypy/module/cpyext/test/test_unicodeobject.py
--- a/pypy/module/cpyext/test/test_unicodeobject.py
+++ b/pypy/module/cpyext/test/test_unicodeobject.py
@@ -111,6 +111,26 @@
         assert isinstance(res, str)
         assert res == 'caf?'
 
+    def test_unicode_macros(self):
+        """The PyUnicode_* macros cast, and calls expecting that build."""
+        module = self.import_extension('foo', [
+             ("test_macro_invocations", "METH_NOARGS",
+             """
+                PyObject* o = PyUnicode_FromString("");
+                PyUnicodeObject* u = (PyUnicodeObject*)o;
+
+                PyUnicode_GET_SIZE(u);
+                PyUnicode_GET_SIZE(o);
+
+                PyUnicode_GET_DATA_SIZE(u);
+                PyUnicode_GET_DATA_SIZE(o);
+
+                PyUnicode_AS_UNICODE(o);
+                PyUnicode_AS_UNICODE(u);
+                return o;
+             """)])
+        assert module.test_macro_invocations() == u''
+
 class TestUnicode(BaseApiTest):
     def test_unicodeobject(self, space, api):
         assert api.PyUnicode_GET_SIZE(space.wrap(u'sp&#65533;m')) == 4
diff --git a/pypy/module/cpyext/test/test_weakref.py 
b/pypy/module/cpyext/test/test_weakref.py
--- a/pypy/module/cpyext/test/test_weakref.py
+++ b/pypy/module/cpyext/test/test_weakref.py
@@ -7,7 +7,6 @@
         w_ref = api.PyWeakref_NewRef(w_obj, space.w_None)
         assert w_ref is not None
         assert space.is_w(api.PyWeakref_GetObject(w_ref), w_obj)
-        assert space.is_w(api.PyWeakref_GET_OBJECT(w_ref), w_obj)
         assert space.is_w(api.PyWeakref_LockObject(w_ref), w_obj)
 
         w_obj = space.newtuple([])
@@ -34,3 +33,26 @@
         del w_obj
         import gc; gc.collect()
         assert space.is_w(api.PyWeakref_LockObject(w_ref), space.w_None)
+
+
+class AppTestWeakReference(AppTestCpythonExtensionBase):
+
+    def test_weakref_macro(self):
+        module = self.import_extension('foo', [
+            ("test_macro_cast", "METH_NOARGS",
+             """
+             // PyExc_Warning is some weak-reffable PyObject*.
+             char* dumb_pointer;
+             PyObject* weakref_obj = PyWeakref_NewRef(PyExc_Warning, NULL);
+             if (!weakref_obj) return weakref_obj;
+             // No public PyWeakReference type.
+             dumb_pointer = (char*) weakref_obj;
+
+             PyWeakref_GET_OBJECT(weakref_obj);
+             PyWeakref_GET_OBJECT(dumb_pointer);
+
+             return weakref_obj;
+             """
+            )
+        ])
+        module.test_macro_cast()
diff --git a/pypy/module/cpyext/tupleobject.py 
b/pypy/module/cpyext/tupleobject.py
--- a/pypy/module/cpyext/tupleobject.py
+++ b/pypy/module/cpyext/tupleobject.py
@@ -47,7 +47,7 @@
 def tuple_check_ref(space, ref):
     w_type = from_ref(space, rffi.cast(PyObject, ref.c_ob_type))
     return (w_type is space.w_tuple or
-            space.is_true(space.issubtype(w_type, space.w_tuple)))
+            space.issubtype_w(w_type, space.w_tuple))
 
 def new_empty_tuple(space, length):
     """
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -18,8 +18,9 @@
     Py_TPFLAGS_HEAPTYPE, METH_VARARGS, METH_KEYWORDS, CANNOT_FAIL,
     Py_TPFLAGS_HAVE_GETCHARBUFFER, build_type_checkers, StaticObjectBuilder,
     PyObjectFields, Py_TPFLAGS_BASETYPE)
-from pypy.module.cpyext.methodobject import (
-    PyDescr_NewWrapper, PyCFunction_NewEx, PyCFunction_typedef, PyMethodDef)
+from pypy.module.cpyext.methodobject import (W_PyCClassMethodObject,
+    PyDescr_NewWrapper, PyCFunction_NewEx, PyCFunction_typedef, PyMethodDef,
+    W_PyCMethodObject, W_PyCFunctionObject)
 from pypy.module.cpyext.modsupport import convert_method_defs
 from pypy.module.cpyext.pyobject import (
     PyObject, make_ref, create_ref, from_ref, get_typedescr, make_typedescr,
@@ -125,6 +126,14 @@
 cpython_struct("PyGetSetDescrObject", PyGetSetDescrObjectFields,
                PyGetSetDescrObjectStruct, level=2)
 
+PyMethodDescrObjectStruct = lltype.ForwardReference()
+PyMethodDescrObject = lltype.Ptr(PyMethodDescrObjectStruct)
+PyMethodDescrObjectFields = PyDescrObjectFields + (
+    ("d_method", lltype.Ptr(PyMethodDef)),
+    )
+cpython_struct("PyMethodDescrObject", PyMethodDescrObjectFields,
+               PyMethodDescrObjectStruct, level=2)
+
 @bootstrap_function
 def init_memberdescrobject(space):
     make_typedescr(W_MemberDescr.typedef,
@@ -136,6 +145,16 @@
                    basestruct=PyGetSetDescrObject.TO,
                    attach=getsetdescr_attach,
                    )
+    make_typedescr(W_PyCClassMethodObject.typedef,
+                   basestruct=PyMethodDescrObject.TO,
+                   attach=methoddescr_attach,
+                   realize=classmethoddescr_realize,
+                   )
+    make_typedescr(W_PyCMethodObject.typedef,
+                   basestruct=PyMethodDescrObject.TO,
+                   attach=methoddescr_attach,
+                   realize=methoddescr_realize,
+                   )
 
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to