forked from hyperspy/rosettasciio
-
Notifications
You must be signed in to change notification settings - Fork 0
/
setup.py
149 lines (120 loc) · 4.42 KB
/
setup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
"""A setuptools based setup module.
See:
https://packaging.python.org/guides/distributing-packages-using-setuptools/
https://github.com/pypa/sampleproject
"""
# Always prefer setuptools over distutils
from setuptools import setup, Extension, Command
import os
import warnings
# stuff to check presence of compiler:
import distutils.sysconfig
import distutils.ccompiler
from distutils.errors import CompileError, DistutilsPlatformError
setup_path = os.path.abspath(os.path.dirname(__file__))
# Extensions. Add your extension here:
raw_extensions = [
Extension(
"rsciio.bruker.unbcf_fast", [os.path.join("rsciio", "bruker", "unbcf_fast.pyx")]
),
]
cleanup_list = []
for leftover in raw_extensions:
path, ext = os.path.splitext(leftover.sources[0])
if ext in (".pyx", ".py"):
cleanup_list.append("".join([os.path.join(setup_path, path), ".c*"]))
if os.name == "nt":
bin_ext = ".cpython-*.pyd"
else:
bin_ext = ".cpython-*.so"
cleanup_list.append("".join([os.path.join(setup_path, path), bin_ext]))
def count_c_extensions(extensions):
c_num = 0
for extension in extensions:
# if first source file with extension *.c or *.cpp exists
# it is cythonised or pure c/c++ extension:
sfile = extension.sources[0]
path, ext = os.path.splitext(sfile)
if os.path.exists(path + ".c") or os.path.exists(path + ".cpp"):
c_num += 1
return c_num
def cythonize_extensions(extensions):
try:
from Cython.Build import cythonize
return cythonize(extensions, language_level="3")
except ImportError:
warnings.warn(
"""WARNING: cython required to generate fast c code is not found on this system.
Only slow pure python alternative functions will be available.
To use fast implementation of some functions writen in cython either:
a) install cython and re-run the installation,
b) try alternative source distribution containing cythonized C versions of fast code,
c) use binary distribution (i.e. wheels, egg)."""
)
return []
def no_cythonize(extensions):
for extension in extensions:
sources = []
for sfile in extension.sources:
path, ext = os.path.splitext(sfile)
if ext in (".pyx", ".py"):
if extension.language == "c++":
ext = ".cpp"
else:
ext = ".c"
sfile = path + ext
sources.append(sfile)
extension.sources[:] = sources
return extensions
# to cythonize, or not to cythonize... :
if len(raw_extensions) > count_c_extensions(raw_extensions):
extensions = cythonize_extensions(raw_extensions)
else:
extensions = no_cythonize(raw_extensions)
if os.environ.get("DISABLE_C_EXTENTIONS"):
# Explicitly disable
extensions = []
else:
# to compile or not to compile... depends if compiler is present:
compiler = distutils.ccompiler.new_compiler()
assert isinstance(compiler, distutils.ccompiler.CCompiler)
distutils.sysconfig.customize_compiler(compiler)
try:
compiler.compile(
[os.path.join(setup_path, "rsciio", "tests", "test_compilers.c")]
)
except (CompileError, DistutilsPlatformError):
warnings.warn(
"""WARNING: C compiler can't be found.
Only slow pure python alternative functions will be available.
To use fast implementation of some functions writen in cython/c either:
a) check that you have compiler (EXACTLY SAME as your python
distribution was compiled with) installed,
b) use binary distribution of hyperspy (i.e. wheels, egg, (only osx and win)).
Installation will continue in 5 sec..."""
)
extensions = []
from time import sleep
sleep(5) # wait 5 secs for user to notice the message
class Recythonize(Command):
"""cythonize all extensions"""
description = "(re-)cythonize all changed cython extensions"
user_options = []
def initialize_options(self):
"""init options"""
pass
def finalize_options(self):
"""finalize options"""
pass
def run(self):
# if there is no cython it is supposed to fail:
from Cython.Build import cythonize
global raw_extensions
global extensions
cythonize(extensions, language_level="3")
setup(
ext_modules=extensions,
cmdclass={
"recythonize": Recythonize,
},
)