Skip to content

Commit fe5ac83

Browse files
committed
now bundling requests and cachecontrol modules
- they get copied into the Resources/python folder of the app (alongside the plotdevice module) - for pip installs of the stand-alone module, the http libs are listed as requirements rather than handled explicitly in the build process
1 parent 1ce7170 commit fe5ac83

5 files changed

Lines changed: 85 additions & 115 deletions

File tree

PlotDevice.xcodeproj/project.pbxproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@
458458
);
459459
runOnlyForDeploymentPostprocessing = 0;
460460
shellPath = /bin/sh;
461-
shellScript = "# have the build fail if setup.py isn't successful\nset -e\n\n# let the setup script handle updating\n$PYTHON setup.py build\n\n# copy the up-to-date module contents into the app bundle\nEXT_DIR=\"$TARGET_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/python/\"\nmkdir -p $EXT_DIR\nditto build/lib/plotdevice \"$EXT_DIR/plotdevice\"\n\n# make sure everything has a .pyc (so code-signing doesn't break on first run)\n$PYTHON -m compileall \"$EXT_DIR/plotdevice\"";
461+
shellScript = "# have the build fail if setup.py isn't successful\nset -e\n\n# let the setup script handle updating\n$PYTHON setup.py build\n\n# copy the up-to-date module contents into the app bundle\nSITE_DIR=\"$TARGET_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/python\"\nditto build/lib \"$SITE_DIR\"\n\n# make sure everything has a .pyc (so code-signing doesn't break on first run)\n$PYTHON -m compileall -q \"$SITE_DIR/plotdevice\"";
462462
showEnvVarsInLog = 0;
463463
};
464464
2AF8981419953CA1005A49A5 /* Manually Update Examples */ = {

app/deps/PyObjC/Makefile

Lines changed: 0 additions & 74 deletions
This file was deleted.

app/deps/build.py

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,58 +2,90 @@
22
import os
33
import sys
44
import errno
5+
from subprocess import call
56
from glob import glob
6-
from os.path import dirname, basename, abspath, isdir, join, exists
7+
from os.path import dirname, basename, abspath, isdir, join
8+
from shutil import rmtree
79

8-
libs_root = dirname(abspath(__file__))
10+
DEPS = dirname(abspath(__file__))
11+
PYTHON = sys.executable
912

10-
def build_libraries(dst_root):
11-
print("\nCompiling required c-extensions")
13+
## Helpers ##
14+
15+
def build(extension):
16+
"""Run setup.py within a given c-extension's folder"""
17+
result = call([PYTHON, 'setup.py', '-q', 'build'], cwd=join(DEPS, extension))
18+
if result > 0:
19+
raise OSError("Could not build %s" % extension)
20+
21+
def make(target, **envvars):
22+
"""Build the specified target in the vendor Makefile"""
23+
os.chdir('%s/vendor'%DEPS)
24+
env = {"PYTHON":PYTHON, "PATH":os.environ['PATH']}
25+
env.update(envvars)
26+
result = call('make -s %s'%target, env=env, shell=True)
27+
if result > 0:
28+
raise OSError("Could not make %s" % target)
29+
os.chdir(DEPS)
1230

31+
def clean():
32+
"""Delete build folders in dependency subdirs"""
33+
build_dirs = glob('%s/*/build'%DEPS)
34+
for build_dir in build_dirs:
35+
lib_name = dirname(build_dir)
36+
print("Cleaning", lib_name)
37+
call('rm -r "%s"' % build_dir)
38+
make('clean')
39+
40+
## Recipes ##
41+
42+
def build_extensions():
1343
# Find all setup.py files in the current folder
14-
setup_scripts = glob('%s/*/setup.py'%libs_root)
15-
for setup_script in setup_scripts:
44+
print("\nCompiling required c-extensions")
45+
for setup_script in glob('%s/*/setup.py'%DEPS):
1646
lib_name = basename(dirname(setup_script))
1747
print("Building %s..."% lib_name)
18-
os.chdir(dirname(setup_script))
19-
result = os.system(sys.executable+' setup.py -q build') # call the lib's setup.py
20-
if result > 0:
21-
raise OSError("Could not build %s" % lib_name)
22-
os.chdir(libs_root)
48+
build(lib_name)
49+
50+
print("Building pyobjc...")
51+
make('pyobjc')
2352

53+
def install_extensions(ext_root):
54+
"""Install the c-extensions and PyObjC site dir within the plotdevice module"""
2455
# Make sure the destination folder exists.
25-
if not isdir(dst_root):
26-
os.makedirs(dst_root)
56+
if not isdir(ext_root):
57+
os.makedirs(ext_root)
2758

28-
# Copy all build results to the ../../build/deps folder.
29-
build_dirs = glob("%s/*/build/lib*"%libs_root)
30-
for build_dir in build_dirs:
31-
lib_name = dirname(dirname(build_dir))
32-
cmd = 'cp -R -p %s/* %s' % (build_dir, dst_root)
33-
print(cmd)
34-
result = os.system(cmd)
59+
# Copy all build results to plotdevice/lib dir
60+
for extension in glob("%s/*/build/lib*"%DEPS):
61+
cmd = 'cp -R -p %s/* %s' % (extension, ext_root)
62+
result = call(cmd, shell=True)
3563
if result > 0:
64+
lib_name = dirname(dirname(extension))
3665
raise OSError("Could not copy %s" % lib_name)
3766
print()
3867

39-
def clean_build_files():
40-
print("Cleaning all library build files...")
41-
42-
build_dirs = glob('%s/*/build'%libs_root)
43-
for build_dir in build_dirs:
44-
lib_name = dirname(build_dir)
45-
print("Cleaning", lib_name)
46-
os.system('rm -r "%s"' % build_dir)
68+
def install_http_libs(mod_root):
69+
"""Install the http modules into the Resources/python subdir"""
70+
if 'ACTION' not in os.environ:
71+
# the ACTION env var will be defined for app and py2app builds, in which
72+
# case we should install the http libs into Resources/python (for non-GUI
73+
# builds, setup.py's install_requires will pull in dependencies automatically)
74+
return
75+
print("Bundling requests module...")
76+
make('http', DSTROOT=mod_root) # makefile uses DSTROOT to target install
4777

4878
if __name__=='__main__':
49-
import sys
50-
5179
if len(sys.argv)>1:
5280
arg = sys.argv[1]
5381
if arg=='clean':
54-
clean_build_files()
82+
print("Cleaning dependency build files...")
83+
clean()
5584
else:
56-
dst_root = join(arg, 'plotdevice/lib')
57-
build_libraries(dst_root)
85+
mod_root = arg
86+
ext_root = join(mod_root, 'plotdevice/lib')
87+
build_extensions()
88+
install_http_libs(mod_root)
89+
install_extensions(ext_root)
5890
else:
5991
print("usage: python build.py <destination-path>")

app/deps/vendor/Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
PYTHON ?= /usr/bin/python
33
PY_VERSION = $(shell $(PYTHON) -c 'import sys; print("py%i%i"%sys.version_info[:2])')
44

5+
# dependencies to be fetched
6+
HTTP_MODULES = requests cachecontrol
7+
58
VENV_VERSION = 13.0.3
69
VENV_SRC = virtualenv-$(VENV_VERSION).tar.gz
710
VENV_URL = https://pypi.python.org/packages/source/v/virtualenv/$(VENV_SRC)
@@ -15,6 +18,7 @@ BUILD = build
1518
ENV = $(BUILD)/env
1619
WHEELHOUSE = $(BUILD)/wheelhouse
1720
PYOBJC = $(BUILD)/lib/PyObjC
21+
DSTROOT ?= $(BUILD)/HTTP
1822

1923
# commands
2024
CURL = @curl -L --progress-bar -f
@@ -42,6 +46,11 @@ wheels: clean $(ENV)
4246
$(PIP) wheel "pyobjc"==$(OBJC_VERSION) -w ${WHEELHOUSE}
4347
tar czfv $(OBJC_SRC) -C $(BUILD) $(notdir ${WHEELHOUSE})
4448

49+
# fetch the current versions of our helper modules
50+
http: $(ENV)
51+
$(ENV)/bin/pip -q install --target=$(DSTROOT) $(HTTP_MODULES)
52+
rm -rf $(DSTROOT)/*.dist-info
53+
4554
# ---------------------------------------------------------------------------------------- #
4655

4756
# fetch the current version of virtualenv (which we mostly use for its copy of pip)

setup.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ def run(self):
191191
self.spawn(['/usr/bin/ibtool','--compile', '%s/viewer.nib'%rsrc_dir, "app/Resources/English.lproj/PlotDeviceScript.xib"])
192192
self.copy_file("app/Resources/PlotDeviceFile.icns", '%s/viewer.icns'%rsrc_dir)
193193

194+
194195
class BuildAppCommand(Command):
195196
description = "Build PlotDevice.app with xcode"
196197
user_options = []
@@ -231,6 +232,8 @@ def initialize_options(self):
231232
def finalize_options(self):
232233
self.verbose=0
233234
build_py2app.finalize_options(self)
235+
os.environ['ACTION'] = 'build' # flag for app/deps/build.py
236+
234237
def run(self):
235238
build_py2app.run(self)
236239
if self.dry_run:
@@ -243,20 +246,19 @@ def run(self):
243246
# set up internal paths and ensure destination dirs exist
244247
RSRC = self.resdir
245248
BIN = join(dirname(RSRC), 'SharedSupport')
246-
MODULE = join(self.bdist_base, 'lib/plotdevice')
247-
PY = join(RSRC, 'python')
248-
for pth in BIN, PY:
249-
self.mkpath(pth)
249+
LIB = join(RSRC, 'python')
250+
MODULES = join(self.bdist_base, 'lib')
250251

251252
# install the module in Resources/python
252-
self.spawn(['/usr/bin/ditto', MODULE, join(PY, 'plotdevice')])
253+
self.spawn(['/usr/bin/ditto', MODULES, LIB])
253254

254255
# discard the eggery-pokery
255256
remove_tree(join(RSRC,'lib'), dry_run=self.dry_run)
256257
os.unlink(join(RSRC,'include'))
257258
os.unlink(join(RSRC,'site.pyc'))
258259

259260
# place the command line tool in SharedSupport
261+
self.mkpath(BIN)
260262
self.copy_file("app/plotdevice", BIN)
261263

262264
# success!
@@ -302,7 +304,7 @@ def run(self):
302304
)
303305

304306
# Download Sparkle (if necessary) and copy it into the bundle
305-
ORIG = 'app/deps/Sparkle-%s/Sparkle.framework'%SPARKLE_VERSION
307+
ORIG = 'app/deps/vendor/Sparkle-%s/Sparkle.framework'%SPARKLE_VERSION
306308
SPARKLE = join(APP,'Contents/Frameworks/Sparkle.framework')
307309
if not exists(ORIG):
308310
self.mkpath(dirname(ORIG))
@@ -385,7 +387,8 @@ def run(self):
385387
cmdclass={
386388
'build_py': BuildCommand,
387389
'py2app': BuildPy2AppCommand,
388-
}
390+
},
391+
install_requires=[]
389392
))
390393

391394
# begin the build process

0 commit comments

Comments
 (0)