Merge lp:~gary/zc.buildout/python-support-5-initial-egg-control into lp:zc.buildout
- python-support-5-initial-egg-control
- Merge into trunk
Status: | Needs review |
---|---|
Proposed branch: | lp:~gary/zc.buildout/python-support-5-initial-egg-control |
Merge into: | lp:zc.buildout |
Prerequisite: | lp:~gary/zc.buildout/python-support-4 |
Diff against target: |
1188 lines (+651/-156) 8 files modified
.bzrignore (+9/-0) src/zc/buildout/easy_install.py (+223/-104) src/zc/buildout/easy_install.txt (+73/-3) src/zc/buildout/testing.py (+33/-6) src/zc/buildout/tests.py (+301/-31) z3c.recipe.scripts_/src/z3c/recipe/scripts/README.txt (+5/-5) z3c.recipe.scripts_/src/z3c/recipe/scripts/scripts.py (+6/-6) z3c.recipe.scripts_/src/z3c/recipe/scripts/tests.py (+1/-1) |
To merge this branch: | bzr merge lp:~gary/zc.buildout/python-support-5-initial-egg-control |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Francis J. Lacoste (community) | Approve | ||
Review via email: mp+20010@code.launchpad.net |
Commit message
Description of the change
Gary Poster (gary) wrote : | # |
Note also that I moved _get_system_paths to the top of easy_install.py because it was now used by both the Installer and sitepackage_
Francis J. Lacoste (flacoste) wrote : | # |
Hi Gary,
My only comment is about some API incompatible changes you made. Not sure it's a problem or not. Otherwise, all fine.
> === modified file 'src/zc/
> def use_dependency_
> old = Installer.
> if setting is not None:
> @@ -858,9 +1014,13 @@
> links=(), index=None,
> executable=
> path=None, working_set=None, newest=True, versions=None,
> - use_dependency_
> + use_dependency_
> + allowed_
> installer = Installer(dest, links, index, executable, always_unzip, path,
> newest, versions, use_dependency_
> + include_
> + allowed_
> + allowed_
> allow_hosts=
> return installer.
>
> @@ -868,9 +1028,14 @@
> def build(spec, dest, build_ext,
> links=(), index=None,
> executable=
> - path=None, newest=True, versions=None, allow_hosts=
> + path=None, newest=True, versions=None, include_
> + allowed_
> installer = Installer(dest, links, index, executable, True, path, newest,
> - versions, allow_hosts=
> + versions,
> + include_
> + allowed_
> + allowed_
> + allow_hosts=
> return installer.
>
Should we care about API compatibility in these two functions? You added
parameters before allow_hosts. Theorically, this breaks API compatibility for
call sites passing things by parameters. Arguably a bad idea with such a
signature, but it's your call :-)
- 555. By Gary Poster
-
be a better backwards-
compatibilty citizen
Gary Poster (gary) wrote : | # |
Yeah, what I did was on purpose and after consideration, but maybe wrong all the same. :-) I changed it.
Thanks!
Unmerged revisions
- 555. By Gary Poster
-
be a better backwards-
compatibilty citizen - 554. By Gary Poster
-
merge from gary-4
- 553. By Gary Poster
-
merge from gary-4
- 552. By Gary Poster
-
settle on "include-
site-packages" and migrate all variations of "add-site-packages" to that spelling. - 551. By Gary Poster
-
merge from gary-4
- 550. By Gary Poster
-
support limiting packages from site-packages
- 549. By Gary Poster
-
propagate merge from gary-3 <- gary-2 <- gary-1 <- trunk
- 548. By gary
-
fix some tests on other Python versions
- 547. By gary
-
revert attempt to skip some of the pkg_resources dance: it caused me trouble.
- 546. By gary
-
simplify resulting code a bit more and try again to remove warnings
Preview Diff
1 | === added file '.bzrignore' | |||
2 | --- .bzrignore 1970-01-01 00:00:00 +0000 | |||
3 | +++ .bzrignore 2010-02-24 23:22:13 +0000 | |||
4 | @@ -0,0 +1,9 @@ | |||
5 | 1 | .installed.cfg | ||
6 | 2 | bin | ||
7 | 3 | build | ||
8 | 4 | develop-eggs | ||
9 | 5 | eggs | ||
10 | 6 | parts | ||
11 | 7 | src/zc.buildout.egg-info | ||
12 | 8 | z3c.recipe.scripts_/src/z3c.recipe.scripts.egg-info | ||
13 | 9 | zc.recipe.egg_/src/zc.recipe.egg.egg-info | ||
14 | 0 | 10 | ||
15 | === modified file 'src/zc/buildout/easy_install.py' | |||
16 | --- src/zc/buildout/easy_install.py 2010-02-24 23:22:13 +0000 | |||
17 | +++ src/zc/buildout/easy_install.py 2010-02-24 23:22:13 +0000 | |||
18 | @@ -19,6 +19,7 @@ | |||
19 | 19 | """ | 19 | """ |
20 | 20 | 20 | ||
21 | 21 | import distutils.errors | 21 | import distutils.errors |
22 | 22 | import fnmatch | ||
23 | 22 | import glob | 23 | import glob |
24 | 23 | import logging | 24 | import logging |
25 | 24 | import os | 25 | import os |
26 | @@ -68,6 +69,64 @@ | |||
27 | 68 | if os.path.normpath(setuptools_loc) != os.path.normpath(buildout_loc): | 69 | if os.path.normpath(setuptools_loc) != os.path.normpath(buildout_loc): |
28 | 69 | buildout_and_setuptools_path.append(buildout_loc) | 70 | buildout_and_setuptools_path.append(buildout_loc) |
29 | 70 | 71 | ||
30 | 72 | def _get_system_paths(executable): | ||
31 | 73 | """Return lists of standard lib and site paths for executable. | ||
32 | 74 | """ | ||
33 | 75 | # We want to get a list of the site packages, which is not easy. | ||
34 | 76 | # The canonical way to do this is to use | ||
35 | 77 | # distutils.sysconfig.get_python_lib(), but that only returns a | ||
36 | 78 | # single path, which does not reflect reality for many system | ||
37 | 79 | # Pythons, which have multiple additions. Instead, we start Python | ||
38 | 80 | # with -S, which does not import site.py and set up the extra paths | ||
39 | 81 | # like site-packages or (Ubuntu/Debian) dist-packages and | ||
40 | 82 | # python-support. We then compare that sys.path with the normal one | ||
41 | 83 | # (minus user packages if this is Python 2.6, because we don't | ||
42 | 84 | # support those (yet?). The set of the normal one minus the set of | ||
43 | 85 | # the ones in ``python -S`` is the set of packages that are | ||
44 | 86 | # effectively site-packages. | ||
45 | 87 | # | ||
46 | 88 | # The given executable might not be the current executable, so it is | ||
47 | 89 | # appropriate to do another subprocess to figure out what the | ||
48 | 90 | # additional site-package paths are. Moreover, even if this | ||
49 | 91 | # executable *is* the current executable, this code might be run in | ||
50 | 92 | # the context of code that has manipulated the sys.path--for | ||
51 | 93 | # instance, to add local zc.buildout or setuptools eggs. | ||
52 | 94 | def get_sys_path(*args, **kwargs): | ||
53 | 95 | cmd = [executable] | ||
54 | 96 | cmd.extend(args) | ||
55 | 97 | cmd.extend([ | ||
56 | 98 | "-c", "import sys, os;" | ||
57 | 99 | "print repr([os.path.normpath(p) for p in sys.path if p])"]) | ||
58 | 100 | # Windows needs some (as yet to be determined) part of the real env. | ||
59 | 101 | env = os.environ.copy() | ||
60 | 102 | env.update(kwargs) | ||
61 | 103 | _proc = subprocess.Popen( | ||
62 | 104 | cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) | ||
63 | 105 | stdout, stderr = _proc.communicate(); | ||
64 | 106 | if _proc.returncode: | ||
65 | 107 | raise RuntimeError( | ||
66 | 108 | 'error trying to get system packages:\n%s' % (stderr,)) | ||
67 | 109 | res = eval(stdout.strip()) | ||
68 | 110 | try: | ||
69 | 111 | res.remove('.') | ||
70 | 112 | except ValueError: | ||
71 | 113 | pass | ||
72 | 114 | return res | ||
73 | 115 | stdlib = get_sys_path('-S') # stdlib only | ||
74 | 116 | no_user_paths = get_sys_path(PYTHONNOUSERSITE='x') | ||
75 | 117 | site_paths = [p for p in no_user_paths if p not in stdlib] | ||
76 | 118 | return (stdlib, site_paths) | ||
77 | 119 | |||
78 | 120 | def _get_version_info(executable): | ||
79 | 121 | cmd = [executable, '-Sc', 'import sys; print repr(sys.version_info)'] | ||
80 | 122 | _proc = subprocess.Popen( | ||
81 | 123 | cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) | ||
82 | 124 | stdout, stderr = _proc.communicate(); | ||
83 | 125 | if _proc.returncode: | ||
84 | 126 | raise RuntimeError( | ||
85 | 127 | 'error trying to get system packages:\n%s' % (stderr,)) | ||
86 | 128 | return eval(stdout.strip()) | ||
87 | 129 | |||
88 | 71 | 130 | ||
89 | 72 | class IncompatibleVersionError(zc.buildout.UserError): | 131 | class IncompatibleVersionError(zc.buildout.UserError): |
90 | 73 | """A specified version is incompatible with a given requirement. | 132 | """A specified version is incompatible with a given requirement. |
91 | @@ -110,7 +169,12 @@ | |||
92 | 110 | 169 | ||
93 | 111 | 170 | ||
94 | 112 | _indexes = {} | 171 | _indexes = {} |
96 | 113 | def _get_index(executable, index_url, find_links, allow_hosts=('*',)): | 172 | def _get_index(executable, index_url, find_links, allow_hosts=('*',), |
97 | 173 | path=None): | ||
98 | 174 | # If path is None, the index will use sys.path. If you provide an empty | ||
99 | 175 | # path ([]), it will complain uselessly about missing index pages for | ||
100 | 176 | # packages found in the paths that you expect to use. Therefore, this path | ||
101 | 177 | # is always the same as the _env path in the Installer. | ||
102 | 114 | key = executable, index_url, tuple(find_links) | 178 | key = executable, index_url, tuple(find_links) |
103 | 115 | index = _indexes.get(key) | 179 | index = _indexes.get(key) |
104 | 116 | if index is not None: | 180 | if index is not None: |
105 | @@ -119,7 +183,8 @@ | |||
106 | 119 | if index_url is None: | 183 | if index_url is None: |
107 | 120 | index_url = default_index_url | 184 | index_url = default_index_url |
108 | 121 | index = AllowHostsPackageIndex( | 185 | index = AllowHostsPackageIndex( |
110 | 122 | index_url, hosts=allow_hosts, python=_get_version(executable) | 186 | index_url, hosts=allow_hosts, search_path=path, |
111 | 187 | python=_get_version(executable) | ||
112 | 123 | ) | 188 | ) |
113 | 124 | 189 | ||
114 | 125 | if find_links: | 190 | if find_links: |
115 | @@ -216,6 +281,8 @@ | |||
116 | 216 | _use_dependency_links = True | 281 | _use_dependency_links = True |
117 | 217 | _allow_picked_versions = True | 282 | _allow_picked_versions = True |
118 | 218 | _always_unzip = False | 283 | _always_unzip = False |
119 | 284 | _include_site_packages = True | ||
120 | 285 | _allowed_eggs_from_site_packages = ('*',) | ||
121 | 219 | 286 | ||
122 | 220 | def __init__(self, | 287 | def __init__(self, |
123 | 221 | dest=None, | 288 | dest=None, |
124 | @@ -227,7 +294,9 @@ | |||
125 | 227 | newest=True, | 294 | newest=True, |
126 | 228 | versions=None, | 295 | versions=None, |
127 | 229 | use_dependency_links=None, | 296 | use_dependency_links=None, |
129 | 230 | allow_hosts=('*',) | 297 | allow_hosts=('*',), |
130 | 298 | include_site_packages=None, | ||
131 | 299 | allowed_eggs_from_site_packages=None | ||
132 | 231 | ): | 300 | ): |
133 | 232 | self._dest = dest | 301 | self._dest = dest |
134 | 233 | self._allow_hosts = allow_hosts | 302 | self._allow_hosts = allow_hosts |
135 | @@ -249,7 +318,28 @@ | |||
136 | 249 | self._executable = executable | 318 | self._executable = executable |
137 | 250 | if always_unzip is not None: | 319 | if always_unzip is not None: |
138 | 251 | self._always_unzip = always_unzip | 320 | self._always_unzip = always_unzip |
140 | 252 | path = (path and path[:] or []) + buildout_and_setuptools_path | 321 | path = (path and path[:] or []) |
141 | 322 | if include_site_packages is not None: | ||
142 | 323 | self._include_site_packages = include_site_packages | ||
143 | 324 | if allowed_eggs_from_site_packages is not None: | ||
144 | 325 | self._allowed_eggs_from_site_packages = tuple( | ||
145 | 326 | allowed_eggs_from_site_packages) | ||
146 | 327 | stdlib, self._site_packages = _get_system_paths(executable) | ||
147 | 328 | version_info = _get_version_info(executable) | ||
148 | 329 | if version_info == sys.version_info: | ||
149 | 330 | # Maybe we can add the buildout and setuptools path. If we | ||
150 | 331 | # are including site_packages, we only have to include the extra | ||
151 | 332 | # bits here, so we don't duplicate. On the other hand, if we | ||
152 | 333 | # are not including site_packages, we only want to include the | ||
153 | 334 | # parts that are not in site_packages, so the code is the same. | ||
154 | 335 | path.extend( | ||
155 | 336 | set(buildout_and_setuptools_path).difference( | ||
156 | 337 | self._site_packages)) | ||
157 | 338 | if self._include_site_packages: | ||
158 | 339 | path.extend(self._site_packages) | ||
159 | 340 | # else we could try to still include the buildout_and_setuptools_path | ||
160 | 341 | # if the elements are not in site_packages, but we're not bothering | ||
161 | 342 | # with this optimization for now, in the name of code simplicity. | ||
162 | 253 | if dest is not None and dest not in path: | 343 | if dest is not None and dest not in path: |
163 | 254 | path.insert(0, dest) | 344 | path.insert(0, dest) |
164 | 255 | self._path = path | 345 | self._path = path |
165 | @@ -258,13 +348,42 @@ | |||
166 | 258 | self._newest = newest | 348 | self._newest = newest |
167 | 259 | self._env = pkg_resources.Environment(path, | 349 | self._env = pkg_resources.Environment(path, |
168 | 260 | python=_get_version(executable)) | 350 | python=_get_version(executable)) |
170 | 261 | self._index = _get_index(executable, index, links, self._allow_hosts) | 351 | self._index = _get_index(executable, index, links, self._allow_hosts, |
171 | 352 | self._path) | ||
172 | 262 | 353 | ||
173 | 263 | if versions is not None: | 354 | if versions is not None: |
174 | 264 | self._versions = versions | 355 | self._versions = versions |
175 | 265 | 356 | ||
176 | 357 | _allowed_eggs_from_site_packages_regex = None | ||
177 | 358 | def allow_site_package_egg(self, name): | ||
178 | 359 | if (not self._include_site_packages or | ||
179 | 360 | not self._allowed_eggs_from_site_packages): | ||
180 | 361 | # If the answer is a blanket "no," perform a shortcut. | ||
181 | 362 | return False | ||
182 | 363 | if self._allowed_eggs_from_site_packages_regex is None: | ||
183 | 364 | pattern = '(%s)' % ( | ||
184 | 365 | '|'.join( | ||
185 | 366 | fnmatch.translate(name) | ||
186 | 367 | for name in self._allowed_eggs_from_site_packages), | ||
187 | 368 | ) | ||
188 | 369 | self._allowed_eggs_from_site_packages_regex = re.compile(pattern) | ||
189 | 370 | return bool(self._allowed_eggs_from_site_packages_regex.match(name)) | ||
190 | 371 | |||
191 | 266 | def _satisfied(self, req, source=None): | 372 | def _satisfied(self, req, source=None): |
193 | 267 | dists = [dist for dist in self._env[req.project_name] if dist in req] | 373 | # We get all distributions that match the given requirement. If we are |
194 | 374 | # not supposed to include site-packages for the given egg, we also | ||
195 | 375 | # filter those out. Even if include_site_packages is False and so we | ||
196 | 376 | # have excluded site packages from the _env's paths (see | ||
197 | 377 | # Installer.__init__), we need to do the filtering here because an | ||
198 | 378 | # .egg-link, such as one for setuptools or zc.buildout installed by | ||
199 | 379 | # zc.buildout.buildout.Buildout.bootstrap, can indirectly include a | ||
200 | 380 | # path in our _site_packages. | ||
201 | 381 | dists = [dist for dist in self._env[req.project_name] if ( | ||
202 | 382 | dist in req and ( | ||
203 | 383 | dist.location not in self._site_packages or | ||
204 | 384 | self.allow_site_package_egg(dist.project_name)) | ||
205 | 385 | ) | ||
206 | 386 | ] | ||
207 | 268 | if not dists: | 387 | if not dists: |
208 | 269 | logger.debug('We have no distributions for %s that satisfies %r.', | 388 | logger.debug('We have no distributions for %s that satisfies %r.', |
209 | 270 | req.project_name, str(req)) | 389 | req.project_name, str(req)) |
210 | @@ -465,14 +584,22 @@ | |||
211 | 465 | # Nothing is available. | 584 | # Nothing is available. |
212 | 466 | return None | 585 | return None |
213 | 467 | 586 | ||
222 | 468 | # Filter the available dists for the requirement and source flag | 587 | # Filter the available dists for the requirement and source flag. If |
223 | 469 | dists = [dist for dist in index[requirement.project_name] | 588 | # we are not supposed to include site-packages for the given egg, we |
224 | 470 | if ((dist in requirement) | 589 | # also filter those out. Even if include_site_packages is False and so |
225 | 471 | and | 590 | # we have excluded site packages from the _env's paths (see |
226 | 472 | ((not source) or | 591 | # Installer.__init__), we need to do the filtering here because an |
227 | 473 | (dist.precedence == pkg_resources.SOURCE_DIST) | 592 | # .egg-link, such as one for setuptools or zc.buildout installed by |
228 | 474 | ) | 593 | # zc.buildout.buildout.Buildout.bootstrap, can indirectly include a |
229 | 475 | ) | 594 | # path in our _site_packages. |
230 | 595 | dists = [dist for dist in index[requirement.project_name] if ( | ||
231 | 596 | dist in requirement and ( | ||
232 | 597 | dist.location not in self._site_packages or | ||
233 | 598 | self.allow_site_package_egg(dist.project_name)) | ||
234 | 599 | and ( | ||
235 | 600 | (not source) or | ||
236 | 601 | (dist.precedence == pkg_resources.SOURCE_DIST)) | ||
237 | 602 | ) | ||
238 | 476 | ] | 603 | ] |
239 | 477 | 604 | ||
240 | 478 | # If we prefer final dists, filter for final and use the | 605 | # If we prefer final dists, filter for final and use the |
241 | @@ -632,7 +759,7 @@ | |||
242 | 632 | self._links.append(link) | 759 | self._links.append(link) |
243 | 633 | self._index = _get_index(self._executable, | 760 | self._index = _get_index(self._executable, |
244 | 634 | self._index_url, self._links, | 761 | self._index_url, self._links, |
246 | 635 | self._allow_hosts) | 762 | self._allow_hosts, self._path) |
247 | 636 | 763 | ||
248 | 637 | for dist in dists: | 764 | for dist in dists: |
249 | 638 | # Check whether we picked a version and, if we did, report it: | 765 | # Check whether we picked a version and, if we did, report it: |
250 | @@ -713,35 +840,52 @@ | |||
251 | 713 | self._maybe_add_setuptools(ws, dist) | 840 | self._maybe_add_setuptools(ws, dist) |
252 | 714 | 841 | ||
253 | 715 | # OK, we have the requested distributions and they're in the working | 842 | # OK, we have the requested distributions and they're in the working |
259 | 716 | # set, but they may have unmet requirements. We'll simply keep | 843 | # set, but they may have unmet requirements. We'll resolve these |
260 | 717 | # trying to resolve requirements, adding missing requirements as they | 844 | # requirements. This is code modified from |
261 | 718 | # are reported. | 845 | # pkg_resources.WorkingSet.resolve. We can't reuse that code directly |
262 | 719 | # | 846 | # because we have to constrain our requirements (see |
263 | 720 | # Note that we don't pass in the environment, because we want | 847 | # versions_section_ignored_for_dependency_in_favor_of_site_packages in |
264 | 848 | # zc.buildout.tests). | ||
265 | 849 | requirements.reverse() # Set up the stack. | ||
266 | 850 | processed = {} # This is a set of processed requirements. | ||
267 | 851 | best = {} # This is a mapping of key -> dist. | ||
268 | 852 | # Note that we don't use the existing environment, because we want | ||
269 | 721 | # to look for new eggs unless what we have is the best that | 853 | # to look for new eggs unless what we have is the best that |
270 | 722 | # matches the requirement. | 854 | # matches the requirement. |
293 | 723 | while 1: | 855 | env = pkg_resources.Environment(ws.entries) |
294 | 724 | try: | 856 | while requirements: |
295 | 725 | ws.resolve(requirements) | 857 | # Process dependencies breadth-first. |
296 | 726 | except pkg_resources.DistributionNotFound, err: | 858 | req = self._constrain(requirements.pop(0)) |
297 | 727 | [requirement] = err | 859 | if req in processed: |
298 | 728 | requirement = self._constrain(requirement) | 860 | # Ignore cyclic or redundant dependencies. |
299 | 729 | if destination: | 861 | continue |
300 | 730 | logger.debug('Getting required %r', str(requirement)) | 862 | dist = best.get(req.key) |
301 | 731 | else: | 863 | if dist is None: |
302 | 732 | logger.debug('Adding required %r', str(requirement)) | 864 | # Find the best distribution and add it to the map. |
303 | 733 | _log_requirement(ws, requirement) | 865 | dist = ws.by_key.get(req.key) |
304 | 734 | 866 | if dist is None: | |
305 | 735 | for dist in self._get_dist(requirement, ws, self._always_unzip | 867 | try: |
306 | 736 | ): | 868 | dist = best[req.key] = env.best_match(req, ws) |
307 | 737 | 869 | except pkg_resources.VersionConflict, err: | |
308 | 738 | ws.add(dist) | 870 | raise VersionConflict(err, ws) |
309 | 739 | self._maybe_add_setuptools(ws, dist) | 871 | if dist is None: |
310 | 740 | except pkg_resources.VersionConflict, err: | 872 | if destination: |
311 | 741 | raise VersionConflict(err, ws) | 873 | logger.debug('Getting required %r', str(req)) |
312 | 742 | else: | 874 | else: |
313 | 743 | break | 875 | logger.debug('Adding required %r', str(req)) |
314 | 744 | 876 | _log_requirement(ws, req) | |
315 | 877 | for dist in self._get_dist(req, | ||
316 | 878 | ws, self._always_unzip): | ||
317 | 879 | ws.add(dist) | ||
318 | 880 | self._maybe_add_setuptools(ws, dist) | ||
319 | 881 | if dist not in req: | ||
320 | 882 | # Oops, the "best" so far conflicts with a dependency. | ||
321 | 883 | raise VersionConflict( | ||
322 | 884 | pkg_resources.VersionConflict(dist, req), ws) | ||
323 | 885 | requirements.extend(dist.requires(req.extras)[::-1]) | ||
324 | 886 | processed[req] = True | ||
325 | 887 | if dist.location in self._site_packages: | ||
326 | 888 | logger.debug('Egg from site-packages: %s', dist) | ||
327 | 745 | return ws | 889 | return ws |
328 | 746 | 890 | ||
329 | 747 | def build(self, spec, build_ext): | 891 | def build(self, spec, build_ext): |
330 | @@ -836,6 +980,18 @@ | |||
331 | 836 | Installer._prefer_final = bool(setting) | 980 | Installer._prefer_final = bool(setting) |
332 | 837 | return old | 981 | return old |
333 | 838 | 982 | ||
334 | 983 | def include_site_packages(setting=None): | ||
335 | 984 | old = Installer._include_site_packages | ||
336 | 985 | if setting is not None: | ||
337 | 986 | Installer._include_site_packages = bool(setting) | ||
338 | 987 | return old | ||
339 | 988 | |||
340 | 989 | def allowed_eggs_from_site_packages(setting=None): | ||
341 | 990 | old = Installer._allowed_eggs_from_site_packages | ||
342 | 991 | if setting is not None: | ||
343 | 992 | Installer._allowed_eggs_from_site_packages = tuple(setting) | ||
344 | 993 | return old | ||
345 | 994 | |||
346 | 839 | def use_dependency_links(setting=None): | 995 | def use_dependency_links(setting=None): |
347 | 840 | old = Installer._use_dependency_links | 996 | old = Installer._use_dependency_links |
348 | 841 | if setting is not None: | 997 | if setting is not None: |
349 | @@ -858,19 +1014,27 @@ | |||
350 | 858 | links=(), index=None, | 1014 | links=(), index=None, |
351 | 859 | executable=sys.executable, always_unzip=None, | 1015 | executable=sys.executable, always_unzip=None, |
352 | 860 | path=None, working_set=None, newest=True, versions=None, | 1016 | path=None, working_set=None, newest=True, versions=None, |
354 | 861 | use_dependency_links=None, allow_hosts=('*',)): | 1017 | use_dependency_links=None, allow_hosts=('*',), |
355 | 1018 | include_site_packages=None, allowed_eggs_from_site_packages=None): | ||
356 | 862 | installer = Installer(dest, links, index, executable, always_unzip, path, | 1019 | installer = Installer(dest, links, index, executable, always_unzip, path, |
357 | 863 | newest, versions, use_dependency_links, | 1020 | newest, versions, use_dependency_links, |
359 | 864 | allow_hosts=allow_hosts) | 1021 | allow_hosts=allow_hosts, |
360 | 1022 | include_site_packages=include_site_packages, | ||
361 | 1023 | allowed_eggs_from_site_packages= | ||
362 | 1024 | allowed_eggs_from_site_packages) | ||
363 | 865 | return installer.install(specs, working_set) | 1025 | return installer.install(specs, working_set) |
364 | 866 | 1026 | ||
365 | 867 | 1027 | ||
366 | 868 | def build(spec, dest, build_ext, | 1028 | def build(spec, dest, build_ext, |
367 | 869 | links=(), index=None, | 1029 | links=(), index=None, |
368 | 870 | executable=sys.executable, | 1030 | executable=sys.executable, |
370 | 871 | path=None, newest=True, versions=None, allow_hosts=('*',)): | 1031 | path=None, newest=True, versions=None, allow_hosts=('*',), |
371 | 1032 | include_site_packages=None, allowed_eggs_from_site_packages=None): | ||
372 | 872 | installer = Installer(dest, links, index, executable, True, path, newest, | 1033 | installer = Installer(dest, links, index, executable, True, path, newest, |
374 | 873 | versions, allow_hosts=allow_hosts) | 1034 | versions, allow_hosts=allow_hosts, |
375 | 1035 | include_site_packages=include_site_packages, | ||
376 | 1036 | allowed_eggs_from_site_packages= | ||
377 | 1037 | allowed_eggs_from_site_packages) | ||
378 | 874 | return installer.build(spec, build_ext) | 1038 | return installer.build(spec, build_ext) |
379 | 875 | 1039 | ||
380 | 876 | 1040 | ||
381 | @@ -965,9 +1129,12 @@ | |||
382 | 965 | undo.reverse() | 1129 | undo.reverse() |
383 | 966 | [f() for f in undo] | 1130 | [f() for f in undo] |
384 | 967 | 1131 | ||
388 | 968 | 1132 | def working_set(specs, executable, path, include_site_packages=None, | |
389 | 969 | def working_set(specs, executable, path): | 1133 | allowed_eggs_from_site_packages=None): |
390 | 970 | return install(specs, None, executable=executable, path=path) | 1134 | return install( |
391 | 1135 | specs, None, executable=executable, path=path, | ||
392 | 1136 | include_site_packages=include_site_packages, | ||
393 | 1137 | allowed_eggs_from_site_packages=allowed_eggs_from_site_packages) | ||
394 | 971 | 1138 | ||
395 | 972 | ############################################################################ | 1139 | ############################################################################ |
396 | 973 | # Script generation functions | 1140 | # Script generation functions |
397 | @@ -1002,7 +1169,7 @@ | |||
398 | 1002 | def sitepackage_safe_scripts( | 1169 | def sitepackage_safe_scripts( |
399 | 1003 | dest, working_set, executable, site_py_dest, | 1170 | dest, working_set, executable, site_py_dest, |
400 | 1004 | reqs=(), scripts=None, interpreter=None, extra_paths=(), | 1171 | reqs=(), scripts=None, interpreter=None, extra_paths=(), |
402 | 1005 | initialization='', add_site_packages=False, exec_sitecustomize=False, | 1172 | initialization='', include_site_packages=False, exec_sitecustomize=False, |
403 | 1006 | relative_paths=False, script_arguments='', script_initialization=''): | 1173 | relative_paths=False, script_arguments='', script_initialization=''): |
404 | 1007 | """Generate scripts and/or an interpreter from a system Python. | 1174 | """Generate scripts and/or an interpreter from a system Python. |
405 | 1008 | 1175 | ||
406 | @@ -1016,7 +1183,7 @@ | |||
407 | 1016 | site_py_dest, executable, initialization, exec_sitecustomize)) | 1183 | site_py_dest, executable, initialization, exec_sitecustomize)) |
408 | 1017 | generated.append(_generate_site( | 1184 | generated.append(_generate_site( |
409 | 1018 | site_py_dest, working_set, executable, extra_paths, | 1185 | site_py_dest, working_set, executable, extra_paths, |
411 | 1019 | add_site_packages, relative_paths)) | 1186 | include_site_packages, relative_paths)) |
412 | 1020 | script_initialization = ( | 1187 | script_initialization = ( |
413 | 1021 | '\nimport site # imports custom buildout-generated site.py\n%s' % ( | 1188 | '\nimport site # imports custom buildout-generated site.py\n%s' % ( |
414 | 1022 | script_initialization,)) | 1189 | script_initialization,)) |
415 | @@ -1301,54 +1468,6 @@ | |||
416 | 1301 | 1468 | ||
417 | 1302 | # These are used only by the newer ``sitepackage_safe_scripts`` function. | 1469 | # These are used only by the newer ``sitepackage_safe_scripts`` function. |
418 | 1303 | 1470 | ||
419 | 1304 | def _get_system_paths(executable): | ||
420 | 1305 | """Return lists of standard lib and site paths for executable. | ||
421 | 1306 | """ | ||
422 | 1307 | # We want to get a list of the site packages, which is not easy. | ||
423 | 1308 | # The canonical way to do this is to use | ||
424 | 1309 | # distutils.sysconfig.get_python_lib(), but that only returns a | ||
425 | 1310 | # single path, which does not reflect reality for many system | ||
426 | 1311 | # Pythons, which have multiple additions. Instead, we start Python | ||
427 | 1312 | # with -S, which does not import site.py and set up the extra paths | ||
428 | 1313 | # like site-packages or (Ubuntu/Debian) dist-packages and | ||
429 | 1314 | # python-support. We then compare that sys.path with the normal one | ||
430 | 1315 | # (minus user packages if this is Python 2.6, because we don't | ||
431 | 1316 | # support those (yet?). The set of the normal one minus the set of | ||
432 | 1317 | # the ones in ``python -S`` is the set of packages that are | ||
433 | 1318 | # effectively site-packages. | ||
434 | 1319 | # | ||
435 | 1320 | # The given executable might not be the current executable, so it is | ||
436 | 1321 | # appropriate to do another subprocess to figure out what the | ||
437 | 1322 | # additional site-package paths are. Moreover, even if this | ||
438 | 1323 | # executable *is* the current executable, this code might be run in | ||
439 | 1324 | # the context of code that has manipulated the sys.path--for | ||
440 | 1325 | # instance, to add local zc.buildout or setuptools eggs. | ||
441 | 1326 | def get_sys_path(*args, **kwargs): | ||
442 | 1327 | cmd = [executable] | ||
443 | 1328 | cmd.extend(args) | ||
444 | 1329 | cmd.extend([ | ||
445 | 1330 | "-c", "import sys, os;" | ||
446 | 1331 | "print repr([os.path.normpath(p) for p in sys.path if p])"]) | ||
447 | 1332 | # Windows needs some (as yet to be determined) part of the real env. | ||
448 | 1333 | env = os.environ.copy() | ||
449 | 1334 | env.update(kwargs) | ||
450 | 1335 | _proc = subprocess.Popen( | ||
451 | 1336 | cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) | ||
452 | 1337 | stdout, stderr = _proc.communicate(); | ||
453 | 1338 | if _proc.returncode: | ||
454 | 1339 | raise RuntimeError( | ||
455 | 1340 | 'error trying to get system packages:\n%s' % (stderr,)) | ||
456 | 1341 | res = eval(stdout.strip()) | ||
457 | 1342 | try: | ||
458 | 1343 | res.remove('.') | ||
459 | 1344 | except ValueError: | ||
460 | 1345 | pass | ||
461 | 1346 | return res | ||
462 | 1347 | stdlib = get_sys_path('-S') # stdlib only | ||
463 | 1348 | no_user_paths = get_sys_path(PYTHONNOUSERSITE='x') | ||
464 | 1349 | site_paths = [p for p in no_user_paths if p not in stdlib] | ||
465 | 1350 | return (stdlib, site_paths) | ||
466 | 1351 | |||
467 | 1352 | def _get_module_file(executable, name): | 1471 | def _get_module_file(executable, name): |
468 | 1353 | """Return a module's file path. | 1472 | """Return a module's file path. |
469 | 1354 | 1473 | ||
470 | @@ -1401,10 +1520,10 @@ | |||
471 | 1401 | return sitecustomize_path | 1520 | return sitecustomize_path |
472 | 1402 | 1521 | ||
473 | 1403 | def _generate_site(dest, working_set, executable, extra_paths=(), | 1522 | def _generate_site(dest, working_set, executable, extra_paths=(), |
475 | 1404 | add_site_packages=False, relative_paths=False): | 1523 | include_site_packages=False, relative_paths=False): |
476 | 1405 | """Write a site.py file with eggs from working_set. | 1524 | """Write a site.py file with eggs from working_set. |
477 | 1406 | 1525 | ||
479 | 1407 | extra_paths will be added to the path. If add_site_packages is True, | 1526 | extra_paths will be added to the path. If include_site_packages is True, |
480 | 1408 | paths from the underlying Python will be added. | 1527 | paths from the underlying Python will be added. |
481 | 1409 | """ | 1528 | """ |
482 | 1410 | path = _get_path(working_set, extra_paths) | 1529 | path = _get_path(working_set, extra_paths) |
483 | @@ -1416,7 +1535,7 @@ | |||
484 | 1416 | [(line and ' %s' % (line,) or line) | 1535 | [(line and ' %s' % (line,) or line) |
485 | 1417 | for line in preamble.split('\n')]) | 1536 | for line in preamble.split('\n')]) |
486 | 1418 | original_path_setup = '' | 1537 | original_path_setup = '' |
488 | 1419 | if add_site_packages: | 1538 | if include_site_packages: |
489 | 1420 | stdlib, site_paths = _get_system_paths(executable) | 1539 | stdlib, site_paths = _get_system_paths(executable) |
490 | 1421 | original_path_setup = original_path_snippet % ( | 1540 | original_path_setup = original_path_snippet % ( |
491 | 1422 | _format_paths((repr(p) for p in site_paths), 2),) | 1541 | _format_paths((repr(p) for p in site_paths), 2),) |
492 | @@ -1431,7 +1550,7 @@ | |||
493 | 1431 | relative_paths) | 1550 | relative_paths) |
494 | 1432 | else: | 1551 | else: |
495 | 1433 | location = repr(distribution.location) | 1552 | location = repr(distribution.location) |
497 | 1434 | preamble += namespace_add_site_packages_setup % (location,) | 1553 | preamble += namespace_include_site_packages_setup % (location,) |
498 | 1435 | original_path_setup = ( | 1554 | original_path_setup = ( |
499 | 1436 | addsitedir_namespace_originalpackages_snippet + | 1555 | addsitedir_namespace_originalpackages_snippet + |
500 | 1437 | original_path_setup) | 1556 | original_path_setup) |
501 | @@ -1460,7 +1579,7 @@ | |||
502 | 1460 | raise RuntimeError('Buildout did not successfully rewrite site.py') | 1579 | raise RuntimeError('Buildout did not successfully rewrite site.py') |
503 | 1461 | return site_path | 1580 | return site_path |
504 | 1462 | 1581 | ||
506 | 1463 | namespace_add_site_packages_setup = ''' | 1582 | namespace_include_site_packages_setup = ''' |
507 | 1464 | setuptools_path = %s | 1583 | setuptools_path = %s |
508 | 1465 | sys.path.append(setuptools_path) | 1584 | sys.path.append(setuptools_path) |
509 | 1466 | known_paths.add(os.path.normcase(setuptools_path)) | 1585 | known_paths.add(os.path.normcase(setuptools_path)) |
510 | 1467 | 1586 | ||
511 | === modified file 'src/zc/buildout/easy_install.txt' | |||
512 | --- src/zc/buildout/easy_install.txt 2010-02-24 23:22:13 +0000 | |||
513 | +++ src/zc/buildout/easy_install.txt 2010-02-24 23:22:13 +0000 | |||
514 | @@ -89,6 +89,14 @@ | |||
515 | 89 | for using dependency_links in preference to other | 89 | for using dependency_links in preference to other |
516 | 90 | locations. Defaults to true. | 90 | locations. Defaults to true. |
517 | 91 | 91 | ||
518 | 92 | include_site_packages | ||
519 | 93 | A flag indicating whether Python's non-standard-library packages should | ||
520 | 94 | be available for finding dependencies. Defaults to true. | ||
521 | 95 | |||
522 | 96 | Paths outside of Python's standard library--or more precisely, those that | ||
523 | 97 | are not included when Python is started with the -S argument--are loosely | ||
524 | 98 | referred to as "site-packages" here. | ||
525 | 99 | |||
526 | 92 | relative_paths | 100 | relative_paths |
527 | 93 | Adjust egg paths so they are relative to the script path. This | 101 | Adjust egg paths so they are relative to the script path. This |
528 | 94 | allows scripts to work when scripts and eggs are moved, as long as | 102 | allows scripts to work when scripts and eggs are moved, as long as |
529 | @@ -399,6 +407,68 @@ | |||
530 | 399 | >>> [d.version for d in ws] | 407 | >>> [d.version for d in ws] |
531 | 400 | ['0.3', '1.1'] | 408 | ['0.3', '1.1'] |
532 | 401 | 409 | ||
533 | 410 | Dependencies in Site Packages | ||
534 | 411 | ----------------------------- | ||
535 | 412 | |||
536 | 413 | Paths outside of Python's standard library--or more precisely, those that are | ||
537 | 414 | not included when Python is started with the -S argument--are loosely referred | ||
538 | 415 | to as "site-packages" here. These site-packages are searched by default for | ||
539 | 416 | distributions. This can be disabled, so that, for instance, a system Python | ||
540 | 417 | can be used with buildout, cleaned of any packages installed by a user or | ||
541 | 418 | system package manager. | ||
542 | 419 | |||
543 | 420 | The default behavior can be controlled and introspected using | ||
544 | 421 | zc.buildout.easy_install.include_site_packages. | ||
545 | 422 | |||
546 | 423 | >>> zc.buildout.easy_install.include_site_packages() | ||
547 | 424 | True | ||
548 | 425 | |||
549 | 426 | Here's an example of using a Python executable that includes our dependencies. | ||
550 | 427 | |||
551 | 428 | Our "py_path" will have the "demoneeded," and "demo" packages available. | ||
552 | 429 | We'll simply be asking for "demoneeded" here, but without any external | ||
553 | 430 | index or links. | ||
554 | 431 | |||
555 | 432 | >>> from zc.buildout.tests import create_sample_sys_install | ||
556 | 433 | >>> py_path, site_packages_path = make_py() | ||
557 | 434 | >>> create_sample_sys_install(site_packages_path) | ||
558 | 435 | |||
559 | 436 | >>> example_dest = tmpdir('site-packages-example-install') | ||
560 | 437 | >>> workingset = zc.buildout.easy_install.install( | ||
561 | 438 | ... ['demoneeded'], example_dest, links=[], executable=py_path, | ||
562 | 439 | ... index=None) | ||
563 | 440 | >>> [dist.project_name for dist in workingset] | ||
564 | 441 | ['demoneeded'] | ||
565 | 442 | |||
566 | 443 | That worked fine. Let's try again with site packages not allowed. We'll | ||
567 | 444 | change the policy by changing the default. Notice that the function for | ||
568 | 445 | changing the default value returns the previous value. | ||
569 | 446 | |||
570 | 447 | >>> zc.buildout.easy_install.include_site_packages(False) | ||
571 | 448 | True | ||
572 | 449 | |||
573 | 450 | >>> zc.buildout.easy_install.include_site_packages() | ||
574 | 451 | False | ||
575 | 452 | |||
576 | 453 | >>> zc.buildout.easy_install.clear_index_cache() | ||
577 | 454 | >>> rmdir(example_dest) | ||
578 | 455 | >>> example_dest = tmpdir('site-packages-example-install') | ||
579 | 456 | >>> workingset = zc.buildout.easy_install.install( | ||
580 | 457 | ... ['demoneeded'], example_dest, links=[], executable=py_path, | ||
581 | 458 | ... index=None) | ||
582 | 459 | Traceback (most recent call last): | ||
583 | 460 | ... | ||
584 | 461 | MissingDistribution: Couldn't find a distribution for 'demoneeded'. | ||
585 | 462 | >>> zc.buildout.easy_install.clear_index_cache() | ||
586 | 463 | |||
587 | 464 | Now we'll reset the default. | ||
588 | 465 | |||
589 | 466 | >>> zc.buildout.easy_install.include_site_packages(True) | ||
590 | 467 | False | ||
591 | 468 | |||
592 | 469 | >>> zc.buildout.easy_install.include_site_packages() | ||
593 | 470 | True | ||
594 | 471 | |||
595 | 402 | Dependency links | 472 | Dependency links |
596 | 403 | ---------------- | 473 | ---------------- |
597 | 404 | 474 | ||
598 | @@ -1197,7 +1267,7 @@ | |||
599 | 1197 | >>> reset_interpreter() | 1267 | >>> reset_interpreter() |
600 | 1198 | >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( | 1268 | >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( |
601 | 1199 | ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, | 1269 | ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, |
603 | 1200 | ... interpreter='py', add_site_packages=True) | 1270 | ... interpreter='py', include_site_packages=True) |
604 | 1201 | >>> sys.stdout.write('#\n'); cat(site_path) | 1271 | >>> sys.stdout.write('#\n'); cat(site_path) |
605 | 1202 | ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE | 1272 | ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE |
606 | 1203 | #... | 1273 | #... |
607 | @@ -1266,7 +1336,7 @@ | |||
608 | 1266 | ... links=[link_server, namespace_eggs], index=link_server+'index/') | 1336 | ... links=[link_server, namespace_eggs], index=link_server+'index/') |
609 | 1267 | >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( | 1337 | >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( |
610 | 1268 | ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, | 1338 | ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, |
612 | 1269 | ... interpreter='py', add_site_packages=True) | 1339 | ... interpreter='py', include_site_packages=True) |
613 | 1270 | >>> sys.stdout.write('#\n'); cat(site_path) | 1340 | >>> sys.stdout.write('#\n'); cat(site_path) |
614 | 1271 | ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE | 1341 | ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE |
615 | 1272 | #... | 1342 | #... |
616 | @@ -1324,7 +1394,7 @@ | |||
617 | 1324 | >>> reset_interpreter() | 1394 | >>> reset_interpreter() |
618 | 1325 | >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( | 1395 | >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( |
619 | 1326 | ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, | 1396 | ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, |
621 | 1327 | ... interpreter='py', add_site_packages=True, | 1397 | ... interpreter='py', include_site_packages=True, |
622 | 1328 | ... relative_paths=interpreter_dir) | 1398 | ... relative_paths=interpreter_dir) |
623 | 1329 | >>> sys.stdout.write('#\n'); cat(site_path) | 1399 | >>> sys.stdout.write('#\n'); cat(site_path) |
624 | 1330 | ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE | 1400 | ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE |
625 | 1331 | 1401 | ||
626 | === modified file 'src/zc/buildout/testing.py' | |||
627 | --- src/zc/buildout/testing.py 2010-02-24 23:22:13 +0000 | |||
628 | +++ src/zc/buildout/testing.py 2010-02-24 23:22:13 +0000 | |||
629 | @@ -222,11 +222,37 @@ | |||
630 | 222 | time.sleep(0.01) | 222 | time.sleep(0.01) |
631 | 223 | raise ValueError('Timed out waiting for: '+label) | 223 | raise ValueError('Timed out waiting for: '+label) |
632 | 224 | 224 | ||
633 | 225 | def get_installer_values(): | ||
634 | 226 | """Get the current values for the easy_install module. | ||
635 | 227 | |||
636 | 228 | This is necessary because instantiating a Buildout will force the | ||
637 | 229 | Buildout's values on the installer. | ||
638 | 230 | |||
639 | 231 | Returns a dict of names-values suitable for set_installer_values.""" | ||
640 | 232 | names = ('default_versions', 'download_cache', 'install_from_cache', | ||
641 | 233 | 'prefer_final', 'include_site_packages', | ||
642 | 234 | 'allowed_eggs_from_site_packages', 'use_dependency_links', | ||
643 | 235 | 'allow_picked_versions', 'always_unzip' | ||
644 | 236 | ) | ||
645 | 237 | values = {} | ||
646 | 238 | for name in names: | ||
647 | 239 | values[name] = getattr(zc.buildout.easy_install, name)() | ||
648 | 240 | return values | ||
649 | 241 | |||
650 | 242 | def set_installer_values(values): | ||
651 | 243 | """Set the given values on the installer.""" | ||
652 | 244 | for name, value in values.items(): | ||
653 | 245 | getattr(zc.buildout.easy_install, name)(value) | ||
654 | 246 | |||
655 | 225 | def make_buildout(): | 247 | def make_buildout(): |
657 | 226 | # Create a basic buildout.cfg to avoid a warning from buildout: | 248 | """Make a buildout that uses this version of zc.buildout.""" |
658 | 249 | # Create a basic buildout.cfg to avoid a warning from buildout. | ||
659 | 227 | open('buildout.cfg', 'w').write( | 250 | open('buildout.cfg', 'w').write( |
660 | 228 | "[buildout]\nparts =\n" | 251 | "[buildout]\nparts =\n" |
661 | 229 | ) | 252 | ) |
662 | 253 | # Get state of installer defaults so we can reinstate them (instantiating | ||
663 | 254 | # a Buildout will force the Buildout's defaults on the installer). | ||
664 | 255 | installer_values = get_installer_values() | ||
665 | 230 | # Use the buildout bootstrap command to create a buildout | 256 | # Use the buildout bootstrap command to create a buildout |
666 | 231 | zc.buildout.buildout.Buildout( | 257 | zc.buildout.buildout.Buildout( |
667 | 232 | 'buildout.cfg', | 258 | 'buildout.cfg', |
668 | @@ -234,20 +260,23 @@ | |||
669 | 234 | # trick bootstrap into putting the buildout develop egg | 260 | # trick bootstrap into putting the buildout develop egg |
670 | 235 | # in the eggs dir. | 261 | # in the eggs dir. |
671 | 236 | ('buildout', 'develop-eggs-directory', 'eggs'), | 262 | ('buildout', 'develop-eggs-directory', 'eggs'), |
673 | 237 | ] | 263 | ], |
674 | 264 | user_defaults=False, | ||
675 | 238 | ).bootstrap([]) | 265 | ).bootstrap([]) |
676 | 239 | # Create the develop-eggs dir, which didn't get created the usual | 266 | # Create the develop-eggs dir, which didn't get created the usual |
677 | 240 | # way due to the trick above: | 267 | # way due to the trick above: |
678 | 241 | os.mkdir('develop-eggs') | 268 | os.mkdir('develop-eggs') |
679 | 269 | # Reinstate the default values of the installer. | ||
680 | 270 | set_installer_values(installer_values) | ||
681 | 242 | 271 | ||
682 | 243 | def buildoutSetUp(test): | 272 | def buildoutSetUp(test): |
683 | 244 | 273 | ||
684 | 245 | test.globs['__tear_downs'] = __tear_downs = [] | 274 | test.globs['__tear_downs'] = __tear_downs = [] |
685 | 246 | test.globs['register_teardown'] = register_teardown = __tear_downs.append | 275 | test.globs['register_teardown'] = register_teardown = __tear_downs.append |
686 | 247 | 276 | ||
688 | 248 | prefer_final = zc.buildout.easy_install.prefer_final() | 277 | installer_values = get_installer_values() |
689 | 249 | register_teardown( | 278 | register_teardown( |
691 | 250 | lambda: zc.buildout.easy_install.prefer_final(prefer_final) | 279 | lambda: set_installer_values(installer_values) |
692 | 251 | ) | 280 | ) |
693 | 252 | 281 | ||
694 | 253 | here = os.getcwd() | 282 | here = os.getcwd() |
695 | @@ -367,8 +396,6 @@ | |||
696 | 367 | make_py = make_py | 396 | make_py = make_py |
697 | 368 | )) | 397 | )) |
698 | 369 | 398 | ||
699 | 370 | zc.buildout.easy_install.prefer_final(prefer_final) | ||
700 | 371 | |||
701 | 372 | def buildoutTearDown(test): | 399 | def buildoutTearDown(test): |
702 | 373 | for f in test.globs['__tear_downs']: | 400 | for f in test.globs['__tear_downs']: |
703 | 374 | f() | 401 | f() |
704 | 375 | 402 | ||
705 | === modified file 'src/zc/buildout/tests.py' | |||
706 | --- src/zc/buildout/tests.py 2010-02-24 23:22:13 +0000 | |||
707 | +++ src/zc/buildout/tests.py 2010-02-24 23:22:13 +0000 | |||
708 | @@ -385,6 +385,64 @@ | |||
709 | 385 | Error: Couldn't find a distribution for 'demoneeded'. | 385 | Error: Couldn't find a distribution for 'demoneeded'. |
710 | 386 | """ | 386 | """ |
711 | 387 | 387 | ||
712 | 388 | def show_eggs_from_site_packages(): | ||
713 | 389 | """ | ||
714 | 390 | Sometimes you want to know what eggs are coming from site-packages. This | ||
715 | 391 | might be for a diagnostic, or so that you can get a starting value for the | ||
716 | 392 | allowed-eggs-from-site-packages option. The -v flag will also include this | ||
717 | 393 | information. | ||
718 | 394 | |||
719 | 395 | Our "py_path" has the "demoneeded," "demo" | ||
720 | 396 | packages available. We'll ask for "bigdemo," which will get both of them. | ||
721 | 397 | |||
722 | 398 | Here's our set up. | ||
723 | 399 | |||
724 | 400 | >>> py_path, site_packages_path = make_py() | ||
725 | 401 | >>> create_sample_sys_install(site_packages_path) | ||
726 | 402 | |||
727 | 403 | >>> write('buildout.cfg', | ||
728 | 404 | ... ''' | ||
729 | 405 | ... [buildout] | ||
730 | 406 | ... parts = eggs | ||
731 | 407 | ... prefer-final = true | ||
732 | 408 | ... find-links = %(link_server)s | ||
733 | 409 | ... | ||
734 | 410 | ... [primed_python] | ||
735 | 411 | ... executable = %(py_path)s | ||
736 | 412 | ... | ||
737 | 413 | ... [eggs] | ||
738 | 414 | ... recipe = zc.recipe.egg:eggs | ||
739 | 415 | ... python = primed_python | ||
740 | 416 | ... eggs = bigdemo | ||
741 | 417 | ... ''' % globals()) | ||
742 | 418 | |||
743 | 419 | Now here is the output. The lines that begin with "Egg from site-packages:" | ||
744 | 420 | indicate the eggs from site-packages that have been selected. You'll see | ||
745 | 421 | we have two: demo 0.3 and demoneeded 1.1. | ||
746 | 422 | |||
747 | 423 | >>> print system(py_path+" "+buildout+" -v") | ||
748 | 424 | Installing 'zc.buildout', 'setuptools'. | ||
749 | 425 | We have a develop egg: zc.buildout V | ||
750 | 426 | We have the best distribution that satisfies 'setuptools'. | ||
751 | 427 | Picked: setuptools = V | ||
752 | 428 | Installing 'zc.recipe.egg'. | ||
753 | 429 | We have a develop egg: zc.recipe.egg V | ||
754 | 430 | Installing eggs. | ||
755 | 431 | Installing 'bigdemo'. | ||
756 | 432 | We have no distributions for bigdemo that satisfies 'bigdemo'. | ||
757 | 433 | Getting distribution for 'bigdemo'. | ||
758 | 434 | Got bigdemo 0.1. | ||
759 | 435 | Picked: bigdemo = 0.1 | ||
760 | 436 | Getting required 'demo' | ||
761 | 437 | required by bigdemo 0.1. | ||
762 | 438 | We have a develop egg: demo V | ||
763 | 439 | Egg from site-packages: demo 0.3 | ||
764 | 440 | Getting required 'demoneeded' | ||
765 | 441 | required by demo 0.3. | ||
766 | 442 | We have a develop egg: demoneeded V | ||
767 | 443 | Egg from site-packages: demoneeded 1.1 | ||
768 | 444 | <BLANKLINE> | ||
769 | 445 | """ | ||
770 | 388 | 446 | ||
771 | 389 | def test_comparing_saved_options_with_funny_characters(): | 447 | def test_comparing_saved_options_with_funny_characters(): |
772 | 390 | """ | 448 | """ |
773 | @@ -1854,7 +1912,7 @@ | |||
774 | 1854 | ... recipe = z3c.recipe.scripts | 1912 | ... recipe = z3c.recipe.scripts |
775 | 1855 | ... python = primed_python | 1913 | ... python = primed_python |
776 | 1856 | ... interpreter = py | 1914 | ... interpreter = py |
778 | 1857 | ... add-site-packages = true | 1915 | ... include-site-packages = true |
779 | 1858 | ... eggs = tellmy.version == 1.0 | 1916 | ... eggs = tellmy.version == 1.0 |
780 | 1859 | ... tellmy.fortune == 1.0 | 1917 | ... tellmy.fortune == 1.0 |
781 | 1860 | ... demo | 1918 | ... demo |
782 | @@ -1879,7 +1937,7 @@ | |||
783 | 1879 | Generated interpreter '/sample-buildout/bin/py'. | 1937 | Generated interpreter '/sample-buildout/bin/py'. |
784 | 1880 | <BLANKLINE> | 1938 | <BLANKLINE> |
785 | 1881 | 1939 | ||
787 | 1882 | Finally, we are ready for the actual test. Prior to the bug fix that | 1940 | Finally, we are ready to see if it worked. Prior to the bug fix that |
788 | 1883 | this tests, the results of both calls below was the following:: | 1941 | this tests, the results of both calls below was the following:: |
789 | 1884 | 1942 | ||
790 | 1885 | 1.1 | 1943 | 1.1 |
791 | @@ -2005,6 +2063,197 @@ | |||
792 | 2005 | 2063 | ||
793 | 2006 | """ | 2064 | """ |
794 | 2007 | 2065 | ||
795 | 2066 | def isolated_include_site_packages(): | ||
796 | 2067 | """ | ||
797 | 2068 | |||
798 | 2069 | This is an isolated test of the include_site_packages functionality, passing | ||
799 | 2070 | the argument directly to install, overriding a default. | ||
800 | 2071 | |||
801 | 2072 | Our "py_path" has the "demoneeded" and "demo" packages available. We'll | ||
802 | 2073 | simply be asking for "demoneeded" here. | ||
803 | 2074 | |||
804 | 2075 | >>> py_path, site_packages_path = make_py() | ||
805 | 2076 | >>> create_sample_sys_install(site_packages_path) | ||
806 | 2077 | >>> zc.buildout.easy_install.include_site_packages(False) | ||
807 | 2078 | True | ||
808 | 2079 | |||
809 | 2080 | >>> example_dest = tmpdir('site-packages-example-install') | ||
810 | 2081 | >>> workingset = zc.buildout.easy_install.install( | ||
811 | 2082 | ... ['demoneeded'], example_dest, links=[], executable=py_path, | ||
812 | 2083 | ... index=None, include_site_packages=True) | ||
813 | 2084 | >>> [dist.project_name for dist in workingset] | ||
814 | 2085 | ['demoneeded'] | ||
815 | 2086 | |||
816 | 2087 | That worked fine. Let's try again with site packages not allowed (and | ||
817 | 2088 | reversing the default). | ||
818 | 2089 | |||
819 | 2090 | >>> zc.buildout.easy_install.include_site_packages(True) | ||
820 | 2091 | False | ||
821 | 2092 | |||
822 | 2093 | >>> zc.buildout.easy_install.clear_index_cache() | ||
823 | 2094 | >>> rmdir(example_dest) | ||
824 | 2095 | >>> example_dest = tmpdir('site-packages-example-install') | ||
825 | 2096 | >>> workingset = zc.buildout.easy_install.install( | ||
826 | 2097 | ... ['demoneeded'], example_dest, links=[], executable=py_path, | ||
827 | 2098 | ... index=None, include_site_packages=False) | ||
828 | 2099 | Traceback (most recent call last): | ||
829 | 2100 | ... | ||
830 | 2101 | MissingDistribution: Couldn't find a distribution for 'demoneeded'. | ||
831 | 2102 | |||
832 | 2103 | That's a failure, as expected. | ||
833 | 2104 | |||
834 | 2105 | Now we explore an important edge case. | ||
835 | 2106 | |||
836 | 2107 | Some system Pythons include setuptools (and other Python packages) in their | ||
837 | 2108 | site-packages (or equivalent) using a .egg-info directory. The pkg_resources | ||
838 | 2109 | module (from setuptools) considers a package installed using .egg-info to be a | ||
839 | 2110 | develop egg. | ||
840 | 2111 | |||
841 | 2112 | zc.buildout.buildout.Buildout.bootstrap will make setuptools and zc.buildout | ||
842 | 2113 | available to the buildout via the eggs directory, for normal eggs; or the | ||
843 | 2114 | develop-eggs directory, for develop-eggs. | ||
844 | 2115 | |||
845 | 2116 | If setuptools or zc.buildout is found in site-packages and considered by | ||
846 | 2117 | pkg_resources to be a develop egg, then the bootstrap code will use a .egg-link | ||
847 | 2118 | in the local develop-eggs, pointing to site-packages, in its entirety. Because | ||
848 | 2119 | develop-eggs must always be available for searching for distributions, this | ||
849 | 2120 | indirectly brings site-packages back into the search path for distributions. | ||
850 | 2121 | |||
851 | 2122 | Because of this, we have to take special care that we still exclude | ||
852 | 2123 | site-packages even in this case. See the comments about site packages in the | ||
853 | 2124 | Installer._satisfied and Installer._obtain methods for the implementation | ||
854 | 2125 | (as of this writing). | ||
855 | 2126 | |||
856 | 2127 | In this demonstration, we insert a link to the "demoneeded" distribution | ||
857 | 2128 | in our develop-eggs, which would bring the package back in, except for | ||
858 | 2129 | the special care we have taken to exclude it. | ||
859 | 2130 | |||
860 | 2131 | >>> zc.buildout.easy_install.clear_index_cache() | ||
861 | 2132 | >>> rmdir(example_dest) | ||
862 | 2133 | >>> example_dest = tmpdir('site-packages-example-install') | ||
863 | 2134 | >>> mkdir(example_dest, 'develop-eggs') | ||
864 | 2135 | >>> write(example_dest, 'develop-eggs', 'demoneeded.egg-link', | ||
865 | 2136 | ... site_packages_path) | ||
866 | 2137 | >>> workingset = zc.buildout.easy_install.install( | ||
867 | 2138 | ... ['demoneeded'], example_dest, links=[], | ||
868 | 2139 | ... path=[join(example_dest, 'develop-eggs')], | ||
869 | 2140 | ... executable=py_path, | ||
870 | 2141 | ... index=None, include_site_packages=False) | ||
871 | 2142 | Traceback (most recent call last): | ||
872 | 2143 | ... | ||
873 | 2144 | MissingDistribution: Couldn't find a distribution for 'demoneeded'. | ||
874 | 2145 | |||
875 | 2146 | The MissingDistribution error shows that buildout correctly excluded the | ||
876 | 2147 | "site-packages" source even though it was indirectly included in the path | ||
877 | 2148 | via a .egg-link file. | ||
878 | 2149 | |||
879 | 2150 | """ | ||
880 | 2151 | |||
881 | 2152 | def allowed_eggs_from_site_packages(): | ||
882 | 2153 | """ | ||
883 | 2154 | Sometimes you need or want to control what eggs from site-packages are used. | ||
884 | 2155 | The allowed-eggs-from-site-packages option allows you to specify a whitelist of | ||
885 | 2156 | project names that may be included from site-packages. You can use globs to | ||
886 | 2157 | specify the value. It defaults to a single value of '*', indicating that any | ||
887 | 2158 | package may come from site-packages. | ||
888 | 2159 | |||
889 | 2160 | This option interacts with include-site-packages in the following ways. | ||
890 | 2161 | |||
891 | 2162 | If include-site-packages is true, then allowed-eggs-from-site-packages filters | ||
892 | 2163 | what eggs from site-packages may be chosen. If allowed-eggs-from-site-packages | ||
893 | 2164 | is an empty list, then no eggs from site-packages are chosen, but site-packages | ||
894 | 2165 | will still be included at the end of path lists. | ||
895 | 2166 | |||
896 | 2167 | If include-site-packages is false, allowed-eggs-from-site-packages is | ||
897 | 2168 | irrelevant. | ||
898 | 2169 | |||
899 | 2170 | This test shows the interaction with the zc.buildout.easy_install API. Another | ||
900 | 2171 | test below (allow_site_package_eggs_option) shows using it with a buildout.cfg. | ||
901 | 2172 | |||
902 | 2173 | Our "py_path" has the "demoneeded" and "demo" packages available. We'll | ||
903 | 2174 | simply be asking for "demoneeded" here. | ||
904 | 2175 | |||
905 | 2176 | >>> py_path, site_packages_path = make_py() | ||
906 | 2177 | >>> create_sample_sys_install(site_packages_path) | ||
907 | 2178 | |||
908 | 2179 | >>> example_dest = tmpdir('site-packages-example-install') | ||
909 | 2180 | >>> workingset = zc.buildout.easy_install.install( | ||
910 | 2181 | ... ['demoneeded'], example_dest, links=[], executable=py_path, | ||
911 | 2182 | ... index=None, | ||
912 | 2183 | ... allowed_eggs_from_site_packages=['demoneeded', 'other']) | ||
913 | 2184 | >>> [dist.project_name for dist in workingset] | ||
914 | 2185 | ['demoneeded'] | ||
915 | 2186 | |||
916 | 2187 | That worked fine. It would work fine for a glob too. | ||
917 | 2188 | |||
918 | 2189 | >>> zc.buildout.easy_install.clear_index_cache() | ||
919 | 2190 | >>> rmdir(example_dest) | ||
920 | 2191 | >>> example_dest = tmpdir('site-packages-example-install') | ||
921 | 2192 | >>> workingset = zc.buildout.easy_install.install( | ||
922 | 2193 | ... ['demoneeded'], example_dest, links=[], executable=py_path, | ||
923 | 2194 | ... index=None, | ||
924 | 2195 | ... allowed_eggs_from_site_packages=['?emon*', 'other']) | ||
925 | 2196 | >>> [dist.project_name for dist in workingset] | ||
926 | 2197 | ['demoneeded'] | ||
927 | 2198 | |||
928 | 2199 | But now let's try again with 'demoneeded' not allowed. | ||
929 | 2200 | |||
930 | 2201 | >>> zc.buildout.easy_install.clear_index_cache() | ||
931 | 2202 | >>> rmdir(example_dest) | ||
932 | 2203 | >>> example_dest = tmpdir('site-packages-example-install') | ||
933 | 2204 | >>> workingset = zc.buildout.easy_install.install( | ||
934 | 2205 | ... ['demoneeded'], example_dest, links=[], executable=py_path, | ||
935 | 2206 | ... index=None, | ||
936 | 2207 | ... allowed_eggs_from_site_packages=['demo']) | ||
937 | 2208 | Traceback (most recent call last): | ||
938 | 2209 | ... | ||
939 | 2210 | MissingDistribution: Couldn't find a distribution for 'demoneeded'. | ||
940 | 2211 | |||
941 | 2212 | Here's the same, but with an empty list. | ||
942 | 2213 | |||
943 | 2214 | >>> zc.buildout.easy_install.clear_index_cache() | ||
944 | 2215 | >>> rmdir(example_dest) | ||
945 | 2216 | >>> example_dest = tmpdir('site-packages-example-install') | ||
946 | 2217 | >>> workingset = zc.buildout.easy_install.install( | ||
947 | 2218 | ... ['demoneeded'], example_dest, links=[], executable=py_path, | ||
948 | 2219 | ... index=None, | ||
949 | 2220 | ... allowed_eggs_from_site_packages=[]) | ||
950 | 2221 | Traceback (most recent call last): | ||
951 | 2222 | ... | ||
952 | 2223 | MissingDistribution: Couldn't find a distribution for 'demoneeded'. | ||
953 | 2224 | |||
954 | 2225 | Of course, this doesn't stop us from getting a package from elsewhere. Here, | ||
955 | 2226 | we add a link server. | ||
956 | 2227 | |||
957 | 2228 | >>> zc.buildout.easy_install.clear_index_cache() | ||
958 | 2229 | >>> rmdir(example_dest) | ||
959 | 2230 | >>> example_dest = tmpdir('site-packages-example-install') | ||
960 | 2231 | >>> workingset = zc.buildout.easy_install.install( | ||
961 | 2232 | ... ['demoneeded'], example_dest, executable=py_path, | ||
962 | 2233 | ... links=[link_server], index=link_server+'index/', | ||
963 | 2234 | ... allowed_eggs_from_site_packages=['other']) | ||
964 | 2235 | >>> [dist.project_name for dist in workingset] | ||
965 | 2236 | ['demoneeded'] | ||
966 | 2237 | >>> [dist.location for dist in workingset] | ||
967 | 2238 | ['/site-packages-example-install/demoneeded-1.1-py2.6.egg'] | ||
968 | 2239 | |||
969 | 2240 | Finally, here's an example of an interaction: we say that it is OK to | ||
970 | 2241 | allow the "demoneeded" egg to come from site-packages, but we don't | ||
971 | 2242 | include-site-packages. | ||
972 | 2243 | |||
973 | 2244 | >>> zc.buildout.easy_install.clear_index_cache() | ||
974 | 2245 | >>> rmdir(example_dest) | ||
975 | 2246 | >>> example_dest = tmpdir('site-packages-example-install') | ||
976 | 2247 | >>> workingset = zc.buildout.easy_install.install( | ||
977 | 2248 | ... ['demoneeded'], example_dest, links=[], executable=py_path, | ||
978 | 2249 | ... index=None, include_site_packages=False, | ||
979 | 2250 | ... allowed_eggs_from_site_packages=['demoneeded']) | ||
980 | 2251 | Traceback (most recent call last): | ||
981 | 2252 | ... | ||
982 | 2253 | MissingDistribution: Couldn't find a distribution for 'demoneeded'. | ||
983 | 2254 | |||
984 | 2255 | """ | ||
985 | 2256 | |||
986 | 2008 | if sys.version_info > (2, 4): | 2257 | if sys.version_info > (2, 4): |
987 | 2009 | def test_exit_codes(): | 2258 | def test_exit_codes(): |
988 | 2010 | """ | 2259 | """ |
989 | @@ -2932,24 +3181,59 @@ | |||
990 | 2932 | finally: | 3181 | finally: |
991 | 2933 | shutil.rmtree(tmp) | 3182 | shutil.rmtree(tmp) |
992 | 2934 | 3183 | ||
993 | 3184 | def _write_eggrecipedemoneeded(tmp, minor_version, suffix=''): | ||
994 | 3185 | from zc.buildout.testing import write | ||
995 | 3186 | write(tmp, 'README.txt', '') | ||
996 | 3187 | write(tmp, 'eggrecipedemoneeded.py', | ||
997 | 3188 | 'y=%s\ndef f():\n pass' % minor_version) | ||
998 | 3189 | write( | ||
999 | 3190 | tmp, 'setup.py', | ||
1000 | 3191 | "from setuptools import setup\n" | ||
1001 | 3192 | "setup(name='demoneeded', py_modules=['eggrecipedemoneeded']," | ||
1002 | 3193 | " zip_safe=True, version='1.%s%s', author='bob', url='bob', " | ||
1003 | 3194 | "author_email='bob')\n" | ||
1004 | 3195 | % (minor_version, suffix) | ||
1005 | 3196 | ) | ||
1006 | 3197 | |||
1007 | 3198 | def _write_eggrecipedemo(tmp, minor_version, suffix=''): | ||
1008 | 3199 | from zc.buildout.testing import write | ||
1009 | 3200 | write(tmp, 'README.txt', '') | ||
1010 | 3201 | write( | ||
1011 | 3202 | tmp, 'eggrecipedemo.py', | ||
1012 | 3203 | 'import eggrecipedemoneeded\n' | ||
1013 | 3204 | 'x=%s\n' | ||
1014 | 3205 | 'def main(): print x, eggrecipedemoneeded.y\n' | ||
1015 | 3206 | % minor_version) | ||
1016 | 3207 | write( | ||
1017 | 3208 | tmp, 'setup.py', | ||
1018 | 3209 | "from setuptools import setup\n" | ||
1019 | 3210 | "setup(name='demo', py_modules=['eggrecipedemo']," | ||
1020 | 3211 | " install_requires = 'demoneeded'," | ||
1021 | 3212 | " entry_points={'console_scripts': " | ||
1022 | 3213 | "['demo = eggrecipedemo:main']}," | ||
1023 | 3214 | " zip_safe=True, version='0.%s%s')\n" % (minor_version, suffix) | ||
1024 | 3215 | ) | ||
1025 | 3216 | |||
1026 | 3217 | def create_sample_sys_install(site_packages_path): | ||
1027 | 3218 | for creator, minor_version in ( | ||
1028 | 3219 | (_write_eggrecipedemoneeded, 1), | ||
1029 | 3220 | (_write_eggrecipedemo, 3)): | ||
1030 | 3221 | # Write the files and install in site_packages_path. | ||
1031 | 3222 | tmp = tempfile.mkdtemp() | ||
1032 | 3223 | try: | ||
1033 | 3224 | creator(tmp, minor_version) | ||
1034 | 3225 | zc.buildout.testing.sys_install(tmp, site_packages_path) | ||
1035 | 3226 | finally: | ||
1036 | 3227 | shutil.rmtree(tmp) | ||
1037 | 3228 | |||
1038 | 2935 | def create_sample_eggs(test, executable=sys.executable): | 3229 | def create_sample_eggs(test, executable=sys.executable): |
1040 | 2936 | write = test.globs['write'] | 3230 | from zc.buildout.testing import write |
1041 | 2937 | dest = test.globs['sample_eggs'] | 3231 | dest = test.globs['sample_eggs'] |
1042 | 2938 | tmp = tempfile.mkdtemp() | 3232 | tmp = tempfile.mkdtemp() |
1043 | 2939 | try: | 3233 | try: |
1044 | 2940 | write(tmp, 'README.txt', '') | ||
1045 | 2941 | |||
1046 | 2942 | for i in (0, 1, 2): | 3234 | for i in (0, 1, 2): |
1057 | 2943 | write(tmp, 'eggrecipedemoneeded.py', 'y=%s\ndef f():\n pass' % i) | 3235 | suffix = i==2 and 'c1' or '' |
1058 | 2944 | c1 = i==2 and 'c1' or '' | 3236 | _write_eggrecipedemoneeded(tmp, i, suffix) |
1049 | 2945 | write( | ||
1050 | 2946 | tmp, 'setup.py', | ||
1051 | 2947 | "from setuptools import setup\n" | ||
1052 | 2948 | "setup(name='demoneeded', py_modules=['eggrecipedemoneeded']," | ||
1053 | 2949 | " zip_safe=True, version='1.%s%s', author='bob', url='bob', " | ||
1054 | 2950 | "author_email='bob')\n" | ||
1055 | 2951 | % (i, c1) | ||
1056 | 2952 | ) | ||
1059 | 2953 | zc.buildout.testing.sdist(tmp, dest) | 3237 | zc.buildout.testing.sdist(tmp, dest) |
1060 | 2954 | 3238 | ||
1061 | 2955 | write( | 3239 | write( |
1062 | @@ -2963,22 +3247,8 @@ | |||
1063 | 2963 | os.remove(os.path.join(tmp, 'eggrecipedemoneeded.py')) | 3247 | os.remove(os.path.join(tmp, 'eggrecipedemoneeded.py')) |
1064 | 2964 | 3248 | ||
1065 | 2965 | for i in (1, 2, 3, 4): | 3249 | for i in (1, 2, 3, 4): |
1082 | 2966 | write( | 3250 | suffix = i==4 and 'c1' or '' |
1083 | 2967 | tmp, 'eggrecipedemo.py', | 3251 | _write_eggrecipedemo(tmp, i, suffix) |
1068 | 2968 | 'import eggrecipedemoneeded\n' | ||
1069 | 2969 | 'x=%s\n' | ||
1070 | 2970 | 'def main(): print x, eggrecipedemoneeded.y\n' | ||
1071 | 2971 | % i) | ||
1072 | 2972 | c1 = i==4 and 'c1' or '' | ||
1073 | 2973 | write( | ||
1074 | 2974 | tmp, 'setup.py', | ||
1075 | 2975 | "from setuptools import setup\n" | ||
1076 | 2976 | "setup(name='demo', py_modules=['eggrecipedemo']," | ||
1077 | 2977 | " install_requires = 'demoneeded'," | ||
1078 | 2978 | " entry_points={'console_scripts': " | ||
1079 | 2979 | "['demo = eggrecipedemo:main']}," | ||
1080 | 2980 | " zip_safe=True, version='0.%s%s')\n" % (i, c1) | ||
1081 | 2981 | ) | ||
1084 | 2982 | zc.buildout.testing.bdist_egg(tmp, executable, dest) | 3252 | zc.buildout.testing.bdist_egg(tmp, executable, dest) |
1085 | 2983 | 3253 | ||
1086 | 2984 | write(tmp, 'eggrecipebigdemo.py', 'import eggrecipedemo') | 3254 | write(tmp, 'eggrecipebigdemo.py', 'import eggrecipedemo') |
1087 | 2985 | 3255 | ||
1088 | === modified file 'z3c.recipe.scripts_/src/z3c/recipe/scripts/README.txt' | |||
1089 | --- z3c.recipe.scripts_/src/z3c/recipe/scripts/README.txt 2010-02-24 23:22:13 +0000 | |||
1090 | +++ z3c.recipe.scripts_/src/z3c/recipe/scripts/README.txt 2010-02-24 23:22:13 +0000 | |||
1091 | @@ -33,7 +33,7 @@ | |||
1092 | 33 | In addition to these, the recipe offers these new options. They are | 33 | In addition to these, the recipe offers these new options. They are |
1093 | 34 | introduced here, and described more in depth below. | 34 | introduced here, and described more in depth below. |
1094 | 35 | 35 | ||
1096 | 36 | add-site-packages | 36 | include-site-packages |
1097 | 37 | You can choose to have the site-packages of the underlying Python | 37 | You can choose to have the site-packages of the underlying Python |
1098 | 38 | available to your script or interpreter, in addition to the packages | 38 | available to your script or interpreter, in addition to the packages |
1099 | 39 | from your eggs. See the section on this option for motivations and | 39 | from your eggs. See the section on this option for motivations and |
1100 | @@ -47,7 +47,7 @@ | |||
1101 | 47 | exec-sitecustomize | 47 | exec-sitecustomize |
1102 | 48 | Normally the Python's real sitecustomize module is not processed. | 48 | Normally the Python's real sitecustomize module is not processed. |
1103 | 49 | If you want it to be processed, set this value to 'true'. This will | 49 | If you want it to be processed, set this value to 'true'. This will |
1105 | 50 | be honored irrespective of the setting for add-site-packages. | 50 | be honored irrespective of the setting for include-site-packages. |
1106 | 51 | 51 | ||
1107 | 52 | script-initialization | 52 | script-initialization |
1108 | 53 | The standard initialization code affects both an interpreter and scripts. | 53 | The standard initialization code affects both an interpreter and scripts. |
1109 | @@ -202,7 +202,7 @@ | |||
1110 | 202 | possibilities. Don't be unaware of the dangers. | 202 | possibilities. Don't be unaware of the dangers. |
1111 | 203 | 203 | ||
1112 | 204 | To show off these features, we need to use buildout with a Python | 204 | To show off these features, we need to use buildout with a Python |
1114 | 205 | executable with some extra paths to show ``add-site-packages``; and one | 205 | executable with some extra paths to show ``include-site-packages``; and one |
1115 | 206 | guaranteed to have a sitecustomize module to show | 206 | guaranteed to have a sitecustomize module to show |
1116 | 207 | ``exec-sitecustomize``. We'll make one using a test fixture called | 207 | ``exec-sitecustomize``. We'll make one using a test fixture called |
1117 | 208 | ``make_py``. The os.environ change below will go into the sitecustomize, | 208 | ``make_py``. The os.environ change below will go into the sitecustomize, |
1118 | @@ -215,7 +215,7 @@ | |||
1119 | 215 | >>> print site_packages_path | 215 | >>> print site_packages_path |
1120 | 216 | /executable_buildout/site-packages | 216 | /executable_buildout/site-packages |
1121 | 217 | 217 | ||
1123 | 218 | Now let's take a look at add-site-packages. | 218 | Now let's take a look at include-site-packages. |
1124 | 219 | 219 | ||
1125 | 220 | >>> write(sample_buildout, 'buildout.cfg', | 220 | >>> write(sample_buildout, 'buildout.cfg', |
1126 | 221 | ... """ | 221 | ... """ |
1127 | @@ -225,7 +225,7 @@ | |||
1128 | 225 | ... | 225 | ... |
1129 | 226 | ... [py] | 226 | ... [py] |
1130 | 227 | ... recipe = z3c.recipe.scripts:interpreter | 227 | ... recipe = z3c.recipe.scripts:interpreter |
1132 | 228 | ... add-site-packages = true | 228 | ... include-site-packages = true |
1133 | 229 | ... eggs = demo<0.3 | 229 | ... eggs = demo<0.3 |
1134 | 230 | ... find-links = %(server)s | 230 | ... find-links = %(server)s |
1135 | 231 | ... index = %(server)s/index | 231 | ... index = %(server)s/index |
1136 | 232 | 232 | ||
1137 | === modified file 'z3c.recipe.scripts_/src/z3c/recipe/scripts/scripts.py' | |||
1138 | --- z3c.recipe.scripts_/src/z3c/recipe/scripts/scripts.py 2010-02-24 23:22:13 +0000 | |||
1139 | +++ z3c.recipe.scripts_/src/z3c/recipe/scripts/scripts.py 2010-02-24 23:22:13 +0000 | |||
1140 | @@ -31,13 +31,13 @@ | |||
1141 | 31 | b_options['parts-directory'], self.name) | 31 | b_options['parts-directory'], self.name) |
1142 | 32 | 32 | ||
1143 | 33 | value = options.setdefault( | 33 | value = options.setdefault( |
1146 | 34 | 'add-site-packages', | 34 | 'include-site-packages', |
1147 | 35 | b_options.get('add-site-packages', 'false')) | 35 | b_options.get('include-site-packages', 'false')) |
1148 | 36 | if value not in ('true', 'false'): | 36 | if value not in ('true', 'false'): |
1149 | 37 | raise zc.buildout.UserError( | 37 | raise zc.buildout.UserError( |
1151 | 38 | "Invalid value for add-site-packages option: %s" % | 38 | "Invalid value for include-site-packages option: %s" % |
1152 | 39 | (value,)) | 39 | (value,)) |
1154 | 40 | self.add_site_packages = (value == 'true') | 40 | self.include_site_packages = (value == 'true') |
1155 | 41 | 41 | ||
1156 | 42 | value = options.setdefault( | 42 | value = options.setdefault( |
1157 | 43 | 'exec-sitecustomize', | 43 | 'exec-sitecustomize', |
1158 | @@ -69,7 +69,7 @@ | |||
1159 | 69 | interpreter=options['name'], | 69 | interpreter=options['name'], |
1160 | 70 | extra_paths=self.extra_paths, | 70 | extra_paths=self.extra_paths, |
1161 | 71 | initialization=options.get('initialization', ''), | 71 | initialization=options.get('initialization', ''), |
1163 | 72 | add_site_packages=self.add_site_packages, | 72 | include_site_packages=self.include_site_packages, |
1164 | 73 | exec_sitecustomize=self.exec_sitecustomize, | 73 | exec_sitecustomize=self.exec_sitecustomize, |
1165 | 74 | relative_paths=self._relative_paths, | 74 | relative_paths=self._relative_paths, |
1166 | 75 | )) | 75 | )) |
1167 | @@ -92,7 +92,7 @@ | |||
1168 | 92 | interpreter=options.get('interpreter'), | 92 | interpreter=options.get('interpreter'), |
1169 | 93 | extra_paths=self.extra_paths, | 93 | extra_paths=self.extra_paths, |
1170 | 94 | initialization=options.get('initialization', ''), | 94 | initialization=options.get('initialization', ''), |
1172 | 95 | add_site_packages=self.add_site_packages, | 95 | include_site_packages=self.include_site_packages, |
1173 | 96 | exec_sitecustomize=self.exec_sitecustomize, | 96 | exec_sitecustomize=self.exec_sitecustomize, |
1174 | 97 | relative_paths=self._relative_paths, | 97 | relative_paths=self._relative_paths, |
1175 | 98 | script_arguments=options.get('arguments', ''), | 98 | script_arguments=options.get('arguments', ''), |
1176 | 99 | 99 | ||
1177 | === modified file 'z3c.recipe.scripts_/src/z3c/recipe/scripts/tests.py' | |||
1178 | --- z3c.recipe.scripts_/src/z3c/recipe/scripts/tests.py 2010-02-24 23:22:13 +0000 | |||
1179 | +++ z3c.recipe.scripts_/src/z3c/recipe/scripts/tests.py 2010-02-24 23:22:13 +0000 | |||
1180 | @@ -25,7 +25,7 @@ | |||
1181 | 25 | # all of the examples. The README tests ``extends``, | 25 | # all of the examples. The README tests ``extends``, |
1182 | 26 | # ``include-site-customization`` and ``name``. That leaves ``python``, | 26 | # ``include-site-customization`` and ``name``. That leaves ``python``, |
1183 | 27 | # ``extra-paths``, ``initialization``, ``relative-paths``, and | 27 | # ``extra-paths``, ``initialization``, ``relative-paths``, and |
1185 | 28 | # ``add-site-packages``. | 28 | # ``include-site-packages``. |
1186 | 29 | 29 | ||
1187 | 30 | def supports_python_option(): | 30 | def supports_python_option(): |
1188 | 31 | """ | 31 | """ |
This branch builds the infrastructure in easy_install that is needed for z3c.recipe.scripts to control what packages from site-packages can be used to fulfill setup.py dependencies. Hooking it up comes in the subsequent branch, ~gary/zc. buildout/ python- support- 6-egg-control .
This branch merged the remaining work from my previous zc.buildout effort. Much of this branch has therefore been reviewed before.
In the previous branch, I had a flag called "include- site-packages" (or "include_ site_packages" depending on whether it is a config file or Python) for behavior related to what I had been calling "add-site-packages" (or "add_site_ packages" ) in the more recent effort. I settled on "include- site-packages" /"include_ site_packages" because it seemed to me to better describe the behavior of the flag, particularly in the case of the zc.buildout. easy_install. include_ site_packages function.
My addition and use of _get_version_info is new to this branch. It seems OK to me, but I questioned it, and would welcome other ideas. You'll notice that previously buildout indiscriminately added the buildout and setuptools paths. I felt that being more careful was warranted, but maybe I'm wrong.
I noticed a couple of intermittent test failures during the development of this branch. I got them to go away with the use of get_installer_ values and set_installer_ values for careful teardowns of various test changes. This work is also new.
That's it. Thank you.
Gary