-
-
Notifications
You must be signed in to change notification settings - Fork 75
/
setup.py
224 lines (199 loc) · 7.46 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
import os
import sys
import re
import subprocess
import sysconfig
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
import setuptools
from distutils import log
log.set_verbosity(log.DEBUG)
def get_python_ext_suffix():
internal_ext_suffix = sysconfig.get_config_var("EXT_SUFFIX")
p = subprocess.run(
[
"python3",
"-c",
"import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))",
],
capture_output=True,
text=True,
)
if p.returncode != 0:
print("Failed to get EXT_SUFFIX via python3")
return internal_ext_suffix
py_ext_suffix = p.stdout.strip()
if py_ext_suffix != internal_ext_suffix:
print("EXT_SUFFIX mismatch")
print("Internal EXT_SUFFIX: " + internal_ext_suffix)
print("Python3 EXT_SUFFIX: " + py_ext_suffix)
print("Current Python Path: " + sys.executable)
print("Current Python Version: " + sys.version)
print(
"Outside Python Path: "
+ subprocess.check_output(["which", "python3"]).decode("utf-8").strip()
)
print(
"Outside Python Version: "
+ subprocess.check_output(["python3", "--version"]).decode("utf-8").strip()
)
return py_ext_suffix
# get the path of the current file
script_dir = os.path.dirname(os.path.abspath(__file__))
libdir = os.path.join(script_dir, "chdb")
def get_latest_git_tag(minor_ver_auto=False):
try:
# get latest tag commit
completed_process = subprocess.run(
["git", "rev-list", "--tags", "--max-count=1"],
capture_output=True,
text=True,
)
if completed_process.returncode != 0:
print(completed_process.stdout)
print(completed_process.stderr)
# get git version
raise RuntimeError("Failed to get git latest tag commit ")
output = completed_process.stdout.strip()
# get latest tag name by commit
completed_process = subprocess.run(
["git", "describe", "--tags", f"{output}"], capture_output=True, text=True
)
if completed_process.returncode != 0:
print(completed_process.stdout)
print(completed_process.stderr)
# get git version
raise RuntimeError("Failed to get git tag")
output = completed_process.stdout.strip()
# strip the v from the tag
output = output[1:]
parts = output.split(".")
if len(parts) == 3:
if minor_ver_auto:
completed_process = subprocess.run(
["git", "rev-list", "--count", f"v{output}..HEAD"],
capture_output=True,
text=True,
)
if completed_process.returncode != 0:
print(completed_process.stdout)
print(completed_process.stderr)
raise RuntimeError("Failed to get git rev-list")
n = completed_process.stdout.strip()
parts[2] = int(parts[2]) + int(n)
return f"{parts[0]}.{parts[1]}.{parts[2]}"
except Exception as e:
print("Failed to get git tag. Error: ")
print(e)
raise
# replace the version in chdb/__init__.py, which is `chdb_version = ('0', '1', '0')` by default
# regex replace the version string `chdb_version = ('0', '1', '0')` with version parts
def fix_version_init(version):
# split version string into parts
p1, p2, p3 = version.split(".")
init_file = os.path.join(script_dir, "chdb", "__init__.py")
with open(init_file, "r+") as f:
init_content = f.read()
# regex replace the version string `chdb_version = ('0', '1', '0')`
regPattern = r"chdb_version = \(\'\d+\', \'\d+\', \'\d+\'\)"
init_content = re.sub(
regPattern, f"chdb_version = ('{p1}', '{p2}', '{p3}')", init_content
)
f.seek(0)
f.write(init_content)
f.truncate()
# Update version in pyproject.toml
def update_pyproject_version(version):
pyproject_file = os.path.join(script_dir, "pyproject.toml")
with open(pyproject_file, "r") as f:
content = f.read()
# Use regex to replace the version
updated_content = re.sub(
r'version\s*=\s*"[^"]*"', f'version = "{version}"', content
)
with open(pyproject_file, "w") as f:
f.write(updated_content)
# As of Python 3.6, CCompiler has a `has_flag` method.
# cf http://bugs.python.org/issue26689
def has_flag(compiler, flagname):
"""Return a boolean indicating whether a flag name is supported on
the specified compiler.
"""
import tempfile
with tempfile.NamedTemporaryFile("w", suffix=".cpp") as f:
f.write("int main (int argc, char **argv) { return 0; }")
try:
compiler.compile([f.name], extra_postargs=[flagname])
except setuptools.distutils.errors.CompileError:
return False
return True
def cpp_flag(compiler):
"""Return the -std=c++[11/2a] compiler flag.
The c++2a is prefered over c++11 (when it is available).
"""
if has_flag(compiler, "-std=c++2a"):
return "-std=c++2a"
elif has_flag(compiler, "-std=c++17"):
return "-std=c++17"
elif has_flag(compiler, "-std=c++14"):
return "-std=c++14"
elif has_flag(compiler, "-std=c++11"):
return "-std=c++11"
else:
raise RuntimeError(
"Unsupported compiler -- at least C++11 support " "is needed!"
)
class BuildExt(build_ext):
"""A custom build extension for adding compiler-specific options."""
def build_extensions(self):
# add the _chdb.cpython-37m-darwin.so or _chdb.cpython-39-x86_64-linux.so to the chdb package
self.distribution.package_data["chdb"] = [
"chdb/_chdb" + get_python_ext_suffix()
]
# super().build_extensions()
# this will be executed by python setup.py bdist_wheel
if __name__ == "__main__":
try:
# get python extension file name
chdb_so = libdir + "/_chdb" + get_python_ext_suffix()
ext_modules = [
Extension(
"_chdb",
sources=["programs/local/LocalChdb.cpp"],
language="c++",
libraries=[],
library_dirs=[libdir],
extra_objects=[chdb_so],
),
]
# fix the version in chdb/__init__.py
versionStr = get_latest_git_tag()
fix_version_init(versionStr)
# Call the function to update pyproject.toml
# update_pyproject_version(versionStr)
# scan the chdb directory and add all the .py files to the package
pkg_files = []
for root, dirs, files in os.walk(libdir):
for file in files:
if file.endswith(".py"):
pkg_files.append(os.path.join(root, file))
pkg_files.append(chdb_so)
setup(
packages=["chdb"],
version=versionStr,
package_data={"chdb": pkg_files},
exclude_package_data={"": ["*.pyc", "src/**"]},
ext_modules=ext_modules,
python_requires=">=3.8",
install_requires=[
"pyarrow>=13.0.0",
"pandas>=2.0.0",
],
cmdclass={"build_ext": BuildExt},
test_suite="tests",
zip_safe=False,
)
except Exception as e:
print("Build from setup.py failed. Error: ")
print(e)
raise