-
Notifications
You must be signed in to change notification settings - Fork 42
/
setup.py
257 lines (231 loc) · 7.07 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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# -*- coding: utf-8 -*-
#################### IMPORTS
import os
import sys
import io
#
from distutils.command.build_ext import build_ext
from distutils.errors import (CCompilerError, DistutilsExecError,
DistutilsPlatformError)
from distutils.core import Command as TestCommand
#
#################### GLOBAL VARIABLES
BEFORE_BREAK_PY3 = (2, 7)
AFTER_BREAK_PY3 = (3, 0)
LINE_STARS = '*' * 75
PYDATALOG = 'pyDatalog'
TEST = 'test'
CURRENT = '.'
#
# The following lines could be improved
RUNTESTS = 'placeholder.py'
RUNTESTS = [CURRENT, PYDATALOG, TEST, RUNTESTS]
RUNTESTS = os.path.join(*RUNTESTS)
#
INIT = '__init__.py'
README = "README.md"
CHANGES = "CHANGES.txt"
TODO = "TODO.md"
SHORT_DESCRIPTION = "A pure-python implementation of Datalog, "\
"a truly declarative language derived from Prolog."
#################### SYSTEM ANALYSIS
#
HAS_FEATURE = False
#
try:
from setuptools import setup, Extension
try:
# see
# https://bitbucket.org/pypa/setuptools/issue/65/deprecate-and-remove-features,
# where they may remove Feature.
from setuptools import Feature
HAS_FEATURE = True
except ImportError:
pass
except ImportError:
from distutils.core import setup, Extension
#
CMDCLASS = {}
EXTRA = {}
PY3K = False
#
if sys.version_info < BEFORE_BREAK_PY3:
raise Exception("pyDatalog requires Python 2.7 or higher.")
elif sys.version_info >= AFTER_BREAK_PY3:
PY3K = True
import platform
CPYTHON = platform.python_implementation() == 'CPython'
EXT_ERRORS = (CCompilerError, DistutilsExecError, DistutilsPlatformError)
if sys.platform == 'win32':
# 2.6's distutils.msvc9compiler can raise an IOError when failing to
# find the compiler
EXT_ERRORS = EXT_ERRORS + (IOError,)
######################## CLASSES
class BuildFailed(Exception):
"""
Specific Error message to work around py 2/3
"""
def __init__(self, *args, **kwargs):
self.cause = sys.exc_info()[1] # work around py 2/3 different syntax
del args
del kwargs
class VeBuildExt(build_ext):
"""This class allows C extension building to fail."""
def run(self):
try:
build_ext.run(self)
except DistutilsPlatformError:
raise BuildFailed()
def build_extension(self, ext):
try:
build_ext.build_extension(self, ext)
except EXT_ERRORS:
raise BuildFailed()
except ValueError:
# this can happen on Windows 64 bit, see Python issue 7511
if "'path'" in str(sys.exc_info()[1]): # works with both py 2/3
raise BuildFailed()
raise BuildFailed()
class PyTest(TestCommand):
"""
For "python setup.py test" working.
Usually, PyTest is subclassed from setuptools.
Here, it is done from distutils.
Have a look at http://pytest.org/latest/goodpractises.html#
integrating-with-distutils-python-setup-py-test
"""
#
# a KILLER line, indeed !
user_options = []
def initialize_options(self):
"""
Subclassing abstract class PyTest
"""
pass
#
def finalize_options(self):
"""
Subclassing abstract class PyTest
"""
pass
def run(self):
"""
Here, RUNTESTS needs to be tuned...
"""
import subprocess
import sys
errno = subprocess.call([sys.executable,
RUNTESTS])
raise SystemExit(errno)
#
##################### FUNCTIONS
#
def _read(*filenames, **kwargs):
"""
Read the docs and give a long description.
"""
encoding = kwargs.get('encoding', 'utf-8')
sep = kwargs.get('sep', '\n')
buf = []
for filename in filenames:
try:
with io.open(filename, encoding=encoding) as _fic:
buf.append(_fic.read())
except IOError:
pass
return sep.join(buf)
def status_msgs(*msgs):
"""
pretty message formatter
"""
print(LINE_STARS)
for msg in msgs:
print(msg)
print(LINE_STARS)
#
############## PREPARING SETUP VALUES
#
from pyDatalog import version as VERSION
_LONG_DESCRIPTION = _read(README, CHANGES, TODO)
#
CMDCLASS['build_ext'] = VeBuildExt
CMDCLASS['test'] = PyTest
#
def run_setup(with_cext):
"""
Contains the whole configuration.
"""
kwargs = EXTRA.copy()
ext_modules = [
Extension('pyDatalog.pyEngine',
sources=['pyDatalog/pyEngine.c']),
]
if with_cext:
if HAS_FEATURE:
kwargs['features'] = {'cextensions': Feature(
"optional C speed-enhancements",
standard=True,
ext_modules=ext_modules
)}
else:
kwargs['ext_modules'] = ext_modules
setup(
name = PYDATALOG,
packages = [PYDATALOG, "pyDatalog/examples"],
version = VERSION.__version__,
cmdclass = CMDCLASS,
description = SHORT_DESCRIPTION,
author = "Pierre Carbonnelle",
author_email = "[email protected]",
tests_require=['pytest'],
url = "https://sites.google.com/site/pydatalog/",
download_url = "http://pypi.python.org/pypi?name=pyDatalog&:action=display",
keywords = "prolog, logic programming, database, SQL, data integration, expert system, AI",
classifiers = [
"Programming Language :: Python",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Prolog",
"Development Status :: 4 - Beta",
"Environment :: Other Environment",
"Intended Audience :: Developers",
"Intended Audience :: Education",
"Topic :: Database",
"Topic :: Database :: Database Engines/Servers",
"License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)",
"Operating System :: OS Independent",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
],
long_description = _LONG_DESCRIPTION,
long_description_content_type='text/markdown',
**kwargs
)
####################### MAIN
if not CPYTHON:
run_setup(False)
status_msgs(
"WARNING: C extensions are not supported on " +
"this Python platform, speedups are not enabled.",
"Plain-Python build succeeded."
)
else:
try:
run_setup(True)
status_msgs(
"C extensions installed successfully."
)
except BuildFailed as exc:
status_msgs(
exc.cause,
"WARNING: The C extension could not be compiled, " +
"speedups are not enabled.",
"Failure information, if any, is above.",
"Retrying the build without the C extension now."
)
run_setup(False)
status_msgs(
"WARNING: The C extension could not be compiled, " +
"speedups are not enabled.",
"Plain-Python build succeeded."
)