[pypy-commit] pypy release-2.6.x: merge default into release

mattip noreply at buildbot.pypy.org
Thu May 28 16:15:01 CEST 2015


Author: mattip <matti.picus at gmail.com>
Branch: release-2.6.x
Changeset: r77653:e03971291f3a
Date: 2015-05-28 17:14 +0300
http://bitbucket.org/pypy/pypy/changeset/e03971291f3a/

Log:	merge default into release

diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -505,7 +505,7 @@
                             "modules")
         mkpath(tmpdir)
         ext, updated = recompile(self, module_name,
-                                 source, tmpdir=tmpdir,
+                                 source, tmpdir=tmpdir, extradir=tmpdir,
                                  source_extension=source_extension,
                                  call_c_compiler=False, **kwds)
         if verbose:
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
--- a/lib_pypy/cffi/recompiler.py
+++ b/lib_pypy/cffi/recompiler.py
@@ -1148,8 +1148,14 @@
                 raise IOError
         return False     # already up-to-date
     except IOError:
-        with open(target_file, 'w') as f1:
+        tmp_file = '%s.~%d' % (target_file, os.getpid())
+        with open(tmp_file, 'w') as f1:
             f1.write(output)
+        try:
+            os.rename(tmp_file, target_file)
+        except OSError:
+            os.unlink(target_file)
+            os.rename(tmp_file, target_file)
         return True
 
 def make_c_source(ffi, module_name, preamble, target_c_file):
@@ -1169,7 +1175,7 @@
     return os.path.join(outputdir, *parts), parts
 
 def recompile(ffi, module_name, preamble, tmpdir='.', call_c_compiler=True,
-              c_file=None, source_extension='.c', **kwds):
+              c_file=None, source_extension='.c', extradir=None, **kwds):
     if not isinstance(module_name, str):
         module_name = module_name.encode('ascii')
     if ffi._windows_unicode:
@@ -1178,6 +1184,8 @@
         if c_file is None:
             c_file, parts = _modname_to_file(tmpdir, module_name,
                                              source_extension)
+            if extradir:
+                parts = [extradir] + parts
             ext_c_file = os.path.join(*parts)
         else:
             ext_c_file = c_file
diff --git a/lib_pypy/cffi/setuptools_ext.py b/lib_pypy/cffi/setuptools_ext.py
--- a/lib_pypy/cffi/setuptools_ext.py
+++ b/lib_pypy/cffi/setuptools_ext.py
@@ -108,13 +108,11 @@
 def _add_py_module(dist, ffi, module_name):
     from distutils.dir_util import mkpath
     from distutils.command.build_py import build_py
+    from distutils.command.build_ext import build_ext
     from distutils import log
     from cffi import recompiler
 
-    def make_mod(tmpdir):
-        module_path = module_name.split('.')
-        module_path[-1] += '.py'
-        py_file = os.path.join(tmpdir, *module_path)
+    def generate_mod(py_file):
         log.info("generating cffi module %r" % py_file)
         mkpath(os.path.dirname(py_file))
         updated = recompiler.make_py_source(ffi, module_name, py_file)
@@ -125,9 +123,25 @@
     class build_py_make_mod(base_class):
         def run(self):
             base_class.run(self)
-            make_mod(self.build_lib)
+            module_path = module_name.split('.')
+            module_path[-1] += '.py'
+            generate_mod(os.path.join(self.build_lib, *module_path))
     dist.cmdclass['build_py'] = build_py_make_mod
 
+    # the following is only for "build_ext -i"
+    base_class_2 = dist.cmdclass.get('build_ext', build_ext)
+    class build_ext_make_mod(base_class_2):
+        def run(self):
+            base_class_2.run(self)
+            if self.inplace:
+                # from get_ext_fullpath() in distutils/command/build_ext.py
+                module_path = module_name.split('.')
+                package = '.'.join(module_path[:-1])
+                build_py = self.get_finalized_command('build_py')
+                package_dir = build_py.get_package_dir(package)
+                file_name = module_path[-1] + '.py'
+                generate_mod(os.path.join(package_dir, file_name))
+    dist.cmdclass['build_ext'] = build_ext_make_mod
 
 def cffi_modules(dist, attr, value):
     assert attr == 'cffi_modules'
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -321,7 +321,7 @@
 
 
 def enable_allworkingmodules(config):
-    modules = working_modules
+    modules = working_modules.copy()
     if config.translation.sandbox:
         modules = default_modules
     # ignore names from 'essential_modules', notably 'exceptions', which
