Skip to content
This repository was archived by the owner on Mar 8, 2020. It is now read-only.

Commit 5ee5ed3

Browse files
authored
Merge pull request #107 from vmarkovtsev/master
Rework setup.py to be portable
2 parents 5909787 + 4a34177 commit 5ee5ed3

2 files changed

Lines changed: 159 additions & 85 deletions

File tree

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ install:
1313
- sudo dpkg -i protobuf-python_3.4.1-1_amd64.deb
1414
- pip3 install --upgrade pip
1515
- pip3 install -r requirements.txt
16-
- python3 setup.py --getdeps
16+
- python3 setup.py --getdeps --log
1717
- pip3 install . --upgrade
1818
script:
1919
- python3 setup.py build_ext -i

setup.py

Lines changed: 158 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1+
import logging
12
import os
3+
import pkg_resources
4+
import shutil
5+
import subprocess
26
import sys
7+
import tarfile
8+
from urllib.request import urlopen
39

410
from setuptools import setup, find_packages, Extension
511
from setuptools.command.build_ext import build_ext
@@ -8,17 +14,20 @@
814
LIBUAST_VERSION = "v1.9.1"
915
SDK_VERSION = "v1.8.0"
1016
SDK_MAJOR = SDK_VERSION.split('.')[0]
11-
PYTHON = "python3"
17+
FORMAT_ARGS = globals()
1218

1319
# For debugging libuast-client interactions, set to True in production!
1420
GET_LIBUAST = True
1521
if not GET_LIBUAST:
16-
print('WARNING: not retrieving libuast, using local version')
22+
print("WARNING: not retrieving libuast, using local version")
1723

18-
os.environ["CC"] = "g++"
19-
os.environ["CXX"] = "g++"
24+
if os.getenv("CC") is None:
25+
os.environ["CC"] = "gcc"
26+
if os.getenv("CXX") is None:
27+
os.environ["CXX"] = "g++"
2028
libraries = ['xml2']
21-
sources = ['bblfsh/pyuast.cc', 'bblfsh/memtracker.cc']
29+
sources = ["bblfsh/pyuast.cc", "bblfsh/memtracker.cc"]
30+
log = logging.getLogger("setup.py")
2231

2332

2433
class CustomBuildExt(build_ext):
@@ -27,115 +36,178 @@ def run(self):
2736
global sources
2837

2938
if "--global-uast" in sys.argv:
30-
libraries.append('uast')
39+
libraries.append("uast")
3140
else:
32-
sources.append('bblfsh/libuast/uast.cc')
33-
sources.append('bblfsh/libuast/roles.c')
41+
sources.append("bblfsh/libuast/uast.cc")
42+
sources.append("bblfsh/libuast/roles.c")
3443

35-
getLibuast()
44+
get_libuast()
3645
build_ext.run(self)
3746

3847

39-
def runc(cmd):
40-
cmd = cmd.format(**globals())
41-
print(cmd)
42-
ret = os.system(cmd)
43-
if ret != 0:
44-
raise Exception("Command failed with output %d: %s" % (ret, cmd))
45-
46-
47-
def createDirs():
48-
runc("mkdir -p gopkg.in/bblfsh/sdk.{SDK_MAJOR}/protocol")
49-
runc("mkdir -p gopkg.in/bblfsh/sdk.{SDK_MAJOR}/uast")
50-
runc("mkdir -p bblfsh/gopkg/in/bblfsh/sdk/{SDK_MAJOR}/protocol")
51-
runc("mkdir -p bblfsh/gopkg/in/bblfsh/sdk/{SDK_MAJOR}/uast")
52-
runc("mkdir -p bblfsh/github/com/gogo/protobuf/gogoproto")
53-
54-
55-
def createInits():
56-
initFiles = [
57-
"bblfsh/github/__init__.py",
58-
"bblfsh/github/com/__init__.py",
59-
"bblfsh/github/com/gogo/__init__.py",
60-
"bblfsh/github/com/gogo/protobuf/__init__.py",
61-
"bblfsh/github/com/gogo/protobuf/gogoproto/__init__.py",
62-
"bblfsh/gopkg/__init__.py",
63-
"bblfsh/gopkg/in/__init__.py",
64-
"bblfsh/gopkg/in/bblfsh/__init__.py",
65-
"bblfsh/gopkg/in/bblfsh/sdk/__init__.py",
66-
"bblfsh/gopkg/in/bblfsh/sdk/{}/__init__.py".format(SDK_MAJOR),
67-
"bblfsh/gopkg/in/bblfsh/sdk/{}/uast/__init__.py".format(SDK_MAJOR),
68-
"bblfsh/gopkg/in/bblfsh/sdk/{}/protocol/__init__.py".format(SDK_MAJOR)
69-
]
48+
def j(*paths):
49+
return os.path.join(*paths)
7050

