Author: mattip <matti.pi...@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, _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit