setup.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. #!/usr/bin/env python
  2. from __future__ import print_function
  3. from setuptools import setup
  4. from setuptools import Distribution
  5. from setuptools.command.sdist import sdist
  6. from setuptools.extension import Extension
  7. import platform
  8. import re
  9. import sys
  10. import os
  11. SKIP_CYTHON_FILE = '__dont_use_cython__.txt'
  12. if os.path.exists(SKIP_CYTHON_FILE):
  13. print("In distributed package, building from C files...", file=sys.stderr)
  14. SOURCE_EXT = 'c'
  15. else:
  16. try:
  17. from Cython.Build import cythonize
  18. print("Building from Cython files...", file=sys.stderr)
  19. SOURCE_EXT = 'pyx'
  20. except ImportError:
  21. print("Cython not found, building from C files...",
  22. file=sys.stderr)
  23. SOURCE_EXT = 'c'
  24. get_output = None
  25. try:
  26. import commands
  27. get_output = commands.getoutput
  28. except ImportError:
  29. import subprocess
  30. def _get_output(*args, **kwargs):
  31. res = subprocess.check_output(*args, shell=True, **kwargs)
  32. decoded = res.decode('utf-8')
  33. return decoded.strip()
  34. get_output = _get_output
  35. # get the compile and link args
  36. link_args = os.environ.get('GSSAPI_LINKER_ARGS', None)
  37. compile_args = os.environ.get('GSSAPI_COMPILER_ARGS', None)
  38. osx_has_gss_framework = False
  39. if sys.platform == 'darwin':
  40. mac_ver = [int(v) for v in platform.mac_ver()[0].split('.')]
  41. osx_has_gss_framework = (mac_ver >= [10, 7, 0])
  42. if link_args is None:
  43. if osx_has_gss_framework:
  44. link_args = '-framework GSS'
  45. elif os.environ.get('MINGW_PREFIX'):
  46. link_args = '-lgss'
  47. else:
  48. link_args = get_output('krb5-config --libs gssapi')
  49. if compile_args is None:
  50. if osx_has_gss_framework:
  51. compile_args = '-framework GSS -DOSX_HAS_GSS_FRAMEWORK'
  52. elif os.environ.get('MINGW_PREFIX'):
  53. compile_args = '-fPIC'
  54. else:
  55. compile_args = get_output('krb5-config --cflags gssapi')
  56. link_args = link_args.split()
  57. compile_args = compile_args.split()
  58. # add in the extra workarounds for different include structures
  59. try:
  60. prefix = get_output('krb5-config gssapi --prefix')
  61. except Exception:
  62. print("WARNING: couldn't find krb5-config; assuming prefix of %s"
  63. % str(sys.prefix))
  64. prefix = sys.prefix
  65. gssapi_ext_h = os.path.join(prefix, 'include/gssapi/gssapi_ext.h')
  66. if os.path.exists(gssapi_ext_h):
  67. compile_args.append("-DHAS_GSSAPI_EXT_H")
  68. # ensure that any specific directories are listed before any generic system
  69. # directories inserted by setuptools
  70. library_dirs = [arg[2:] for arg in link_args if arg.startswith('-L')]
  71. link_args = [arg for arg in link_args if not arg.startswith('-L')]
  72. ENABLE_SUPPORT_DETECTION = \
  73. (os.environ.get('GSSAPI_SUPPORT_DETECT', 'true').lower() == 'true')
  74. if ENABLE_SUPPORT_DETECTION:
  75. import ctypes.util
  76. main_lib = os.environ.get('GSSAPI_MAIN_LIB', None)
  77. main_path = ""
  78. if main_lib is None and osx_has_gss_framework:
  79. main_lib = ctypes.util.find_library('GSS')
  80. elif os.environ.get('MINGW_PREFIX'):
  81. main_lib = os.environ.get('MINGW_PREFIX')+'/bin/libgss-3.dll'
  82. elif main_lib is None:
  83. for opt in link_args:
  84. if opt.startswith('-lgssapi'):
  85. main_lib = 'lib%s.so' % opt[2:]
  86. # To support Heimdal on Debian, read the linker path.
  87. if opt.startswith('-Wl,/'):
  88. main_path = opt[4:] + "/"
  89. if main_lib is None:
  90. raise Exception("Could not find main GSSAPI shared library. Please "
  91. "try setting GSSAPI_MAIN_LIB yourself or setting "
  92. "ENABLE_SUPPORT_DETECTION to 'false'")
  93. GSSAPI_LIB = ctypes.CDLL(main_path + main_lib)
  94. # add in the flag that causes us not to compile from Cython when
  95. # installing from an sdist
  96. class sdist_gssapi(sdist):
  97. def run(self):
  98. if not self.dry_run:
  99. with open(SKIP_CYTHON_FILE, 'w') as flag_file:
  100. flag_file.write('COMPILE_FROM_C_ONLY')
  101. sdist.run(self)
  102. os.remove(SKIP_CYTHON_FILE)
  103. DONT_CYTHONIZE_FOR = ('clean',)
  104. class GSSAPIDistribution(Distribution, object):
  105. def run_command(self, command):
  106. self._last_run_command = command
  107. Distribution.run_command(self, command)
  108. @property
  109. def ext_modules(self):
  110. if SOURCE_EXT != 'pyx':
  111. return getattr(self, '_ext_modules', None)
  112. if getattr(self, '_ext_modules', None) is None:
  113. return None
  114. if getattr(self, '_last_run_command', None) in DONT_CYTHONIZE_FOR:
  115. return self._ext_modules
  116. if getattr(self, '_cythonized_ext_modules', None) is None:
  117. self._cythonized_ext_modules = cythonize(self._ext_modules)
  118. return self._cythonized_ext_modules
  119. @ext_modules.setter
  120. def ext_modules(self, mods):
  121. self._cythonized_ext_modules = None
  122. self._ext_modules = mods
  123. @ext_modules.deleter
  124. def ext_modules(self):
  125. del self._ext_modules
  126. del self._cythonized_ext_modules
  127. # detect support
  128. def main_file(module):
  129. return Extension('gssapi.raw.%s' % module,
  130. extra_link_args=link_args,
  131. extra_compile_args=compile_args,
  132. library_dirs=library_dirs,
  133. sources=['gssapi/raw/%s.%s' % (module, SOURCE_EXT)])
  134. ENUM_EXTS = []
  135. def extension_file(module, canary):
  136. if ENABLE_SUPPORT_DETECTION and not hasattr(GSSAPI_LIB, canary):
  137. print('Skipping the %s extension because it '
  138. 'is not supported by your GSSAPI implementation...' % module)
  139. return None
  140. else:
  141. enum_ext_path = 'gssapi/raw/_enum_extensions/ext_%s.%s' % (module,
  142. SOURCE_EXT)
  143. if os.path.exists(enum_ext_path):
  144. ENUM_EXTS.append(
  145. Extension('gssapi.raw._enum_extensions.ext_%s' % module,
  146. extra_link_args=link_args,
  147. extra_compile_args=compile_args,
  148. sources=[enum_ext_path],
  149. library_dirs=library_dirs,
  150. include_dirs=['gssapi/raw/']))
  151. return Extension('gssapi.raw.ext_%s' % module,
  152. extra_link_args=link_args,
  153. extra_compile_args=compile_args,
  154. library_dirs=library_dirs,
  155. sources=['gssapi/raw/ext_%s.%s' % (module,
  156. SOURCE_EXT)])
  157. def gssapi_modules(lst):
  158. # filter out missing files
  159. res = [mod for mod in lst if mod is not None]
  160. # add in supported mech files
  161. MECHS_SUPPORTED = os.environ.get('GSSAPI_MECHS', 'krb5').split(',')
  162. for mech in MECHS_SUPPORTED:
  163. res.append(Extension('gssapi.raw.mech_%s' % mech,
  164. extra_link_args=link_args,
  165. extra_compile_args=compile_args,
  166. library_dirs=library_dirs,
  167. sources=['gssapi/raw/mech_%s.%s' % (mech,
  168. SOURCE_EXT)]))
  169. # add in any present enum extension files
  170. res.extend(ENUM_EXTS)
  171. return res
  172. long_desc = re.sub('\.\. role:: \w+\(code\)\s*\n\s*.+', '',
  173. re.sub(r':(python|bash|code):', '',
  174. re.sub(r'\.\. code-block:: \w+', '::',
  175. open('README.txt').read())))
  176. install_requires = [
  177. 'decorator',
  178. 'six >= 1.4.0'
  179. ]
  180. if sys.version_info < (3, 4):
  181. install_requires.append('enum34')
  182. setup(
  183. name='gssapi',
  184. version='1.5.1',
  185. author='The Python GSSAPI Team',
  186. author_email='sross@redhat.com',
  187. packages=['gssapi', 'gssapi.raw', 'gssapi.raw._enum_extensions',
  188. 'gssapi.tests'],
  189. description='Python GSSAPI Wrapper',
  190. long_description=long_desc,
  191. license='LICENSE.txt',
  192. url="https://github.com/pythongssapi/python-gssapi",
  193. classifiers=[
  194. 'Development Status :: 4 - Beta',
  195. 'Programming Language :: Python',
  196. 'Programming Language :: Python :: 2.7',
  197. 'Programming Language :: Python :: 3',
  198. 'Programming Language :: Python :: 3.3',
  199. 'Intended Audience :: Developers',
  200. 'License :: OSI Approved :: ISC License (ISCL)',
  201. 'Programming Language :: Python :: Implementation :: CPython',
  202. 'Programming Language :: Cython',
  203. 'Topic :: Security',
  204. 'Topic :: Software Development :: Libraries :: Python Modules'
  205. ],
  206. distclass=GSSAPIDistribution,
  207. cmdclass={'sdist': sdist_gssapi},
  208. ext_modules=gssapi_modules([
  209. main_file('misc'),
  210. main_file('exceptions'),
  211. main_file('creds'),
  212. main_file('names'),
  213. main_file('sec_contexts'),
  214. main_file('types'),
  215. main_file('message'),
  216. main_file('oids'),
  217. main_file('cython_converters'),
  218. main_file('chan_bindings'),
  219. extension_file('s4u', 'gss_acquire_cred_impersonate_name'),
  220. extension_file('cred_store', 'gss_store_cred_into'),
  221. extension_file('rfc5587', 'gss_indicate_mechs_by_attrs'),
  222. extension_file('rfc5588', 'gss_store_cred'),
  223. extension_file('rfc5801', 'gss_inquire_saslname_for_mech'),
  224. extension_file('cred_imp_exp', 'gss_import_cred'),
  225. extension_file('dce', 'gss_wrap_iov'),
  226. extension_file('iov_mic', 'gss_get_mic_iov'),
  227. extension_file('ggf', 'gss_inquire_sec_context_by_oid'),
  228. extension_file('set_cred_opt', 'gss_set_cred_option'),
  229. # see ext_rfc6680_comp_oid for more information on this split
  230. extension_file('rfc6680', 'gss_display_name_ext'),
  231. extension_file('rfc6680_comp_oid', 'GSS_C_NT_COMPOSITE_EXPORT'),
  232. # see ext_password{,_add}.pyx for more information on this split
  233. extension_file('password', 'gss_acquire_cred_with_password'),
  234. extension_file('password_add', 'gss_add_cred_with_password'),
  235. ]),
  236. keywords=['gssapi', 'security'],
  237. install_requires=install_requires
  238. )