71-
for f in initFiles:
72-
open(f, 'w').close()
7351

52+
def mkdir(path):
53+
path = path.format(**FORMAT_ARGS)
54+
log.info("mkdir -p " + path)
55+
os.makedirs(path, exist_ok=True)
7456

75-
def getLibuast():
76-
if not GET_LIBUAST:
77-
return
7857

79-
runc("curl -SL https://github.com/bblfsh/libuast/archive/{LIBUAST_VERSION}/"
80-
"{LIBUAST_VERSION}.tar.gz | tar xz")
81-
runc("mv {} libuast".format('libuast-' + LIBUAST_VERSION.replace('v', '')))
82-
runc("cp -a libuast/src bblfsh/libuast")
83-
runc("rm -rf libuast")
58+
def rimraf(path):
59+
path = path.format(**FORMAT_ARGS)
60+
log.info("rm -rf " + path)
61+
shutil.rmtree(path, ignore_errors=True)
8462

8563

86-
def protoDownload():
87-
runc("curl -SL https://github.com/bblfsh/sdk/archive/{SDK_VERSION}.tar.gz | tar xz")
88-
dir_ = "sdk-" + SDK_VERSION[1:]
89-
runc("cp %s/protocol/generated.proto gopkg.in/bblfsh/sdk.{SDK_MAJOR}/protocol/" % dir_)
90-
runc("cp %s/uast/generated.proto gopkg.in/bblfsh/sdk.{SDK_MAJOR}/uast/" % dir_)
91-
runc("rm -rf %s" % dir_)
64+
def mv(src, dst):
65+
src = src.format(**FORMAT_ARGS)
66+
dst = dst.format(**FORMAT_ARGS)
67+
log.info("mv %s %s", src, dst)
68+
shutil.rmtree(dst, ignore_errors=True)
69+
os.rename(src, dst)
9270

9371

94-
def protoCompile():
95-
# SDK
96-
runc("{PYTHON} -m grpc.tools.protoc --python_out=bblfsh/gopkg/in/bblfsh/sdk/{SDK_MAJOR}/protocol "
97-
"--grpc_python_out=bblfsh/gopkg/in/bblfsh/sdk/{SDK_MAJOR}/protocol "
98-
"-I gopkg.in/bblfsh/sdk.{SDK_MAJOR}/protocol -I . "
99-
"gopkg.in/bblfsh/sdk.{SDK_MAJOR}/protocol/generated.proto")
72+
def cp(src, dst):
73+
src = src.format(**FORMAT_ARGS)
74+
dst = dst.format(**FORMAT_ARGS)
75+
log.info("cp -p %s %s", src, dst)
76+
shutil.rmtree(dst, ignore_errors=True)
77+
shutil.copy2(src, dst)
78+
79+
80+
def cpr(src, dst):
81+
src = src.format(**FORMAT_ARGS)
82+
dst = dst.format(**FORMAT_ARGS)
83+
log.info("cp -pr %s %s", src, dst)
84+
shutil.rmtree(dst, ignore_errors=True)
85+
shutil.copytree(src, dst, symlinks=True)
86+
87+
88+
def untar_url(url, path="."):
89+
log.info("tar xf " + url)
90+
with urlopen(url) as response:
91+
response.tell = lambda: 0 # tarfile calls it only once in the beginning
92+
with tarfile.open(fileobj=response, mode=("r:" + url.rsplit(".", 1)[-1])) as tar:
93+
tar.extractall(path=path)
94+
95+
96+
def call(*cmd):
97+
log.info(" ".join(cmd))
98+
subprocess.check_call(cmd)
99+
100+
101+
def create_dirs():
102+
mkdir(j("gopkg.in", "bblfsh", "sdk.{SDK_MAJOR}", "protocol"))
103+
mkdir(j("gopkg.in", "bblfsh", "sdk.{SDK_MAJOR}", "uast"))
104+
mkdir(j("bblfsh", "gopkg", "in", "bblfsh", "sdk", SDK_MAJOR, "protocol"))
105+
mkdir(j("bblfsh", "gopkg", "in", "bblfsh", "sdk", SDK_MAJOR, "uast"))
106+
mkdir(j("bblfsh", "github", "com", "gogo", "protobuf", "gogoproto"))
100107

