Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100755 237 lines (187 sloc) 7.943 kb
e9a479a Jeff Hammel [Bug 754338] put setup_development.py shebang back in;r=wlach
k0s authored
1 #!/usr/bin/env python
2
e816caa William Lachance Update licensing headers for new MPL 2.0 boilerplate
wlach authored
3 # This Source Code Form is subject to the terms of the Mozilla Public
4 # License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 # You can obtain one at http://mozilla.org/MPL/2.0/.
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
6
7 """
8 Setup mozbase packages for development.
9
10 Packages may be specified as command line arguments.
11 If no arguments are given, install all packages.
12
13 See https://wiki.mozilla.org/Auto-tools/Projects/MozBase
14 """
15
16 import pkg_resources
17 import os
18 import sys
19 from optparse import OptionParser
20
21 from subprocess import PIPE
22 try:
23 from subprocess import check_call as call
24 except ImportError:
25 from subprocess import call
26
27
28 # directory containing this file
29 here = os.path.dirname(os.path.abspath(__file__))
30
31 # all python packages
32 all_packages = [i for i in os.listdir(here)
33 if os.path.exists(os.path.join(here, i, 'setup.py'))]
34
35 def cycle_check(order, dependencies):
36 """ensure no cyclic dependencies"""
37 order_dict = dict([(j, i) for i, j in enumerate(order)])
38 for package, deps in dependencies.items():
39 index = order_dict[package]
40 for d in deps:
41 assert index > order_dict[d], "Cyclic dependencies detected"
42
82f13ef Jeff Hammel Bug 760722 - automatic version bumping for mozbase;r=whimboo
k0s authored
43 def info(directory):
44 "get the package setup.py information"
45
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
46 assert os.path.exists(os.path.join(directory, 'setup.py'))
47
48 # setup the egg info
49 call([sys.executable, 'setup.py', 'egg_info'], cwd=directory, stdout=PIPE)
50
51 # get the .egg-info directory
82f13ef Jeff Hammel Bug 760722 - automatic version bumping for mozbase;r=whimboo
k0s authored
52 egg_info = [entry for entry in os.listdir(directory)
53 if entry.endswith('.egg-info')]
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
54 assert len(egg_info) == 1, 'Expected one .egg-info directory in %s, got: %s' % (directory, egg_info)
55 egg_info = os.path.join(directory, egg_info[0])
56 assert os.path.isdir(egg_info), "%s is not a directory" % egg_info
57
58 # read the package information
59 pkg_info = os.path.join(egg_info, 'PKG-INFO')
60 info_dict = {}
61 for line in file(pkg_info).readlines():
62 if not line or line[0].isspace():
63 continue # XXX neglects description
64 assert ':' in line
65 key, value = [i.strip() for i in line.split(':', 1)]
66 info_dict[key] = value
67
82f13ef Jeff Hammel Bug 760722 - automatic version bumping for mozbase;r=whimboo
k0s authored
68 return info_dict
69
70 def get_dependencies(directory):
71 "returns the package name and dependencies given a package directory"
72
73 # get the package metadata
74 info_dict = info(directory)
75
76 # get the .egg-info directory
77 egg_info = [entry for entry in os.listdir(directory)
78 if entry.endswith('.egg-info')][0]
79
80 # read the dependencies
81 requires = os.path.join(directory, egg_info, 'requires.txt')
82 if os.path.exists(requires):
83 dependencies = [line.strip()
84 for line in file(requires).readlines()
85 if line.strip()]
86 else:
87 dependencies = []
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
88
89 # return the information
90 return info_dict['Name'], dependencies
91
82f13ef Jeff Hammel Bug 760722 - automatic version bumping for mozbase;r=whimboo
k0s authored
92 def dependency_info(dep):
93 "return dictionary of dependency information from a dependency string"
94 retval = dict(Name=None, Type=None, Version=None)
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
95 for joiner in ('==', '<=', '>='):
96 if joiner in dep:
82f13ef Jeff Hammel Bug 760722 - automatic version bumping for mozbase;r=whimboo
k0s authored
97 retval['Type'] = joiner
98 name, version = [i.strip() for i in dep.split(joiner, 1)]
99 retval['Name'] = name
100 retval['Version'] = version
101 break
102 else:
aa50f7c Jonathan Griffin Bug 801973 - Fix setup_development.py for versionless deps, r=jhammel
jonallengriffin authored
103 retval['Name'] = dep.strip()
82f13ef Jeff Hammel Bug 760722 - automatic version bumping for mozbase;r=whimboo
k0s authored
104 return retval
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
105
106 def unroll_dependencies(dependencies):
107 """
108 unroll a set of dependencies to a flat list
109
110 dependencies = {'packageA': set(['packageB', 'packageC', 'packageF']),
111 'packageB': set(['packageC', 'packageD', 'packageE', 'packageG']),
112 'packageC': set(['packageE']),
113 'packageE': set(['packageF', 'packageG']),
114 'packageF': set(['packageG']),
115 'packageX': set(['packageA', 'packageG'])}
116 """
117
118 order = []
119
120 # flatten all
121 packages = set(dependencies.keys())
122 for deps in dependencies.values():
123 packages.update(deps)
124
125 while len(order) != len(packages):
126
127 for package in packages.difference(order):
128 if set(dependencies.get(package, set())).issubset(order):
129 order.append(package)
130 break
131 else:
132 raise AssertionError("Cyclic dependencies detected")
133
134 cycle_check(order, dependencies) # sanity check
fef85bb Andrew Halberstadt Bug 703278 - Fix licenses and remove trailing whitespace (aka fix and
ahal authored
135
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
136 return order
fef85bb Andrew Halberstadt Bug 703278 - Fix licenses and remove trailing whitespace (aka fix and
ahal authored
137
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
138
139 def main(args=sys.argv[1:]):
140
141 # parse command line options
142 usage = '%prog [options] [package] [package] [...]'
143 parser = OptionParser(usage=usage, description=__doc__)
144 parser.add_option('-d', '--dependencies', dest='list_dependencies',
145 action='store_true', default=False,
146 help="list dependencies for the packages")
147 parser.add_option('--list', action='store_true', default=False,
148 help="list what will be installed")
149 options, packages = parser.parse_args(args)
150
151 if not packages:
152 # install all packages
153 packages = sorted(all_packages)
154
155 # ensure specified packages are in the list
1cf1471 Jeff Hammel improve error message
k0s authored
156 assert set(packages).issubset(all_packages), "Packages should be in %s (You gave: %s)" % (all_packages, packages)
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
157
158 if options.list_dependencies:
159 # list the package dependencies
160 for package in packages:
82f13ef Jeff Hammel Bug 760722 - automatic version bumping for mozbase;r=whimboo
k0s authored
161 print '%s: %s' % get_dependencies(os.path.join(here, package))
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
162 parser.exit()
163
164 # gather dependencies
b7ed866 Jeff Hammel Bug 759836 - setup_development.py doesnt always actually setup for devel...
k0s authored
165 # TODO: version conflict checking
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
166 deps = {}
b7ed866 Jeff Hammel Bug 759836 - setup_development.py doesnt always actually setup for devel...
k0s authored
167 alldeps = {}
2cd1d4e rework script following Bug 695866 - move ManifestDestiny to mozbase rep...
Jeff Hammel authored
168 mapping = {} # mapping from subdir name to package name
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
169 # core dependencies
170 for package in packages:
82f13ef Jeff Hammel Bug 760722 - automatic version bumping for mozbase;r=whimboo
k0s authored
171 key, value = get_dependencies(os.path.join(here, package))
172 deps[key] = [dependency_info(dep)['Name'] for dep in value]
2cd1d4e rework script following Bug 695866 - move ManifestDestiny to mozbase rep...
Jeff Hammel authored
173 mapping[package] = key
b7ed866 Jeff Hammel Bug 759836 - setup_development.py doesnt always actually setup for devel...
k0s authored
174
175 # keep track of all dependencies for non-mozbase packages
176 for dep in value:
82f13ef Jeff Hammel Bug 760722 - automatic version bumping for mozbase;r=whimboo
k0s authored
177 alldeps[dependency_info(dep)['Name']] = ''.join(dep.split())
b7ed866 Jeff Hammel Bug 759836 - setup_development.py doesnt always actually setup for devel...
k0s authored
178
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
179 # indirect dependencies
180 flag = True
181 while flag:
182 flag = False
183 for value in deps.values():
184 for dep in value:
185 if dep in all_packages and dep not in deps:
82f13ef Jeff Hammel Bug 760722 - automatic version bumping for mozbase;r=whimboo
k0s authored
186 key, value = get_dependencies(os.path.join(here, dep))
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
187 deps[key] = [sanitize_dependency(dep) for dep in value]
b7ed866 Jeff Hammel Bug 759836 - setup_development.py doesnt always actually setup for devel...
k0s authored
188
189 for dep in value:
190 alldeps[sanitize_dependency(dep)] = ''.join(dep.split())
2cd1d4e rework script following Bug 695866 - move ManifestDestiny to mozbase rep...
Jeff Hammel authored
191 mapping[package] = key
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
192 flag = True
193 break
194 if flag:
195 break
196
2cd1d4e rework script following Bug 695866 - move ManifestDestiny to mozbase rep...
Jeff Hammel authored
197 # get the remaining names for the mapping
198 for package in all_packages:
199 if package in mapping:
200 continue
82f13ef Jeff Hammel Bug 760722 - automatic version bumping for mozbase;r=whimboo
k0s authored
201 key, value = get_dependencies(os.path.join(here, package))
2cd1d4e rework script following Bug 695866 - move ManifestDestiny to mozbase rep...
Jeff Hammel authored
202 mapping[package] = key
203
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
204 # unroll dependencies
205 unrolled = unroll_dependencies(deps)
206
2cd1d4e rework script following Bug 695866 - move ManifestDestiny to mozbase rep...
Jeff Hammel authored
207 # make a reverse mapping: package name -> subdirectory
208 reverse_mapping = dict([(j,i) for i, j in mapping.items()])
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
209
2cd1d4e rework script following Bug 695866 - move ManifestDestiny to mozbase rep...
Jeff Hammel authored
210 # we only care about dependencies in mozbase
211 unrolled = [package for package in unrolled if package in reverse_mapping]
fef85bb Andrew Halberstadt Bug 703278 - Fix licenses and remove trailing whitespace (aka fix and
ahal authored
212
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
213 if options.list:
214 # list what will be installed
215 for package in unrolled:
216 print package
217 parser.exit()
218
1f679a8 Jeff Hammel Bug 805440 - Mozrunner installed from pypi when running setup_developmen...
k0s authored
219 # set up the packages for development
220 for package in unrolled:
221 call([sys.executable, 'setup.py', 'develop', '--no-deps'],
222 cwd=os.path.join(here, reverse_mapping[package]))
223
b7ed866 Jeff Hammel Bug 759836 - setup_development.py doesnt always actually setup for devel...
k0s authored
224 # install non-mozbase dependencies
225 # these need to be installed separately and the --no-deps flag
226 # subsequently used due to a bug in setuptools; see
227 # https://bugzilla.mozilla.org/show_bug.cgi?id=759836
228 pypi_deps = dict([(i, j) for i,j in alldeps.items()
229 if i not in unrolled])
230 for package, version in pypi_deps.items():
231 # easy_install should be available since we rely on setuptools
232 call(['easy_install', version])
233
32e90d9 Jeff Hammel add a script to setup for development
k0s authored
234
235 if __name__ == '__main__':
236 main()
Something went wrong with that request. Please try again.