Package _setup :: Module ext
[hide private]
[frames] | no frames]

Source Code for Module _setup.ext

  1  # -*- coding: ascii -*- 
  2  # 
  3  # Copyright 2007, 2008, 2009, 2010 
  4  # Andr\xe9 Malo or his licensors, as applicable 
  5  # 
  6  # Licensed under the Apache License, Version 2.0 (the "License"); 
  7  # you may not use this file except in compliance with the License. 
  8  # You may obtain a copy of the License at 
  9  # 
 10  #     http://www.apache.org/licenses/LICENSE-2.0 
 11  # 
 12  # Unless required by applicable law or agreed to in writing, software 
 13  # distributed under the License is distributed on an "AS IS" BASIS, 
 14  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 15  # See the License for the specific language governing permissions and 
 16  # limitations under the License. 
 17  """ 
 18  =================== 
 19   C extension tools 
 20  =================== 
 21   
 22  C extension tools. 
 23  """ 
 24  __author__ = u"Andr\xe9 Malo" 
 25  __docformat__ = "restructuredtext en" 
 26  __test__ = False 
 27   
 28  from distutils import core as _core 
 29  from distutils import errors as _distutils_errors 
 30  from distutils.command import build_ext as _build_ext 
 31  try: 
 32      from distutils import log 
 33  except ImportError: 
