[pypy-commit] pypy fix-result-types: hg merge default
rlamy
noreply at buildbot.pypy.org
Fri May 29 16:17:59 CEST 2015
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: fix-result-types
Changeset: r77691:af369ce9b273
Date: 2015-05-29 15:17 +0100
http://bitbucket.org/pypy/pypy/changeset/af369ce9b273/
Log: hg merge default
diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -11,3 +11,5 @@
10f1b29a2bd21f837090286174a9ca030b8680b2 release-2.5.0
9c4588d731b7fe0b08669bd732c2b676cb0a8233 release-2.5.1
fcdb941565156385cbac04cfb891f8f4c7a92ef6 release-2.6.0
+fcdb941565156385cbac04cfb891f8f4c7a92ef6 release-2.6.0
+e03971291f3a0729ecd3ee7fae7ddb0bb82d476c release-2.6.0
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/cffi_opcode.py b/lib_pypy/cffi/cffi_opcode.py
--- a/lib_pypy/cffi/cffi_opcode.py
+++ b/lib_pypy/cffi/cffi_opcode.py
@@ -52,6 +52,7 @@
OP_CONSTANT_INT = 31
OP_GLOBAL_VAR = 33
OP_DLOPEN_FUNC = 35
+OP_DLOPEN_CONST = 37
PRIM_VOID = 0
PRIM_BOOL = 1
diff --git a/lib_pypy/cffi/parse_c_type.h b/lib_pypy/cffi/parse_c_type.h
--- a/lib_pypy/cffi/parse_c_type.h
+++ b/lib_pypy/cffi/parse_c_type.h
@@ -25,6 +25,7 @@
#define _CFFI_OP_CONSTANT_INT 31
#define _CFFI_OP_GLOBAL_VAR 33
#define _CFFI_OP_DLOPEN_FUNC 35
+#define _CFFI_OP_DLOPEN_CONST 37
#define _CFFI_PRIM_VOID 0
#define _CFFI_PRIM_BOOL 1
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
@@ -11,7 +11,7 @@
class GlobalExpr:
- def __init__(self, name, address, type_op, size=0, check_value=None):
+ def __init__(self, name, address, type_op, size=0, check_value=0):
self.name = name
self.address = address
self.type_op = type_op
@@ -23,11 +23,6 @@
self.name, self.address, self.type_op.as_c_expr(), self.size)
def as_python_expr(self):
- if not isinstance(self.check_value, int_type):
- raise ffiplatform.VerificationError(
- "ffi.dlopen() will not be able to figure out the value of "
- "constant %r (only integer constants are supported, and only "
- "if their value are specified in the cdef)" % (self.name,))
return "b'%s%s',%d" % (self.type_op.as_python_bytes(), self.name,
self.check_value)
@@ -747,7 +742,7 @@
meth_kind = OP_CPYTHON_BLTN_V # 'METH_VARARGS'
self._lsts["global"].append(
GlobalExpr(name, '_cffi_f_%s' % name,
- CffiOp(meth_kind, type_index), check_value=0,
+ CffiOp(meth_kind, type_index),
size='_cffi_d_%s' % name))
# ----------
@@ -971,7 +966,7 @@
def _generate_cpy_constant_collecttype(self, tp, name):
is_int = isinstance(tp, model.PrimitiveType) and tp.is_integer_type()
- if not is_int:
+ if not is_int or self.target_is_python:
self._do_collect_type(tp)
def _generate_cpy_constant_decl(self, tp, name):
@@ -979,11 +974,20 @@
self._generate_cpy_const(is_int, name, tp)
def _generate_cpy_constant_ctx(self, tp, name):
- if isinstance(tp, model.PrimitiveType) and tp.is_integer_type():
+ if (not self.target_is_python and
+ isinstance(tp, model.PrimitiveType) and tp.is_integer_type()):
type_op = CffiOp(OP_CONSTANT_INT, -1)
else:
+ if not tp.sizeof_enabled():
+ raise ffiplatform.VerificationError(
+ "constant '%s' is of type '%s', whose size is not known"
+ % (name, tp._get_c_name()))
+ if self.target_is_python:
+ const_kind = OP_DLOPEN_CONST
+ else:
+ const_kind = OP_CONSTANT
type_index = self._typesdict[tp]
- type_op = CffiOp(OP_CONSTANT, type_index)
+ type_op = CffiOp(const_kind, type_index)
self._lsts["global"].append(
GlobalExpr(name, '_cffi_const_%s' % name, type_op))
@@ -1034,6 +1038,10 @@
def _generate_cpy_macro_ctx(self, tp, name):
if tp == '...':
+ if self.target_is_python:
+ raise ffiplatform.VerificationError(
+ "cannot use the syntax '...' in '#define %s ...' when "
+ "using the ABI mode" % (name,))
check_value = None
else:
check_value = tp # an integer
@@ -1066,7 +1074,7 @@
else:
size = 0
self._lsts["global"].append(
- GlobalExpr(name, '&%s' % name, type_op, size, 0))
+ GlobalExpr(name, '&%s' % name, type_op, size))
# ----------
# emitting the opcodes for individual types
@@ -1148,8 +1156,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):
@@ -1159,29 +1173,45 @@
def make_py_source(ffi, module_name, target_py_file):
return _make_c_or_py_source(ffi, module_name, None, target_py_file)
-def _get_extension(module_name, c_file, kwds):
- source_name = ffiplatform.maybe_relative_path(c_file)
- return ffiplatform.get_extension(source_name, module_name, **kwds)
+def _modname_to_file(outputdir, modname, extension):
+ parts = modname.split('.')
+ try:
+ os.makedirs(os.path.join(outputdir, *parts[:-1]))
+ except OSError:
+ pass
+ parts[-1] += extension
+ 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:
ffi._apply_windows_unicode(kwds)
if preamble is not None:
if c_file is None:
- c_file = os.path.join(tmpdir, module_name + source_extension)
- ext = _get_extension(module_name, c_file, kwds)
+ 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
+ ext = ffiplatform.get_extension(ext_c_file, module_name, **kwds)
updated = make_c_source(ffi, module_name, preamble, c_file)
if call_c_compiler:
- outputfilename = ffiplatform.compile(tmpdir, ext)
+ cwd = os.getcwd()
+ try:
+ os.chdir(tmpdir)
+ outputfilename = ffiplatform.compile('.', ext)
+ finally:
+ os.chdir(cwd)
return outputfilename
else:
return ext, updated
else:
if c_file is None:
- c_file = os.path.join(tmpdir, module_name + '.py')
+ c_file, _ = _modname_to_file(tmpdir, module_name, '.py')
updated = make_py_source(ffi, module_name, c_file)
if call_c_compiler:
return 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/lib_pypy/datetime.py b/lib_pypy/datetime.py
--- a/lib_pypy/datetime.py
+++ b/lib_pypy/datetime.py
@@ -816,9 +816,9 @@
_MONTHNAMES[self._month],
self._day, self._year)
- def strftime(self, fmt):
+ def strftime(self, format):
"Format using strftime()."
- return _wrap_strftime(self, fmt, self.timetuple())
+ return _wrap_strftime(self, format, self.timetuple())
def __format__(self, fmt):
if not isinstance(fmt, (str, unicode)):
@@ -1308,7 +1308,7 @@
__str__ = isoformat
- def strftime(self, fmt):
+ def strftime(self, format):
"""Format using strftime(). The date part of the timestamp passed
to underlying strftime should not be used.
"""
@@ -1317,7 +1317,7 @@
timetuple = (1900, 1, 1,
self._hour, self._minute, self._second,
0, 1, -1)
- return _wrap_strftime(self, fmt, timetuple)
+ return _wrap_strftime(self, format, timetuple)
def __format__(self, fmt):
if not isinstance(fmt, (str, unicode)):
@@ -1497,7 +1497,7 @@
return self._tzinfo
@classmethod
- def fromtimestamp(cls, t, tz=None):
+ def fromtimestamp(cls, timestamp, tz=None):
"""Construct a datetime from a POSIX timestamp (like time.time()).
A timezone info object may be passed in as well.
@@ -1507,12 +1507,12 @@
converter = _time.localtime if tz is None else _time.gmtime
- if isinstance(t, int):
+ if isinstance(timestamp, int):
us = 0
else:
- t_full = t
- t = int(_math.floor(t))
- frac = t_full - t
+ t_full = timestamp
+ timestamp = int(_math.floor(timestamp))
+ frac = t_full - timestamp
us = _round(frac * 1e6)
# If timestamp is less than one microsecond smaller than a
@@ -1520,9 +1520,9 @@
# roll over to seconds, otherwise, ValueError is raised
# by the constructor.
if us == 1000000:
- t += 1
+ timestamp += 1
us = 0
- y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
+ y, m, d, hh, mm, ss, weekday, jday, dst = converter(timestamp)
ss = min(ss, 59) # clamp out leap seconds if the platform has them
result = cls(y, m, d, hh, mm, ss, us, tz)
if tz is not None:
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/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -364,6 +364,18 @@
wrappers. On PyPy we can't tell the difference, so
``ismethod([].__add__) == ismethod(list.__add__) == True``.
+* in pure Python, if you write ``class A(object): def f(self): pass``
+ and have a subclass ``B`` which doesn't override ``f()``, then
+ ``B.f(x)`` still checks that ``x`` is an instance of ``B``. In
+ CPython, types written in C use a different rule. If ``A`` is
+ written in C, any instance of ``A`` will be accepted by ``B.f(x)``
+ (and actually, ``B.f is A.f`` in this case). Some code that could
+ work on CPython but not on PyPy includes:
+ ``datetime.datetime.strftime(datetime.date.today(), ...)`` (here,
+ ``datetime.date`` is the superclass of ``datetime.datetime``).
+ Anyway, the proper fix is arguably to use a regular method call in
+ the first place: ``datetime.date.today().strftime(...)``
+
* the ``__dict__`` attribute of new-style classes returns a normal dict, as
opposed to a dict proxy like in CPython. Mutating the dict will change the
type and vice versa. For builtin types, a dictionary will be returned that
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/cffi_opcode.py b/pypy/module/_cffi_backend/cffi_opcode.py
--- a/pypy/module/_cffi_backend/cffi_opcode.py
+++ b/pypy/module/_cffi_backend/cffi_opcode.py
@@ -52,6 +52,7 @@
OP_CONSTANT_INT = 31
OP_GLOBAL_VAR = 33
OP_DLOPEN_FUNC = 35
+OP_DLOPEN_CONST = 37
PRIM_VOID = 0
PRIM_BOOL = 1
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
@@ -122,18 +122,26 @@
w_result = realize_c_type.realize_global_int(self.ffi, g,
index)
#
- elif op == cffi_opcode.OP_CONSTANT:
+ elif (op == cffi_opcode.OP_CONSTANT or
+ op == cffi_opcode.OP_DLOPEN_CONST):
# A constant which is not of integer type
w_ct = realize_c_type.realize_c_type(
self.ffi, self.ctx.c_types, getarg(g.c_type_op))
fetch_funcptr = rffi.cast(
realize_c_type.FUNCPTR_FETCH_CHARP,
g.c_address)
- assert fetch_funcptr
- assert w_ct.size > 0
- with lltype.scoped_alloc(rffi.CCHARP.TO, w_ct.size) as ptr:
+ if w_ct.size <= 0:
+ raise oefmt(space.w_SystemError,
+ "constant has no known size")
+ if not fetch_funcptr: # for dlopen() style
+ assert op == cffi_opcode.OP_DLOPEN_CONST
+ ptr = self.cdlopen_fetch(attr)
+ else:
+ assert op == cffi_opcode.OP_CONSTANT
+ 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)
+ 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_re_python.py b/pypy/module/_cffi_backend/test/test_re_python.py
--- a/pypy/module/_cffi_backend/test/test_re_python.py
+++ b/pypy/module/_cffi_backend/test/test_re_python.py
@@ -22,6 +22,8 @@
#define BIGNEG -420000000000L
int add42(int x) { return x + 42; }
int globalvar42 = 1234;
+ const int globalconst42 = 4321;
+ const char *const globalconsthello = "hello";
struct foo_s;
typedef struct bar_s { int x; signed char a[]; } bar_t;
enum foo_e { AA, BB, CC };
@@ -34,7 +36,8 @@
c_file = tmpdir.join('_test_re_python.c')
c_file.write(SRC)
ext = ffiplatform.get_extension(str(c_file), '_test_re_python',
- export_symbols=['add42', 'globalvar42'])
+ export_symbols=['add42', 'globalvar42',
+ 'globalconst42', 'globalconsthello'])
outputfilename = ffiplatform.compile(str(tmpdir), ext)
cls.w_extmod = space.wrap(outputfilename)
#mod.tmpdir = tmpdir
@@ -47,6 +50,8 @@
#define BIGNEG -420000000000L
int add42(int);
int globalvar42;
+ const int globalconst42;
+ const char *const globalconsthello = "hello";
int no_such_function(int);
int no_such_globalvar;
struct foo_s;
@@ -157,6 +162,18 @@
p[0] -= 1
assert lib.globalvar42 == 1238
+ def test_global_const_int(self):
+ from re_python_pysrc import ffi
+ lib = ffi.dlopen(self.extmod)
+ assert lib.globalconst42 == 4321
+ raises(AttributeError, ffi.addressof, lib, 'globalconst42')
+
+ def test_global_const_nonint(self):
+ from re_python_pysrc import ffi
+ lib = ffi.dlopen(self.extmod)
+ assert ffi.string(lib.globalconsthello, 8) == "hello"
+ raises(AttributeError, ffi.addressof, lib, 'globalconsthello')
+
def test_rtld_constants(self):
from re_python_pysrc import ffi
ffi.RTLD_NOW # check that we have the attributes
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
@@ -7,7 +7,8 @@
@unwrap_spec(cdef=str, module_name=str, source=str)
-def prepare(space, cdef, module_name, source, w_includes=None):
+def prepare(space, cdef, module_name, source, w_includes=None,
+ w_extra_source=None):
try:
import cffi
from cffi import FFI # <== the system one, which
@@ -45,9 +46,13 @@
ffi.emit_c_code(c_file)
base_module_name = module_name.split('.')[-1]
+ sources = []
+ if w_extra_source is not None:
+ sources.append(space.str_w(w_extra_source))
ext = ffiplatform.get_extension(c_file, module_name,
include_dirs=[str(rdir)],
- export_symbols=['_cffi_pypyinit_' + base_module_name])
+ export_symbols=['_cffi_pypyinit_' + base_module_name],
+ sources=sources)
ffiplatform.compile(str(rdir), ext)
for extension in ['so', 'pyd', 'dylib']:
@@ -66,6 +71,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
@@ -76,6 +84,8 @@
if cls.runappdirect:
py.test.skip("not a test for -A")
cls.w_prepare = cls.space.wrap(interp2app(prepare))
+ cls.w_udir = cls.space.wrap(str(udir))
+ cls.w_os_sep = cls.space.wrap(os.sep)
def setup_method(self, meth):
self._w_modules = self.space.appexec([], """():
@@ -84,6 +94,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 +813,73 @@
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"
+
+ def test_constant_of_value_unknown_to_the_compiler(self):
+ extra_c_source = self.udir + self.os_sep + (
+ 'extra_test_constant_of_value_unknown_to_the_compiler.c')
+ with open(extra_c_source, 'w') as f:
+ f.write('const int external_foo = 42;\n')
+ ffi, lib = self.prepare(
+ "const int external_foo;",
+ 'test_constant_of_value_unknown_to_the_compiler',
+ "extern const int external_foo;",
+ extra_source=extra_c_source)
+ assert lib.external_foo == 42
+
+ def test_call_with_incomplete_structs(self):
+ ffi, lib = self.prepare(
+ "typedef struct {...;} foo_t; "
+ "foo_t myglob; "
+ "foo_t increment(foo_t s); "
+ "double getx(foo_t s);",
+ 'test_call_with_incomplete_structs', """
+ typedef double foo_t;
+ double myglob = 42.5;
+ double getx(double x) { return x; }
+ double increment(double x) { return x + 1; }
+ """)
+ assert lib.getx(lib.myglob) == 42.5
+ assert lib.getx(lib.increment(lib.myglob)) == 43.5
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_dlopen.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_dlopen.py
@@ -20,27 +20,20 @@
)
"""
-def test_invalid_global_constant():
+def test_global_constant():
ffi = FFI()
- ffi.cdef("static const int BB;")
- target = udir.join('test_invalid_global_constants.py')
- e = py.test.raises(VerificationError, make_py_source, ffi,
- 'test_invalid_global_constants', str(target))
- assert str(e.value) == (
- "ffi.dlopen() will not be able to figure out "
- "the value of constant 'BB' (only integer constants are "
- "supported, and only if their value are specified in the cdef)")
+ ffi.cdef("static const long BB; static const float BF = 12;")
+ target = udir.join('test_valid_global_constant.py')
+ make_py_source(ffi, 'test_valid_global_constant', str(target))
+ assert target.read() == r"""# auto-generated file
+import _cffi_backend
-def test_invalid_global_constant_2():
- ffi = FFI()
- ffi.cdef("static const float BB = 12;")
- target = udir.join('test_invalid_global_constants_2.py')
- e = py.test.raises(VerificationError, make_py_source, ffi,
- 'test_invalid_global_constants_2', str(target))
- assert str(e.value) == (
- "ffi.dlopen() will not be able to figure out "
- "the value of constant 'BB' (only integer constants are "
- "supported, and only if their value are specified in the cdef)")
+ffi = _cffi_backend.FFI('test_valid_global_constant',
+ _version = 0x2601,
+ _types = b'\x00\x00\x0D\x01\x00\x00\x09\x01',
+ _globals = (b'\x00\x00\x01\x25BB',0,b'\x00\x00\x00\x25BF',0),
+)
+"""
def test_invalid_global_constant_3():
ffi = FFI()
@@ -54,10 +47,8 @@
target = udir.join('test_invalid_dotdotdot_in_macro.py')
e = py.test.raises(VerificationError, make_py_source, ffi,
'test_invalid_dotdotdot_in_macro', str(target))
- assert str(e.value) == (
- "ffi.dlopen() will not be able to figure out "
- "the value of constant 'FOO' (only integer constants are "
- "supported, and only if their value are specified in the cdef)")
+ assert str(e.value) == ("macro FOO: cannot use the syntax '...' in "
+ "'#define FOO ...' when using the ABI mode")
def test_typename():
ffi = FFI()
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_re_python.py
@@ -15,6 +15,8 @@
int add42(int x) { return x + 42; }
int add43(int x, ...) { return x; }
int globalvar42 = 1234;
+ const int globalconst42 = 4321;
+ const char *const globalconsthello = "hello";
struct foo_s;
typedef struct bar_s { int x; signed char a[]; } bar_t;
enum foo_e { AA, BB, CC };
@@ -29,7 +31,8 @@
ext = ffiplatform.get_extension(
str(c_file),
'_test_re_python',
- export_symbols=['add42', 'add43', 'globalvar42']
+ export_symbols=['add42', 'add43', 'globalvar42',
+ 'globalconst42', 'globalconsthello']
)
outputfilename = ffiplatform.compile(str(tmpdir), ext)
mod.extmod = outputfilename
@@ -44,6 +47,8 @@
int add42(int);
int add43(int, ...);
int globalvar42;
+ const int globalconst42;
+ const char *const globalconsthello = "hello";
int no_such_function(int);
int no_such_globalvar;
struct foo_s;
@@ -127,6 +132,10 @@
sub_ffi.set_source('re_python_pysrc', None)
sub_ffi.emit_python_code(str(tmpdir.join('_re_include_1.py')))
#
+ if sys.version_info[:2] >= (3, 3):
+ import importlib
+ importlib.invalidate_caches() # issue 197 (but can't reproduce myself)
+ #
from _re_include_1 import ffi
assert ffi.integer_const('FOOBAR') == -42
assert ffi.integer_const('FOOBAZ') == -43
@@ -149,6 +158,18 @@
p[0] -= 1
assert lib.globalvar42 == 1238
+def test_global_const_int():
+ from re_python_pysrc import ffi
+ lib = ffi.dlopen(extmod)
+ assert lib.globalconst42 == 4321
+ py.test.raises(AttributeError, ffi.addressof, lib, 'globalconst42')
+
+def test_global_const_nonint():
+ from re_python_pysrc import ffi
+ lib = ffi.dlopen(extmod)
+ assert ffi.string(lib.globalconsthello, 8) == b"hello"
+ py.test.raises(AttributeError, ffi.addressof, lib, 'globalconsthello')
+
def test_rtld_constants():
from re_python_pysrc import ffi
ffi.RTLD_NOW # check that we have the attributes
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
@@ -479,8 +479,11 @@
old_sys_path = sys.path[:]
try:
package_dir = udir.join('test_module_name_in_package')
+ for name in os.listdir(str(udir)):
+ assert not name.startswith('test_module_name_in_package.')
assert os.path.isdir(str(package_dir))
assert len(os.listdir(str(package_dir))) > 0
+ assert os.path.exists(str(package_dir.join('mymod.c')))
package_dir.join('__init__.py').write('')
#
sys.path.insert(0, str(udir))
@@ -821,3 +824,87 @@
assert addr(0xABC05) == 47
assert isinstance(addr, ffi.CData)
assert ffi.typeof(addr) == ffi.typeof("long(*)(long)")
+
+def test_issue198():
+ ffi = FFI()
+ ffi.cdef("""
+ typedef struct{...;} opaque_t;
+ const opaque_t CONSTANT;
+ int toint(opaque_t);
+ """)
+ lib = verify(ffi, '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():
+ ffi = FFI()
+ ffi.cdef("static const float almost_forty_two;")
+ lib = verify(ffi, '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_constant_of_unknown_size():
+ ffi = FFI()
+ ffi.cdef("""
+ typedef ... opaque_t;
+ const opaque_t CONSTANT;
+ """)
+ e = py.test.raises(VerificationError, verify, ffi,
+ 'test_constant_of_unknown_size', "stuff")
+ assert str(e.value) == ("constant CONSTANT: constant 'CONSTANT' is of "
+ "type 'opaque_t', whose size is not known")
+
+def test_variable_of_unknown_size():
+ ffi = FFI()
+ ffi.cdef("""
+ typedef ... opaque_t;
+ opaque_t globvar;
+ """)
+ lib = verify(ffi, 'test_constant_of_unknown_size', """
+ typedef char opaque_t[6];
+ opaque_t globvar = "hello";
+ """)
+ # can't read or write it at all
+ e = py.test.raises(TypeError, getattr, lib, 'globvar')
+ assert str(e.value) == "cdata 'opaque_t' is opaque"
+ e = py.test.raises(TypeError, setattr, lib, 'globvar', [])
+ assert str(e.value) == "'opaque_t' is opaque"
+ # 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) == b"hello"
+
+def test_constant_of_value_unknown_to_the_compiler():
+ extra_c_source = udir.join(
+ 'extra_test_constant_of_value_unknown_to_the_compiler.c')
+ extra_c_source.write('const int external_foo = 42;\n')
+ ffi = FFI()
+ ffi.cdef("const int external_foo;")
+ lib = verify(ffi, 'test_constant_of_value_unknown_to_the_compiler', """
+ extern const int external_foo;
+ """, sources=[str(extra_c_source)])
+ assert lib.external_foo == 42
+
+def test_call_with_incomplete_structs():
+ ffi = FFI()
+ ffi.cdef("typedef struct {...;} foo_t; "
+ "foo_t myglob; "
+ "foo_t increment(foo_t s); "
+ "double getx(foo_t s);")
+ lib = verify(ffi, 'test_call_with_incomplete_structs', """
+ typedef double foo_t;
+ double myglob = 42.5;
+ double getx(double x) { return x; }
+ double increment(double x) { return x + 1; }
+ """)
+ assert lib.getx(lib.myglob) == 42.5
+ assert lib.getx(lib.increment(lib.myglob)) == 43.5
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
new file mode 100644
--- /dev/null
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
@@ -0,0 +1,339 @@
+# 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
+
+
+def chdir_to_tmp(f):
+ f.chdir_to_tmp = True
+ return f
+
+def from_outside(f):
+ f.chdir_to_tmp = False
+ return f
+
+
+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:
+ self.saved_cwd = os.getcwd()
+ os.chdir(str(self.udir))
+
+ def teardown_method(self, meth):
+ 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)
+ found_so = None
+ for name in os.listdir(curdir):
+ if (name.endswith('.so') or name.endswith('.pyd') or
+ 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)
+ if value is None:
+ assert name.endswith('.SO') or (
+ os.path.isfile(os.path.join(curdir, name)))
+ else:
+ subdir = os.path.join(curdir, name)
+ assert os.path.isdir(subdir)
+ if value == '?':
+ continue
+ found_so = self.check_produced_files(value, subdir) or found_so
+ assert content == {}, "files or dirs not produced in %r: %r" % (
+ curdir, content.keys())
+ return found_so
+
+ @chdir_to_tmp
+ def test_empty(self):
+ self.check_produced_files({})
+
+ @chdir_to_tmp
+ def test_abi_emit_python_code_1(self):
+ ffi = cffi.FFI()
+ ffi.set_source("package_name_1.mymod", None)
+ ffi.emit_python_code('xyz.py')
+ self.check_produced_files({'xyz.py': None})
+
+ @chdir_to_tmp
+ def test_abi_emit_python_code_2(self):
+ ffi = cffi.FFI()
+ ffi.set_source("package_name_1.mymod", None)
+ py.test.raises(IOError, ffi.emit_python_code, 'unexisting/xyz.py')
+
+ @from_outside
+ def test_abi_emit_python_code_3(self):
+ ffi = cffi.FFI()
+ ffi.set_source("package_name_1.mymod", None)
+ ffi.emit_python_code(str(self.udir.join('xyt.py')))
+ self.check_produced_files({'xyt.py': None})
+
+ @chdir_to_tmp
+ def test_abi_compile_1(self):
+ ffi = cffi.FFI()
+ ffi.set_source("mod_name_in_package.mymod", None)
+ x = ffi.compile()
+ self.check_produced_files({'mod_name_in_package': {'mymod.py': None}})
+ assert x == os.path.join('.', 'mod_name_in_package', 'mymod.py')
+
+ @chdir_to_tmp
+ def test_abi_compile_2(self):
+ ffi = cffi.FFI()
+ ffi.set_source("mod_name_in_package.mymod", None)
+ x = ffi.compile('build2')
+ self.check_produced_files({'build2': {
+ 'mod_name_in_package': {'mymod.py': None}}})
+ assert x == os.path.join('build2', 'mod_name_in_package', 'mymod.py')
+
+ @from_outside
+ def test_abi_compile_3(self):
+ ffi = cffi.FFI()
+ ffi.set_source("mod_name_in_package.mymod", None)
+ tmpdir = str(self.udir.join('build3'))
+ x = ffi.compile(tmpdir)
+ self.check_produced_files({'build3': {
+ 'mod_name_in_package': {'mymod.py': None}}})
+ assert x == os.path.join(tmpdir, 'mod_name_in_package', 'mymod.py')
+
+ @chdir_to_tmp
+ def test_api_emit_c_code_1(self):
+ ffi = cffi.FFI()
+ ffi.set_source("package_name_1.mymod", "/*code would be here*/")
+ ffi.emit_c_code('xyz.c')
+ self.check_produced_files({'xyz.c': None})
+
+ @chdir_to_tmp
+ def test_api_emit_c_code_2(self):
+ ffi = cffi.FFI()
+ ffi.set_source("package_name_1.mymod", "/*code would be here*/")
+ py.test.raises(IOError, ffi.emit_c_code, 'unexisting/xyz.c')
+
+ @from_outside
+ def test_api_emit_c_code_3(self):
+ ffi = cffi.FFI()
+ ffi.set_source("package_name_1.mymod", "/*code would be here*/")
+ ffi.emit_c_code(str(self.udir.join('xyu.c')))
+ self.check_produced_files({'xyu.c': None})
+
+ @chdir_to_tmp
+ def test_api_compile_1(self):
+ ffi = cffi.FFI()
+ ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
+ x = ffi.compile()
+ if sys.platform != 'win32':
+ sofile = self.check_produced_files({
+ 'mod_name_in_package': {'mymod.SO': None,
+ 'mymod.c': None,
+ 'mymod.o': None}})
+ assert os.path.isabs(x) and os.path.samefile(x, sofile)
+ else:
+ self.check_produced_files({
+ 'mod_name_in_package': {'mymod.SO': None,
+ 'mymod.c': None},
+ 'Release': '?'})
+
+ @chdir_to_tmp
+ def test_api_compile_2(self):
+ ffi = cffi.FFI()
+ ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
+ x = ffi.compile('output')
+ if sys.platform != 'win32':
+ sofile = self.check_produced_files({
+ 'output': {'mod_name_in_package': {'mymod.SO': None,
+ 'mymod.c': None,
+ 'mymod.o': None}}})
+ assert os.path.isabs(x) and os.path.samefile(x, sofile)
+ else:
+ self.check_produced_files({
+ 'output': {'mod_name_in_package': {'mymod.SO': None,
+ 'mymod.c': None},
+ 'Release': '?'}})
+
+ @from_outside
+ def test_api_compile_3(self):
+ ffi = cffi.FFI()
+ ffi.set_source("mod_name_in_package.mymod", "/*code would be here*/")
+ x = ffi.compile(str(self.udir.join('foo')))
+ if sys.platform != 'win32':
+ sofile = self.check_produced_files({
+ 'foo': {'mod_name_in_package': {'mymod.SO': None,
+ 'mymod.c': None,
+ 'mymod.o': None}}})
+ assert os.path.isabs(x) and os.path.samefile(x, sofile)
+ else:
+ self.check_produced_files({
+ '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,
diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -560,6 +560,7 @@
'debug_start': LLOp(canrun=True),
'debug_stop': LLOp(canrun=True),
'have_debug_prints': LLOp(canrun=True),
+ 'have_debug_prints_for':LLOp(canrun=True),
'debug_offset': LLOp(canrun=True),
'debug_flush': LLOp(canrun=True),
'debug_assert': LLOp(tryfold=True),
@@ -573,6 +574,7 @@
'debug_reraise_traceback': LLOp(),
'debug_print_traceback': LLOp(),
'debug_nonnull_pointer': LLOp(canrun=True),
+ 'debug_forked': LLOp(),
# __________ instrumentation _________
'instrument_count': LLOp(),
diff --git a/rpython/rtyper/lltypesystem/opimpl.py b/rpython/rtyper/lltypesystem/opimpl.py
--- a/rpython/rtyper/lltypesystem/opimpl.py
+++ b/rpython/rtyper/lltypesystem/opimpl.py
@@ -597,6 +597,9 @@
def op_have_debug_prints():
return debug.have_debug_prints()
+def op_have_debug_prints_for(prefix):
+ return True
+
def op_debug_nonnull_pointer(x):
assert x
More information about the pypy-commit
mailing list