diff --git a/pypy/doc/config/objspace.usemodules._vmprof.txt b/pypy/doc/config/objspace.usemodules._vmprof.txt
new file mode 100644
diff --git a/pypy/doc/config/translation.icon.txt b/pypy/doc/config/translation.icon.txt
new file mode 100644
diff --git a/pypy/doc/how-to-release.rst b/pypy/doc/how-to-release.rst
--- a/pypy/doc/how-to-release.rst
+++ b/pypy/doc/how-to-release.rst
@@ -16,40 +16,44 @@
 -------------
 
 * At code freeze make a release branch using release-x.x.x in mercurial
-  Bump the
+  and add a release-specific tag
+* Bump the
   pypy version number in module/sys/version.py and in
-  module/cpyext/include/patchlevel.h. The branch
+  module/cpyext/include/patchlevel.h and . The branch
   will capture the revision number of this change for the release.
+
   Some of the next updates may be done before or after branching; make
   sure things are ported back to the trunk and to the branch as
-  necessary; also update the version number in pypy/doc/conf.py.
+  necessary.
 * update pypy/doc/contributor.rst (and possibly LICENSE)
   pypy/doc/tool/makecontributor.py generates the list of contributors
 * rename pypy/doc/whatsnew_head.rst to whatsnew_VERSION.rst
   create a fresh whatsnew_head.rst after the release
   and add the new file to  pypy/doc/index-of-whatsnew.rst
-* go to pypy/tool/release and run:
-  force-builds.py <release branch>
-
-  The following binaries should be built, however, we need more buildbots:
-    JIT: windows, linux, os/x, armhf, armel
-    no JIT: windows, linux, os/x
-    sandbox: linux, os/x
+* go to pypy/tool/release and run
+  ``force-builds.py <release branch>``
+  The following binaries should be built, however, we need more buildbots
+ - JIT: windows, linux, os/x, armhf, armel
+ - no JIT: windows, linux, os/x
+ - sandbox: linux, os/x
 
 * wait for builds to complete, make sure there are no failures
 * download the builds, repackage binaries. Tag the release version
   and download and repackage source from bitbucket. You may find it
-  convenient to use the repackage.sh script in pypy/tools to do this. 
-  Otherwise, repackage and upload source "-src.tar.bz2" to bitbucket
+  convenient to use the ``repackage.sh`` script in pypy/tools to do this. 
+
+  Otherwise repackage and upload source "-src.tar.bz2" to bitbucket
   and to cobra, as some packagers prefer a clearly labeled source package
- (download e.g.  https://bitbucket.org/pypy/pypy/get/release-2.5.x.tar.bz2,
+  ( download e.g.  https://bitbucket.org/pypy/pypy/get/release-2.5.x.tar.bz2,
   unpack, rename the top-level directory to "pypy-2.5.0-src", repack, and upload)
 
 * Upload binaries to https://bitbucket.org/pypy/pypy/downloads
 
 * write release announcement pypy/doc/release-x.y(.z).txt
-  the release announcement should contain a direct link to the download page
-  and add new files to  pypy/doc/index-of-release-notes.rst
+
+  The release announcement should contain a direct link to the download page
+
+* Add the new files to  pypy/doc/index-of-{whatsnew,release-notes}.rst
 
 * update pypy.org (under extradoc/pypy.org), rebuild and commit
 
@@ -59,4 +63,5 @@
 
 * add a tag on the pypy/jitviewer repo that corresponds to pypy release
 * add a tag on the codespeed web site that corresponds to pypy release
+* update the version number in {rpython,pypy}/doc/conf.py.
 * revise versioning at https://readthedocs.org/projects/pypy
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
@@ -131,9 +131,10 @@
                     g.c_address)
                 assert fetch_funcptr
                 assert w_ct.size > 0
-                with lltype.scoped_alloc(rffi.CCHARP.TO, w_ct.size) as ptr:
-                    fetch_funcptr(ptr)
-                    w_result = w_ct.convert_to_object(ptr)
+                ptr = lltype.malloc(rffi.CCHARP.TO, w_ct.size, flavor='raw')
+                self.ffi._finalizer.free_mems.append(ptr)
+                fetch_funcptr(ptr)
+                w_result = w_ct.convert_to_object(ptr)
                 #
             elif op == cffi_opcode.OP_DLOPEN_FUNC:
                 # For dlopen(): the function of the given 'name'.  We use
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
@@ -66,6 +66,9 @@
     """)
     ffiobject = space.getitem(w_res, space.wrap(0))
     ffiobject._test_recompiler_source_ffi = ffi
+    if not hasattr(space, '_cleanup_ffi'):
+        space._cleanup_ffi = []
+    space._cleanup_ffi.append(ffiobject)
     return w_res
 
 
@@ -84,6 +87,10 @@
         """)
 
     def teardown_method(self, meth):
+        if hasattr(self.space, '_cleanup_ffi'):
+            for ffi in self.space._cleanup_ffi:
+                del ffi.cached_types     # try to prevent cycles
+            del self.space._cleanup_ffi
         self.space.appexec([self._w_modules], """(old_modules):
             import sys
             for key in sys.modules.keys():
@@ -799,3 +806,46 @@
         assert addr(0xABC05) == 47
         assert isinstance(addr, ffi.CData)
         assert ffi.typeof(addr) == ffi.typeof("long(*)(long)")
+
+    def test_issue198(self):
+        ffi, lib = self.prepare("""
+            typedef struct{...;} opaque_t;
+            const opaque_t CONSTANT;
+            int toint(opaque_t);
+        """, 'test_issue198', """
+            typedef int opaque_t;
+            #define CONSTANT ((opaque_t)42)
+            static int toint(opaque_t o) { return o; }
+        """)
+        def random_stuff():
+            pass
+        assert lib.toint(lib.CONSTANT) == 42
+        random_stuff()
+        assert lib.toint(lib.CONSTANT) == 42
+
+    def test_constant_is_not_a_compiler_constant(self):
+        ffi, lib = self.prepare(
+            "static const float almost_forty_two;",
+            'test_constant_is_not_a_compiler_constant', """
+                static float f(void) { return 42.25; }
+                #define almost_forty_two (f())
+            """)
+        assert lib.almost_forty_two == 42.25
+
+    def test_variable_of_unknown_size(self):
+        ffi, lib = self.prepare("""
+            typedef ... opaque_t;
+            opaque_t globvar;
+        """, 'test_constant_of_unknown_size', """
+            typedef char opaque_t[6];
+            opaque_t globvar = "hello";
+        """)
+        # can't read or write it at all
+        e = raises(TypeError, getattr, lib, 'globvar')
+        assert str(e.value) == "'opaque_t' is opaque or not completed yet"
+        e = raises(TypeError, setattr, lib, 'globvar', [])
+        assert str(e.value) == "'opaque_t' is opaque or not completed yet"
+        # but we can get its address
+        p = ffi.addressof(lib, 'globvar')
+        assert ffi.typeof(p) == ffi.typeof('opaque_t *')
+        assert ffi.string(ffi.cast("char *", p), 8) == "hello"
diff --git a/pypy/module/_vmprof/src/fake_pypy_api.c b/pypy/module/_vmprof/src/fake_pypy_api.c
--- a/pypy/module/_vmprof/src/fake_pypy_api.c
+++ b/pypy/module/_vmprof/src/fake_pypy_api.c
@@ -1,21 +1,4 @@
-
-long pypy_jit_stack_depth_at_loc(long x)
-{
-	return 0;
-}
-
-void *pypy_find_codemap_at_addr(long x)
-{
-	return (void *)0;
-}
-
-long pypy_yield_codemap_at_addr(void *x, long y, long *a)
-{
-	return 0;
-}
 
 void pypy_pyframe_execute_frame(void)
 {
 }
-
-volatile int pypy_codemap_currently_invalid = 0;
diff --git a/pypy/module/_vmprof/src/get_custom_offset.c b/pypy/module/_vmprof/src/get_custom_offset.c
--- a/pypy/module/_vmprof/src/get_custom_offset.c
+++ b/pypy/module/_vmprof/src/get_custom_offset.c
@@ -1,3 +1,5 @@
+
+#ifdef PYPY_JIT_CODEMAP
 
 extern volatile int pypy_codemap_currently_invalid;
 
@@ -6,6 +8,8 @@
                                 long *current_pos_addr);
 long pypy_jit_stack_depth_at_loc(long loc);
 
+#endif
+
 
 void vmprof_set_tramp_range(void* start, void* end)
 {
@@ -13,17 +17,26 @@
 
 int custom_sanity_check()
 {
+#ifdef PYPY_JIT_CODEMAP
     return !pypy_codemap_currently_invalid;
+#else
+    return 1;
+#endif
 }
 
 static ptrdiff_t vmprof_unw_get_custom_offset(void* ip, void *cp) {
+#ifdef PYPY_JIT_CODEMAP
     intptr_t ip_l = (intptr_t)ip;
     return pypy_jit_stack_depth_at_loc(ip_l);
+#else
+    return 0;
+#endif
 }
 
 static long vmprof_write_header_for_jit_addr(void **result, long n,
                                              void *ip, int max_depth)
 {
+#ifdef PYPY_JIT_CODEMAP
     void *codemap;
     long current_pos = 0;
     intptr_t id;
@@ -62,5 +75,6 @@
     if (n < max_depth) {
         result[n++] = (void*)3;
     }
+#endif
     return n;
 }
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
@@ -1,5 +1,6 @@
 # Generated by pypy/tool/import_cffi.py
 import sys, os, py
+import subprocess
 import cffi
 from pypy.module.test_lib_pypy.cffi_tests.udir import udir
 
@@ -16,6 +17,9 @@
 class TestDist(object):
 
     def setup_method(self, meth):
+        self.executable = os.path.abspath(sys.executable)
+        self.rootdir = os.path.abspath(os.path.dirname(os.path.dirname(
+            cffi.__file__)))
         self.udir = udir.join(meth.__name__)
         os.mkdir(str(self.udir))
         if meth.chdir_to_tmp:
@@ -26,6 +30,25 @@
         if hasattr(self, 'saved_cwd'):
             os.chdir(self.saved_cwd)
 
+    def run(self, args):
+        env = os.environ.copy()
+        newpath = self.rootdir
+        if 'PYTHONPATH' in env:
+            newpath += os.pathsep + env['PYTHONPATH']
+        env['PYTHONPATH'] = newpath
+        subprocess.check_call([self.executable] + args, env=env)
+
+    def _prepare_setuptools(self):
+        if hasattr(TestDist, '_setuptools_ready'):
+            return
+        try:
+            import setuptools
+        except ImportError:
+            py.test.skip("setuptools not found")
+        subprocess.check_call([self.executable, 'setup.py', 'egg_info'],
+                              cwd=self.rootdir)
+        TestDist._setuptools_ready = True
+
     def check_produced_files(self, content, curdir=None):
         if curdir is None:
             curdir = str(self.udir)
@@ -35,6 +58,8 @@
                 name.endswith('.dylib')):
                 found_so = os.path.join(curdir, name)
                 name = name.split('.')[0] + '.SO' # foo.cpython-34m.so => foo.SO
+            if name.startswith('pycparser') and name.endswith('.egg'):
+                continue    # no clue why this shows up sometimes and not others
             assert name in content, "found unexpected file %r" % (
                 os.path.join(curdir, name),)
             value = content.pop(name)
@@ -172,3 +197,143 @@
                 'foo': {'mod_name_in_package': {'mymod.SO': None,
                                                 'mymod.c': None},
                         'Release': '?'}})
+
+    @chdir_to_tmp
+    def test_api_distutils_extension_1(self):
+        ffi = cffi.FFI()
+        ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
+        ext = ffi.distutils_extension()
+        self.check_produced_files({'build': {
+            'mod_name_in_package': {'mymod.c': None}}})
+        if hasattr(os.path, 'samefile'):
+            assert os.path.samefile(ext.sources[0],
+                                    'build/mod_name_in_package/mymod.c')
+
+    @from_outside
+    def test_api_distutils_extension_2(self):
+        ffi = cffi.FFI()
+        ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
+        ext = ffi.distutils_extension(str(self.udir.join('foo')))
+        self.check_produced_files({'foo': {
+            'mod_name_in_package': {'mymod.c': None}}})
+        if hasattr(os.path, 'samefile'):
+            assert os.path.samefile(ext.sources[0],
+                str(self.udir.join('foo/mod_name_in_package/mymod.c')))
+
+
+    def _make_distutils_api(self):
+        os.mkdir("src")
+        os.mkdir(os.path.join("src", "pack1"))
+        with open(os.path.join("src", "pack1", "__init__.py"), "w") as f:
+            pass
+        with open("setup.py", "w") as f:
+            f.write("""if 1:
+                import cffi
+                ffi = cffi.FFI()
+                ffi.set_source("pack1.mymod", "/*code would be here*/")
+
+                from distutils.core import setup
+                setup(name='example1',
+                      version='0.1',
+                      packages=['pack1'],
+                      package_dir={'': 'src'},
+                      ext_modules=[ffi.distutils_extension()])
+            """)
+
+    @chdir_to_tmp
+    def test_distutils_api_1(self):
+        self._make_distutils_api()
+        self.run(["setup.py", "build"])
+        self.check_produced_files({'setup.py': None,
+                                   'build': '?',
+                                   'src': {'pack1': {'__init__.py': None}}})
+
+    @chdir_to_tmp
+    def test_distutils_api_2(self):
+        self._make_distutils_api()
+        self.run(["setup.py", "build_ext", "-i"])
+        self.check_produced_files({'setup.py': None,
+                                   'build': '?',
+                                   'src': {'pack1': {'__init__.py': None,
+                                                     'mymod.SO': None}}})
+
+    def _make_setuptools_abi(self):
+        self._prepare_setuptools()
+        os.mkdir("src0")
+        os.mkdir(os.path.join("src0", "pack2"))
+        with open(os.path.join("src0", "pack2", "__init__.py"), "w") as f:
+            pass
+        with open(os.path.join("src0", "pack2", "_build.py"), "w") as f:
+            f.write("""if 1:
+                import cffi
+                ffi = cffi.FFI()
+                ffi.set_source("pack2.mymod", None)
+            """)
+        with open("setup.py", "w") as f:
+            f.write("""if 1:
+                from setuptools import setup
+                setup(name='example1',
+                      version='0.1',
+                      packages=['pack2'],
+                      package_dir={'': 'src0'},
+                      cffi_modules=["src0/pack2/_build.py:ffi"])
+            """)
+
+    @chdir_to_tmp
+    def test_setuptools_abi_1(self):
+        self._make_setuptools_abi()
+        self.run(["setup.py", "build"])
+        self.check_produced_files({'setup.py': None,
+                                   'build': '?',
+                                   'src0': {'pack2': {'__init__.py': None,
+                                                      '_build.py': None}}})
+
+    @chdir_to_tmp
+    def test_setuptools_abi_2(self):
+        self._make_setuptools_abi()
+        self.run(["setup.py", "build_ext", "-i"])
+        self.check_produced_files({'setup.py': None,
+                                   'src0': {'pack2': {'__init__.py': None,
+                                                      '_build.py': None,
+                                                      'mymod.py': None}}})
+
+    def _make_setuptools_api(self):
+        self._prepare_setuptools()
+        os.mkdir("src1")
+        os.mkdir(os.path.join("src1", "pack3"))
+        with open(os.path.join("src1", "pack3", "__init__.py"), "w") as f:
+            pass
+        with open(os.path.join("src1", "pack3", "_build.py"), "w") as f:
+            f.write("""if 1:
+                import cffi
+                ffi = cffi.FFI()
+                ffi.set_source("pack3.mymod", "/*code would be here*/")
+            """)
+        with open("setup.py", "w") as f:
+            f.write("""if 1:
+                from setuptools import setup
+                setup(name='example1',
+                      version='0.1',
+                      packages=['pack3'],
+                      package_dir={'': 'src1'},
+                      cffi_modules=["src1/pack3/_build.py:ffi"])
+            """)
+
+    @chdir_to_tmp
+    def test_setuptools_api_1(self):
+        self._make_setuptools_api()
+        self.run(["setup.py", "build"])
+        self.check_produced_files({'setup.py': None,
+                                   'build': '?',
+                                   'src1': {'pack3': {'__init__.py': None,
+                                                      '_build.py': None}}})
+
+    @chdir_to_tmp
+    def test_setuptools_api_2(self):
+        self._make_setuptools_api()
+        self.run(["setup.py", "build_ext", "-i"])
+        self.check_produced_files({'setup.py': None,
+                                   'build': '?',
+                                   'src1': {'pack3': {'__init__.py': None,
+                                                      '_build.py': None,
+                                                      'mymod.SO': None}}})
diff --git a/rpython/doc/conf.py b/rpython/doc/conf.py
--- a/rpython/doc/conf.py
+++ b/rpython/doc/conf.py
@@ -66,9 +66,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = '2.5'
+version = '2.6'
 # The full version, including alpha/beta/rc tags.
-release = '2.5.0'
+release = '2.6.0'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/rpython/jit/backend/llsupport/codemap.py b/rpython/jit/backend/llsupport/codemap.py
--- a/rpython/jit/backend/llsupport/codemap.py
+++ b/rpython/jit/backend/llsupport/codemap.py
@@ -30,6 +30,7 @@
     libraries.append('Kernel32')
 
 eci = ExternalCompilationInfo(post_include_bits=["""
+
 RPY_EXTERN long pypy_jit_codemap_add(unsigned long addr,
                                      unsigned int machine_code_size,
                                      long *bytecode_info,
@@ -47,7 +48,8 @@
 """], separate_module_sources=[
     open(os.path.join(srcdir, 'skiplist.c'), 'r').read() +
     open(os.path.join(srcdir, 'codemap.c'), 'r').read()
-], include_dirs=[cdir], libraries=libraries)
+], include_dirs=[cdir], libraries=libraries,
+compile_extra=['-DPYPY_JIT_CODEMAP'])
 
 def llexternal(name, args, res):
     return rffi.llexternal(name, args, res, compilation_info=eci,


More information about the pypy-commit mailing list