108+
109+
def create_inits():
110+
init_files = [
111+
j("bblfsh", "github", "__init__.py"),
112+
j("bblfsh", "github", "com", "__init__.py"),
113+
j("bblfsh", "github", "com", "gogo", "__init__.py"),
114+
j("bblfsh", "github", "com", "gogo", "protobuf", "__init__.py"),
115+
j("bblfsh", "github", "com", "gogo", "protobuf", "gogoproto", "__init__.py"),
116+
j("bblfsh", "gopkg", "__init__.py"),
117+
j("bblfsh", "gopkg", "in", "__init__.py"),
118+
j("bblfsh", "gopkg", "in", "bblfsh", "__init__.py"),
119+
j("bblfsh", "gopkg", "in", "bblfsh", "sdk", "__init__.py"),
120+
j("bblfsh", "gopkg", "in", "bblfsh", "sdk", SDK_MAJOR, "__init__.py"),
121+
j("bblfsh", "gopkg", "in", "bblfsh", "sdk", SDK_MAJOR, "uast", "__init__.py"),
122+
j("bblfsh", "gopkg", "in", "bblfsh", "sdk", SDK_MAJOR, "protocol", "__init__.py"),
123+
]
124+
125+
for f in init_files:
126+
open(f, "w").close()
127+
128+
129+
def get_libuast():
130+
if not GET_LIBUAST:
131+
return
132+
133+
untar_url(
134+
"https://github.com/bblfsh/libuast/archive/{LIBUAST_VERSION}/{LIBUAST_VERSION}.tar.gz"
135+
.format(**FORMAT_ARGS))
136+
mv("libuast-" + LIBUAST_VERSION.replace("v", ""), "libuast")
137+
cpr(j("libuast", "src"), j("bblfsh", "libuast"))
138+
rimraf("libuast")
139+
140+
141+
def proto_download():
142+
untar_url("https://github.com/bblfsh/sdk/archive/%s.tar.gz" % SDK_VERSION)
143+
sdkdir = "sdk-" + SDK_VERSION[1:]
144+
cp(j(sdkdir, "protocol", "generated.proto"),
145+
j("gopkg.in", "bblfsh", "sdk.{SDK_MAJOR}", "protocol", "generated.proto"))
146+
cp(j(sdkdir, "uast", "generated.proto"),
147+
j("gopkg.in", "bblfsh", "sdk.{SDK_MAJOR}", "uast", "generated.proto"))
148+
rimraf(sdkdir)
149+
150+
151+
def proto_compile():
152+
sysinclude = "-I" + pkg_resources.resource_filename("grpc_tools", "_proto")
153+
from grpc.tools import protoc as protoc_module
154+
155+
def protoc(python_out, proto_file, *extra, grpc=True):
156+
main_args = [protoc_module.__file__, "--python_out=" + python_out]
157+
if grpc:
158+
main_args += ["--grpc_python_out=" + python_out]
159+
main_args += extra
160+
main_args += ["-I.", sysinclude, proto_file]
161+
log.info("%s -m grpc.tools.protoc " + " ".join(main_args), sys.executable)
162+
protoc_module.main(main_args)
163+
164+
# SDK
165+
protoc(j("bblfsh", "gopkg", "in", "bblfsh", "sdk", SDK_MAJOR, "protocol"),
166+
j("gopkg.in", "bblfsh", "sdk." + SDK_MAJOR, "protocol", "generated.proto"),
167+
"-I" + j("gopkg.in", "bblfsh", "sdk." + SDK_MAJOR, "protocol"))
101168
# UAST
102-
runc("protoc --python_out bblfsh github.com/gogo/protobuf/gogoproto/gogo.proto")
103-
runc("protoc --python_out bblfsh gopkg.in/bblfsh/sdk.{SDK_MAJOR}/uast/generated.proto")
169+
protoc("bblfsh", j("github.com", "gogo", "protobuf", "gogoproto", "gogo.proto"),
170+
grpc=False)
171+
protoc("bblfsh", j("gopkg.in", "bblfsh", "sdk." + SDK_MAJOR, "uast", "generated.proto"),
172+
grpc=False)
104173

