diff options
-rw-r--r-- | cffi/verifier.py | 33 | ||||
-rw-r--r-- | doc/source/index.rst | 22 | ||||
-rw-r--r-- | testing/test_zdistutils.py | 16 |
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 |