-
Notifications
You must be signed in to change notification settings - Fork 45
/
build.py
executable file
·150 lines (116 loc) · 4.24 KB
/
build.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
#! /usr/bin/env python
#This script builds a standalone version of mergepbx.py
#all scripts are bundled into one single file that can be easily distributed
#the user will only need the file generated by this script and he can execute
#it like any other program
#idea: http://code.activestate.com/recipes/215301/
import zipfile
import tempfile
from ConfigParser import SafeConfigParser
from ConfigParser import NoOptionError
from collections import namedtuple
import os
import stat
import sys
import fnmatch
#templates
HEADER = \
"""\
#!/bin/sh
PYTHON=$(which python 2>/dev/null)
if [ ! -x "$PYTHON" ] ; then
echo "Python executable not found - can't continue!"
echo "Please install Python (>= 2.3) to run this program"
exit 1
fi
read -r -d '' PYTHON_CODE << END_OF_PYTHON_CODE
import sys
sys.path.insert(0, sys.argv[1])
del sys.argv[0:1]
import %(mainmodule)s
%(mainmodule)s.main()
END_OF_PYTHON_CODE
exec $PYTHON -c "${PYTHON_CODE}" "${0}" "${@}"
"""
class Manifest(object):
ModuleFile = namedtuple("ModuleFile", ("file_path", "egg_path"))
def __init__(self, mainmodule, files, default_target=None):
self.mainmodule = mainmodule
self.files = files
self._default_target = default_target
def iterfiles(self):
return iter(self.files)
def default_target(self):
return self._default_target
@staticmethod
def read(fpath):
config = SafeConfigParser()
config.read(fpath)
mainmodule = config.get("build", "mainmodule")
mainmodule_path = config.get("build", "mainmodule_path")
modules = config.get("build", "modules").split(",")
try:
default_target = config.get("build", "default_target")
except NoOptionError:
default_target = None
print modules
#add modules
files = []
for module in modules:
path = config.get(module, "path")
files += Manifest._get_module_files(module, path)
#add main module
files += [Manifest.ModuleFile(mainmodule_path, mainmodule + ".py")]
return Manifest(mainmodule, files, default_target)
@staticmethod
def _get_module_files(module, path):
module_files = []
for (dir_path, dirs, files) in os.walk(path):
python_files = fnmatch.filter(files, "*.py")
python_files = [os.path.join(dir_path, file) for file in python_files]
egg_python_files = [Manifest._get_egg_path(module, path, python_file) for python_file in python_files]
module_files += [Manifest.ModuleFile(python_file, egg_python_file) for python_file, egg_python_file in zip(python_files, egg_python_files)]
return module_files
@staticmethod
def _get_egg_path(module, module_path, file_path):
rel_file_path = os.path.relpath(file_path, module_path)
rel_file_path = os.path.normpath(rel_file_path)
egg_path_components = [module] + rel_file_path.split(os.sep)
egg_path = str.join("/", egg_path_components)
return egg_path
def main():
#default settings
target_file = None
manifest_file = "MANIFEST"
if len(sys.argv) >= 2:
target_file = sys.argv[1]
if len(sys.argv) >= 3:
manifest_file = sys.argv[2]
manifest = Manifest.read(manifest_file)
if not target_file:
target_file = manifest.default_target()
if not target_file:
sys.stderr.write("please specify a target by using: ./build.py target\n")
sys.exit(os.EX_USAGE)
build(target_file, manifest)
def build(target_file, manifest):
pack_egg(target_file, manifest)
def pack_egg(target_file, manifest):
zip_fd, zip_path = tempfile.mkstemp()
egg = zipfile.ZipFile(zip_path, "w")
for file_path, egg_path in manifest.iterfiles():
print "adding %s as %s" % (file_path, egg_path)
egg.write(file_path, egg_path)
egg.close()
target = open(target_file, "w")
eggf = open(zip_path, "r")
target.write(HEADER % {
"mainmodule" : manifest.mainmodule
})
target.write(eggf.read())
target.close()
eggf.close()
egg_permissions = os.stat(target_file).st_mode
os.chmod(target_file, egg_permissions | (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH))
if __name__ == "__main__":
main()