105174

106-
def doGetDeps():
107-
getLibuast()
108-
createDirs()
109-
createInits()
110-
protoDownload()
111-
protoCompile()
175+
def do_get_deps():
176+
get_libuast()
177+
create_dirs()
178+
create_inits()
179+
proto_download()
180+
proto_compile()
112181

113182

114183
def clean():
115-
runc("rm -rf gopkg.in")
116-
runc("rm -rf bblfsh/github")
117-
runc("rm -rf bblfsh/gopkg")
184+
rimraf("gopkg.in")
185+
rimraf(j("bblfsh", "github"))
186+
rimraf(j("bblfsh", "gopkg"))
118187
if GET_LIBUAST:
119-
runc("rm -rf bblfsh/libuast")
188+
rimraf(j("bblfsh", "libuast"))
120189

121190

122191
def main():
123192
# The --global-uast flag allows to install the python driver using the installed uast library
193+
if "--log" in sys.argv:
194+
logging.basicConfig(level=logging.INFO)
195+
124196
if "--getdeps" in sys.argv:
125-
doGetDeps()
126-
sys.exit(0)
197+
do_get_deps()
198+
sys.exit()
127199

128200
if "--clean" in sys.argv:
129201
clean()
130-
sys.exit(0)
202+
sys.exit()
131203

132204
libuast_module = Extension(
133-
'bblfsh.pyuast',
205+
"bblfsh.pyuast",
134206
libraries=libraries,
135-
library_dirs=['/usr/lib', '/usr/local/lib'],
136-
extra_compile_args=['-std=c++11'],
137-
include_dirs=['bblfsh/libuast/', '/usr/local/include', '/usr/local/include/libxml2',
138-
'/usr/include', '/usr/include/libxml2'], sources=sources)
207+
library_dirs=["/usr/lib", "/usr/local/lib"],
208+
extra_compile_args=["-std=c++11"],
209+
include_dirs=[j("bblfsh", "libuast"), "/usr/local/include", "/usr/local/include/libxml2",
210+
"/usr/include", "/usr/include/libxml2"], sources=sources)
139211

140212
setup(
141213
cmdclass = {
@@ -148,11 +220,12 @@ def main():
148220
author="source{d}",
149221
author_email="language-analysis@sourced.tech",
150222
url="https://github.com/bblfsh/client-python",
151-
download_url='https://github.com/bblfsh/client-python',
223+
download_url="https://github.com/bblfsh/client-python",
152224
packages=find_packages(),
153225
exclude=["bblfsh/test.py"],
154226
keywords=["babelfish", "uast"],
155227
install_requires=["grpcio==1.10.0", "grpcio-tools==1.10.0", "docker", "protobuf>=3.4.0"],
228+
156229
package_data={"": ["LICENSE", "README.md"]},
157230
ext_modules=[libuast_module],
158231
classifiers=[
@@ -164,10 +237,11 @@ def main():
164237
"Programming Language :: Python :: 3.4",
165238
"Programming Language :: Python :: 3.5",
166239
"Programming Language :: Python :: 3.6",
240+
"Programming Language :: Python :: 3.7",
167241
"Topic :: Software Development :: Libraries"
168242
]
169243
)
170244

171245

172-
if __name__ == '__main__':
246+
if __name__ == "__main__":
173247
main()

0 commit comments

Comments
 (0)