34 - class log(object):
35 # pylint: disable = C0103, C0111
36 - def info(self, value):
37 print value
38 - def debug(self, value):
39 pass
40 log = log() 41 import os as _os 42 import shutil as _shutil 43 import tempfile as _tempfile 44 45
46 -class BuildExt(_build_ext.build_ext):
47 """ 48 Extended extension builder class 49 50 This class allows extensions to provide a ``check_prerequisites`` method 51 which is called before actually building it. The method takes the 52 `BuildExt` instance and returns whether the extension should be skipped or 53 not. 54 """ 55
56 - def build_extension(self, ext):
57 """ 58 Build C extension - with extended functionality 59 60 The following features are added here: 61 62 - ``ext.check_prerequisites`` is called before the extension is being 63 built. See `Extension` for details. If the method does not exist, 64 simply no check will be run. 65 - The macros ``EXT_PACKAGE`` and ``EXT_MODULE`` will be filled (or 66 unset) depending on the extensions name, but only if they are not 67 already defined. 68 - the include subdirectory is added to the include path 69 70 :Parameters: 71 `ext` : `Extension` 72 The extension to build. If it's a pure 73 ``distutils.core.Extension``, simply no prequisites check is 74 applied. 75 76 :Return: whatever ``distutils.command.build_ext.build_ext`` returns 77 :Rtype: any 78 """ 79 # add include path 80 included = _os.path.join(_os.path.dirname(__file__), 'include') 81 if included not in ext.include_dirs: 82 ext.include_dirs.append(included) 83 84 # add cext.h to the dependencies 85 cext_h = _os.path.join(included, 'cext.h') 86 if cext_h not in ext.depends: 87 ext.depends.append(cext_h) 88 89 # handle name macros 90 macros = dict(ext.define_macros or ()) 91 tup = ext.name.split('.') 92 if len(tup) == 1: 93 pkg, mod = None, tup[0] 94 else: 95 pkg, mod = '.'.join(tup[:-1]), tup[-1] 96 if pkg is not None and 'EXT_PACKAGE' not in macros: 97 ext.define_macros.append(('EXT_PACKAGE', pkg)) 98 if 'EXT_MODULE' not in macros: 99 ext.define_macros.append(('EXT_MODULE', mod)) 100 if pkg is None: 101 macros = dict(ext.undef_macros or ()) 102 if 'EXT_PACKAGE' not in macros: 103 ext.undef_macros.append('EXT_PACKAGE') 104 105 try: 106 checker = ext.check_prerequisites 107 except AttributeError: 108 pass 109 else: 110 if checker(self): 111 log.info("Skipping %s extension" % ext.name) 112 return 113 114 return _build_ext.build_ext.build_extension(self, ext)
115 116
117 -class Extension(_core.Extension):
118 """ 119 Extension with prerequisite check interface 120 121 If your check is cacheable (during the setup run), override 122 `cached_check_prerequisites`, `check_prerequisites` otherwise. 123 124 :IVariables: 125 `cached_check` : ``bool`` 126 The cached check result 127 """ 128 cached_check = None 129
130 - def __init__(self, *args, **kwargs):
131 """ Initialization """ 132 if kwargs.has_key('depends'): 133 self.depends = kwargs['depends'] or [] 134 else: 135 self.depends = [] 136 _core.Extension.__init__(self, *args, **kwargs)
137
138 - def check_prerequisites(self, build):
139 """ 140 Check prerequisites 141 142 The check should cover all dependencies needed for the extension to 143 be built and run. The method can do the following: 144 145 - return a false value: the extension will be built 146 - return a true value: the extension will be skipped. This is useful 147 for optional extensions 148 - raise an exception. This is useful for mandatory extensions 149 150 If the check result is cacheable (during the setup run), override 151 `cached_check_prerequisites` instead. 152 153 :Parameters: 154 `build` : `BuildExt` 155 The extension builder 156 157 :Return: Skip the extension? 158 :Rtype: ``bool`` 159 """ 160 if self.cached_check is None: 161 log.debug("PREREQ check for %s" % self.name) 162 self.cached_check = self.cached_check_prerequisites(build) 163 else: 164 log.debug("PREREQ check for %s (cached)" % self.name) 165 return self.cached_check
166
167 - def cached_check_prerequisites(self, build):
168 """ 169 Check prerequisites 170 171 The check should cover all dependencies needed for the extension to 172 be built and run. The method can do the following: 173 174 - return a false value: the extension will be built 175 - return a true value: the extension will be skipped. This is useful 176 for optional extensions 177 - raise an exception. This is useful for mandatory extensions 178 179 If the check result is *not* cacheable (during the setup run), 180 override `check_prerequisites` instead. 181 182 :Parameters: 183 `build` : `BuildExt` 184 The extension builder 185 186 :Return: Skip the extension? 187 :Rtype: ``bool`` 188 """ 189 # pylint: disable = W0613 190 log.debug("Nothing to check for %s!" % self.name) 191 return False
192 193
194 -class ConfTest(object):
195 """ 196 Single conftest abstraction 197 198 :IVariables: 199 `_tempdir` : ``str`` 200 The tempdir created for this test 201 202 `src` : ``str`` 203 Name of the source file 204 205 `target` : ``str`` 206 Target filename 207 208 `compiler` : ``CCompiler`` 209 compiler instance 210 211 `obj` : ``list`` 212 List of object filenames (``[str, ...]``) 213 """ 214 _tempdir = None 215
216 - def __init__(self, build, source):
217 """ 218 Initialization 219 220 :Parameters: 221 `build` : ``distuils.command.build_ext.build_ext`` 222 builder instance 223 224 `source` : ``str`` 225 Source of the file to compile 226 """ 227 self._tempdir = tempdir = _tempfile.mkdtemp() 228 src = _os.path.join(tempdir, 'conftest.c') 229 fp = file(src, 'w') 230 try: 231 fp.write(source) 232 finally: 233 fp.close() 234 self.src = src 235 self.compiler = compiler = build.compiler 236 self.target = _os.path.join(tempdir, 'conftest') 237 self.obj = compiler.object_filenames([src], output_dir=tempdir)
238
239 - def __del__(self):
240 """ Destruction """ 241 self.destroy()
242
243 - def destroy(self):
244 """ Destroy the conftest leftovers on disk """ 245 tempdir, self._tempdir = self._tempdir, None 246 if tempdir is not None: 247 _shutil.rmtree(tempdir)
248
249 - def compile(self, **kwargs):
250 """ 251 Compile the conftest 252 253 :Parameters: 254 `kwargs` : ``dict`` 255 Optional keyword parameters for the compiler call 256 257 :Return: Was the compilation successful? 258 :Rtype: ``bool`` 259 """ 260 kwargs['output_dir'] = self._tempdir 261 try: 262 self.compiler.compile([self.src], **kwargs) 263 except _distutils_errors.CompileError: 264 return False 265 return True
266 285
286 - def pipe(self, mode="r"):
287 r""" 288 Execute the conftest binary and connect to it using a pipe 289 290 Before you can pipe to or from the conftest binary it needs to 291 be `link`\ed. 292 293 :Parameters: 294 `mode` : ``str`` 295 Pipe mode - r/w 296 297 :Return: The open pipe 298 :Rtype: ``file`` 299 """ 300 return _os.popen(self.compiler.executable_filename(self.target), mode)
301