Author: Armin Rigo <[email protected]>
Branch: cffi-1.0
Changeset: r1876:35dd6cec69f3
Date: 2015-04-29 19:30 +0200
http://bitbucket.org/cffi/cffi/changeset/35dd6cec69f3/
Log: first attempt at writing setuptools hooks
diff --git a/_cffi1/setuptools_ext.py b/_cffi1/setuptools_ext.py
new file mode 100644
--- /dev/null
+++ b/_cffi1/setuptools_ext.py
@@ -0,0 +1,80 @@
+
+def error(msg):
+ from distutils.errors import DistutilsSetupError
+ raise DistutilsSetupError(msg)
+
+
+def add_cffi_module(dist, mod_spec):
+ import os
+ from cffi.api import FFI
+ from _cffi1 import recompiler
+ from distutils.core import Extension
+ from distutils.command.build_ext import build_ext
+ from distutils.dir_util import mkpath
+ from distutils import log
+
+ if not isinstance(mod_spec, str):
+ error("argument to 'cffi_modules=...' must be a str or a list of str,"
+ " not %r" % (type(mod_spec).__name__,))
+ try:
+ build_mod_name, ffi_var_name = mod_spec.split(':')
+ except ValueError:
+ error("%r must be of the form 'build_mod_name:ffi_variable'" %
+ (mod_spec,))
+ mod = __import__(build_mod_name, None, None, [ffi_var_name])
+ try:
+ ffi = getattr(mod, ffi_var_name)
+ except AttributeError:
+ error("%r: object %r not found in module" % (mod_spec,
+ ffi_var_name))
+ if not isinstance(ffi, FFI):
+ error("%r is not an FFI instance (got %r)" % (mod_spec,
+ type(ffi).__name__))
+ if not hasattr(ffi, '_assigned_source'):
+ error("%r: the set_source() method was not called" % (mod_spec,))
+ module_name = ffi._recompiler_module_name
+ source, kwds = ffi._assigned_source
+
+ allsources = ['$PLACEHOLDER']
+ allsources.extend(kwds.get('sources', []))
+ ext = Extension(name=module_name, sources=allsources, **kwds)
+
+ def make_mod(tmpdir):
+ mkpath(tmpdir)
+ file_name = module_name + '.c'
+ log.info("generating cffi module %r" % file_name)
+ c_file = os.path.join(tmpdir, file_name)
+ c_tmp = '%s.%s' % (c_file, os.getpid())
+ recompiler.make_c_source(ffi, module_name, source, c_tmp)
+ try:
+ with open(c_file, 'r') as f1:
+ with open(c_tmp, 'r') as f2:
+ if f1.read() != f2.read():
+ raise IOError
+ except IOError:
+ os.rename(c_tmp, c_file)
+ else:
+ log.info("already up-to-date")
+ os.unlink(c_tmp)
+ return c_file
+
+ if dist.ext_modules is None:
+ dist.ext_modules = []
+ dist.ext_modules.append(ext)
+
+ base_class = dist.cmdclass.get('build_ext', build_ext)
+ class build_ext_make_mod(base_class):
+ def run(self):
+ if ext.sources[0] == '$PLACEHOLDER':
+ ext.sources[0] = make_mod(self.build_temp)
+ base_class.run(self)
+ dist.cmdclass['build_ext'] = build_ext_make_mod
+
+
+def cffi_modules(dist, attr, value):
+ assert attr == 'cffi_modules'
+ if isinstance(value, str):
+ value = [value]
+
+ for cffi_module in value:
+ add_cffi_module(dist, cffi_module)
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -475,6 +475,22 @@
('_UNICODE', '1')]
kwds['define_macros'] = defmacros
+ def set_source(self, module_name, source, **kwds):
+ if hasattr(self, '_assigned_source'):
+ raise ValueError("set_source() cannot be called several times "
+ "per ffi object")
+ self._recompiler_module_name = module_name
+ self._assigned_source = (source, kwds)
+
+ def compile(self, tmpdir='.'):
+ from _cffi1 import recompile
+ #
+ if not hasattr(self, '_assigned_source'):
+ raise ValueError("set_source() must be called before compile()")
+ source, kwds = self._assigned_source
+ return recompile(self, self._recompiler_module_name,
+ source, tmpdir=tmpdir, **kwds)
+
def _load_backend_lib(backend, name, flags):
if name is None:
diff --git a/demo/bsdopendirtype_build.py b/demo/bsdopendirtype_build.py
--- a/demo/bsdopendirtype_build.py
+++ b/demo/bsdopendirtype_build.py
@@ -1,5 +1,4 @@
from cffi import FFI
-from _cffi1 import recompile
ffi = FFI()
ffi.cdef("""
@@ -15,7 +14,10 @@
static const int DT_BLK, DT_CHR, DT_DIR, DT_FIFO, DT_LNK, DT_REG, DT_SOCK;
""")
-recompile(ffi, "_bsdopendirtype", """
+ffi.set_source("_bsdopendirtype", """
#include <sys/types.h>
#include <dirent.h>
""")
+
+if __name__ == '__main__':
+ ffi.compile()
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -142,8 +142,9 @@
`Mailing list <https://groups.google.com/forum/#!forum/python-cffi>`_
""",
- version='0.9.2',
- packages=['cffi'],
+ version='1.0.0',
+ packages=['cffi', '_cffi1'],
+ package_data={'_cffi1': ['_cffi_include.h', 'parse_c_type.h']},
zip_safe=False,
url='http://cffi.readthedocs.org',
@@ -157,6 +158,13 @@
install_requires=[
'pycparser',
],
+
+ entry_points = {
+ "distutils.setup_keywords": [
+ "cffi_modules = _cffi1.setuptools_ext:cffi_modules",
+ ],
+ },
+
classifiers=[
'Programming Language :: Python',
'Programming Language :: Python :: 2',
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit