summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cffi/verifier.py33
-rw-r--r--doc/source/index.rst22
-rw-r--r--testing/test_zdistutils.py16
3 files changed, 52 insertions, 19 deletions
diff --git a/cffi/verifier.py b/cffi/verifier.py
index 3215e94..2df3afe 100644
--- a/cffi/verifier.py
+++ b/cffi/verifier.py
@@ -5,27 +5,32 @@ from . import ffiplatform
class Verifier(object):
- def __init__(self, ffi, preamble, tmpdir=None, ext_package=None,
- tag='', force_generic_engine=False, **kwds):
+ def __init__(self, ffi, preamble, tmpdir=None, modulename=None,
+ ext_package=None, tag='', force_generic_engine=False, **kwds):
self.ffi = ffi
self.preamble = preamble
- flattened_kwds = ffiplatform.flatten(kwds)
+ if not modulename:
+ flattened_kwds = ffiplatform.flatten(kwds)
vengine_class = _locate_engine_class(ffi, force_generic_engine)
self._vengine = vengine_class(self)
self._vengine.patch_extension_kwds(kwds)
self.kwds = kwds
#
- key = '\x00'.join([sys.version[:3], __version__, preamble,
- flattened_kwds] +
- ffi._cdefsources)
- if sys.version_info >= (3,):
- key = key.encode('utf-8')
- k1 = hex(binascii.crc32(key[0::2]) & 0xffffffff)
- k1 = k1.lstrip('0x').rstrip('L')
- k2 = hex(binascii.crc32(key[1::2]) & 0xffffffff)
- k2 = k2.lstrip('0').rstrip('L')
- modulename = '_cffi_%s_%s%s%s' % (tag, self._vengine._class_key,
- k1, k2)
+ if modulename:
+ if tag:
+ raise TypeError("can't specify both 'modulename' and 'tag'")
+ else:
+ key = '\x00'.join([sys.version[:3], __version__, preamble,
+ flattened_kwds] +
+ ffi._cdefsources)
+ if sys.version_info >= (3,):
+ key = key.encode('utf-8')
+ k1 = hex(binascii.crc32(key[0::2]) & 0xffffffff)
+ k1 = k1.lstrip('0x').rstrip('L')
+ k2 = hex(binascii.crc32(key[1::2]) & 0xffffffff)
+ k2 = k2.lstrip('0').rstrip('L')
+ modulename = '_cffi_%s_%s%s%s' % (tag, self._vengine._class_key,
+ k1, k2)
suffix = _get_so_suffix()
self.tmpdir = tmpdir or _caller_dir_pycache()
self.sourcefilename = os.path.join(self.tmpdir, modulename + '.c')
diff --git a/doc/source/index.rst b/doc/source/index.rst
index d866c86..bcd9861 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -453,7 +453,7 @@ Windows). It defaults to ``ffi.RTLD_NOW``.
The verification step
---------------------
-``ffi.verify(source, tmpdir=.., ext_package=.., tag='', **kwargs)``:
+``ffi.verify(source, tmpdir=.., ext_package=.., modulename=.., **kwargs)``:
verifies that the current ffi signatures
compile on this machine, and return a dynamic library object. The
dynamic library can be used to call functions and access global
@@ -598,6 +598,18 @@ not recommended.
middle of the extension module's name: ``_cffi_<tag>_<hash>``.
Useful to give a bit more context, e.g. when debugging.
+.. _`warning about modulename`:
+
+.. versionadded:: 0.5
+ The ``modulename`` argument can be used to force a specific module
+ name, overriding the name ``_cffi_<tag>_<hash>``. Use with care,
+ e.g. if you are passing variable information to ``verify()`` but
+ still want the module name to be always the same (e.g. absolute
+ paths to local files). In this case, no hash is computed and if
+ the module name already exists it will be reused without further
+ check. Be sure to have other means of clearing the ``tmpdir``
+ whenever you change your sources.
+
Working with pointers, structures and arrays
--------------------------------------------
@@ -1339,15 +1351,17 @@ For advanced use cases, the ``Verifier`` class from ``cffi.verifier``
can be instantiated directly. It is normally instantiated for you by
``ffi.verify()``, and the instance is attached as ``ffi.verifier``.
-- ``Verifier(ffi, preamble, tmpdir=.., ext_package='', tag='', **kwds)``:
+- ``Verifier(ffi, preamble, tmpdir=.., ext_package='', modulename=None,
+ tag='', **kwds)``:
instantiate the class with an
FFI object and a preamble, which is C text that will be pasted into
the generated C source. The value of ``tmpdir`` defaults to the
directory ``directory_of_the_caller/__pycache__``. The value of
``ext_package`` is used when looking up an already-compiled, already-
installed version of the extension module. The module name is
- ``_cffi_<tag>_<hash>``.
- The keyword arguments are passed directly
+ ``_cffi_<tag>_<hash>``, unless overridden with ``modulename``
+ (see the `warning about modulename`_ above).
+ The other keyword arguments are passed directly
to `distutils when building the Extension object.`__
.. __: http://docs.python.org/distutils/setupscript.html#describing-extension-module
diff --git a/testing/test_zdistutils.py b/testing/test_zdistutils.py
index 763fb9d..b6b84a5 100644
--- a/testing/test_zdistutils.py
+++ b/testing/test_zdistutils.py
@@ -1,7 +1,7 @@
import sys, os, imp, math, shutil
import py
from cffi import FFI, FFIError
-from cffi.verifier import Verifier, _locate_engine_class
+from cffi.verifier import Verifier, _locate_engine_class, _get_so_suffix
from cffi.ffiplatform import maybe_relative_path
from testing.udir import udir
@@ -241,6 +241,20 @@ class DistUtilsTest(object):
assert lib.test1tag(143) == 101.0
assert '_cffi_xxtest_tagxx_' in ffi.verifier.modulefilename
+ def test_modulename(self):
+ ffi = FFI()
+ ffi.cdef("/* %s test_modulename */ double test1foo(double x);" % self)
+ csrc = "double test1foo(double x) { return x - 63.0; }"
+ modname = 'xxtest_modulenamexx%d' % (self.generic,)
+ lib = ffi.verify(csrc, force_generic_engine=self.generic,
+ modulename=modname)
+ assert lib.test1foo(143) == 80.0
+ suffix = _get_so_suffix()
+ fn1 = os.path.join(ffi.verifier.tmpdir, modname + '.c')
+ fn2 = os.path.join(ffi.verifier.tmpdir, modname + suffix)
+ assert ffi.verifier.sourcefilename == fn1
+ assert ffi.verifier.modulefilename == fn2
+
class TestDistUtilsCPython(DistUtilsTest):
generic = False