1 | Python API for egg and script installation |
---|
2 | ========================================== |
---|
3 | |
---|
4 | The easy_install module provides some functions to provide support for |
---|
5 | egg and script installation. It provides functionality at the python |
---|
6 | level that is similar to easy_install, with a few exceptions: |
---|
7 | |
---|
8 | - By default, we look for new packages *and* the packages that |
---|
9 | they depend on. This is somewhat like (and uses) the --upgrade |
---|
10 | option of easy_install, except that we also upgrade required |
---|
11 | packages. |
---|
12 | |
---|
13 | - If the highest-revision package satisfying a specification is |
---|
14 | already present, then we don't try to get another one. This saves a |
---|
15 | lot of search time in the common case that packages are pegged to |
---|
16 | specific versions. |
---|
17 | |
---|
18 | - If there is a develop egg that satisfies a requirement, we don't |
---|
19 | look for additional distributions. We always give preference to |
---|
20 | develop eggs. |
---|
21 | |
---|
22 | - Distutils options for building extensions can be passed. |
---|
23 | |
---|
24 | Distribution installation |
---|
25 | ------------------------- |
---|
26 | |
---|
27 | The easy_install module provides a function, install, for installing one |
---|
28 | or more packages and their dependencies. The install function takes 2 |
---|
29 | positional arguments: |
---|
30 | |
---|
31 | - An iterable of setuptools requirement strings for the distributions |
---|
32 | to be installed, and |
---|
33 | |
---|
34 | - A destination directory to install to and to satisfy requirements |
---|
35 | from. The destination directory can be None, in which case, no new |
---|
36 | distributions are downloaded and there will be an error if the |
---|
37 | needed distributions can't be found among those already installed. |
---|
38 | |
---|
39 | It supports a number of optional keyword arguments: |
---|
40 | |
---|
41 | links |
---|
42 | A sequence of URLs, file names, or directories to look for |
---|
43 | links to distributions. |
---|
44 | |
---|
45 | index |
---|
46 | The URL of an index server, or almost any other valid URL. :) |
---|
47 | |
---|
48 | If not specified, the Python Package Index, |
---|
49 | http://pypi.python.org/simple/, is used. You can specify an |
---|
50 | alternate index with this option. If you use the links option and |
---|
51 | if the links point to the needed distributions, then the index can |
---|
52 | be anything and will be largely ignored. In the examples, here, |
---|
53 | we'll just point to an empty directory on our link server. This |
---|
54 | will make our examples run a little bit faster. |
---|
55 | |
---|
56 | executable |
---|
57 | A path to a Python executable. Distributions will be installed |
---|
58 | using this executable and will be for the matching Python version. |
---|
59 | |
---|
60 | path |
---|
61 | A list of additional directories to search for locally-installed |
---|
62 | distributions. |
---|
63 | |
---|
64 | always_unzip |
---|
65 | A flag indicating that newly-downloaded distributions should be |
---|
66 | directories even if they could be installed as zip files. |
---|
67 | |
---|
68 | working_set |
---|
69 | An existing working set to be augmented with additional |
---|
70 | distributions, if necessary to satisfy requirements. This allows |
---|
71 | you to call install multiple times, if necessary, to gather |
---|
72 | multiple sets of requirements. |
---|
73 | |
---|
74 | newest |
---|
75 | A boolean value indicating whether to search for new distributions |
---|
76 | when already-installed distributions meet the requirement. When |
---|
77 | this is true, the default, and when the destination directory is |
---|
78 | not None, then the install function will search for the newest |
---|
79 | distributions that satisfy the requirements. |
---|
80 | |
---|
81 | versions |
---|
82 | A dictionary mapping project names to version numbers to be used |
---|
83 | when selecting distributions. This can be used to specify a set of |
---|
84 | distribution versions independent of other requirements. |
---|
85 | |
---|
86 | use_dependency_links |
---|
87 | A flag indicating whether to search for dependencies using the |
---|
88 | setup dependency_links metadata or not. If true, links are searched |
---|
89 | for using dependency_links in preference to other |
---|
90 | locations. Defaults to true. |
---|
91 | |
---|
92 | relative_paths |
---|
93 | Adjust egg paths so they are relative to the script path. This |
---|
94 | allows scripts to work when scripts and eggs are moved, as long as |
---|
95 | they are both moved in the same way. |
---|
96 | |
---|
97 | The install method returns a working set containing the distributions |
---|
98 | needed to meet the given requirements. |
---|
99 | |
---|
100 | We have a link server that has a number of eggs: |
---|
101 | |
---|
102 | >>> print get(link_server), |
---|
103 | <html><body> |
---|
104 | <a href="bigdemo-0.1-py2.4.egg">bigdemo-0.1-py2.4.egg</a><br> |
---|
105 | <a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br> |
---|
106 | <a href="demo-0.2-py2.4.egg">demo-0.2-py2.4.egg</a><br> |
---|
107 | <a href="demo-0.3-py2.4.egg">demo-0.3-py2.4.egg</a><br> |
---|
108 | <a href="demo-0.4c1-py2.4.egg">demo-0.4c1-py2.4.egg</a><br> |
---|
109 | <a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br> |
---|
110 | <a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br> |
---|
111 | <a href="demoneeded-1.2c1.zip">demoneeded-1.2c1.zip</a><br> |
---|
112 | <a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br> |
---|
113 | <a href="index/">index/</a><br> |
---|
114 | <a href="other-1.0-py2.4.egg">other-1.0-py2.4.egg</a><br> |
---|
115 | </body></html> |
---|
116 | |
---|
117 | Let's make a directory and install the demo egg to it, using the demo: |
---|
118 | |
---|
119 | >>> dest = tmpdir('sample-install') |
---|
120 | >>> import zc.buildout.easy_install |
---|
121 | >>> ws = zc.buildout.easy_install.install( |
---|
122 | ... ['demo==0.2'], dest, |
---|
123 | ... links=[link_server], index=link_server+'index/') |
---|
124 | |
---|
125 | We requested version 0.2 of the demo distribution to be installed into |
---|
126 | the destination server. We specified that we should search for links |
---|
127 | on the link server and that we should use the (empty) link server |
---|
128 | index directory as a package index. |
---|
129 | |
---|
130 | The working set contains the distributions we retrieved. |
---|
131 | |
---|
132 | >>> for dist in ws: |
---|
133 | ... print dist |
---|
134 | demo 0.2 |
---|
135 | demoneeded 1.1 |
---|
136 | |
---|
137 | We got demoneeded because it was a dependency of demo. |
---|
138 | |
---|
139 | And the actual eggs were added to the eggs directory. |
---|
140 | |
---|
141 | >>> ls(dest) |
---|
142 | - demo-0.2-py2.4.egg |
---|
143 | - demoneeded-1.1-py2.4.egg |
---|
144 | |
---|
145 | If we remove the version restriction on demo, but specify a false |
---|
146 | value for newest, no new distributions will be installed: |
---|
147 | |
---|
148 | >>> ws = zc.buildout.easy_install.install( |
---|
149 | ... ['demo'], dest, links=[link_server], index=link_server+'index/', |
---|
150 | ... newest=False) |
---|
151 | >>> ls(dest) |
---|
152 | - demo-0.2-py2.4.egg |
---|
153 | - demoneeded-1.1-py2.4.egg |
---|
154 | |
---|
155 | If we leave off the newest option, we'll get an update for demo: |
---|
156 | |
---|
157 | >>> ws = zc.buildout.easy_install.install( |
---|
158 | ... ['demo'], dest, links=[link_server], index=link_server+'index/') |
---|
159 | >>> ls(dest) |
---|
160 | - demo-0.2-py2.4.egg |
---|
161 | - demo-0.3-py2.4.egg |
---|
162 | - demoneeded-1.1-py2.4.egg |
---|
163 | |
---|
164 | Note that we didn't get the newest versions available. There were |
---|
165 | release candidates for newer versions of both packages. By default, |
---|
166 | final releases are preferred. We can change this behavior using the |
---|
167 | prefer_final function: |
---|
168 | |
---|
169 | >>> zc.buildout.easy_install.prefer_final(False) |
---|
170 | True |
---|
171 | |
---|
172 | The old setting is returned. |
---|
173 | |
---|
174 | >>> ws = zc.buildout.easy_install.install( |
---|
175 | ... ['demo'], dest, links=[link_server], index=link_server+'index/') |
---|
176 | >>> for dist in ws: |
---|
177 | ... print dist |
---|
178 | demo 0.4c1 |
---|
179 | demoneeded 1.2c1 |
---|
180 | |
---|
181 | >>> ls(dest) |
---|
182 | - demo-0.2-py2.4.egg |
---|
183 | - demo-0.3-py2.4.egg |
---|
184 | - demo-0.4c1-py2.4.egg |
---|
185 | - demoneeded-1.1-py2.4.egg |
---|
186 | - demoneeded-1.2c1-py2.4.egg |
---|
187 | |
---|
188 | Let's put the setting back to the default. |
---|
189 | |
---|
190 | >>> zc.buildout.easy_install.prefer_final(True) |
---|
191 | False |
---|
192 | |
---|
193 | We can supply additional distributions. We can also supply |
---|
194 | specifications for distributions that would normally be found via |
---|
195 | dependencies. We might do this to specify a specific version. |
---|
196 | |
---|
197 | >>> ws = zc.buildout.easy_install.install( |
---|
198 | ... ['demo', 'other', 'demoneeded==1.0'], dest, |
---|
199 | ... links=[link_server], index=link_server+'index/') |
---|
200 | |
---|
201 | >>> for dist in ws: |
---|
202 | ... print dist |
---|
203 | demo 0.3 |
---|
204 | other 1.0 |
---|
205 | demoneeded 1.0 |
---|
206 | |
---|
207 | >>> ls(dest) |
---|
208 | - demo-0.2-py2.4.egg |
---|
209 | - demo-0.3-py2.4.egg |
---|
210 | - demo-0.4c1-py2.4.egg |
---|
211 | - demoneeded-1.0-py2.4.egg |
---|
212 | - demoneeded-1.1-py2.4.egg |
---|
213 | - demoneeded-1.2c1-py2.4.egg |
---|
214 | d other-1.0-py2.4.egg |
---|
215 | |
---|
216 | We can request that eggs be unzipped even if they are zip safe. This |
---|
217 | can be useful when debugging. |
---|
218 | |
---|
219 | >>> rmdir(dest) |
---|
220 | >>> dest = tmpdir('sample-install') |
---|
221 | >>> ws = zc.buildout.easy_install.install( |
---|
222 | ... ['demo'], dest, links=[link_server], index=link_server+'index/', |
---|
223 | ... always_unzip=True) |
---|
224 | |
---|
225 | >>> ls(dest) |
---|
226 | d demo-0.3-py2.4.egg |
---|
227 | d demoneeded-1.1-py2.4.egg |
---|
228 | |
---|
229 | >>> rmdir(dest) |
---|
230 | >>> dest = tmpdir('sample-install') |
---|
231 | >>> ws = zc.buildout.easy_install.install( |
---|
232 | ... ['demo'], dest, links=[link_server], index=link_server+'index/', |
---|
233 | ... always_unzip=False) |
---|
234 | |
---|
235 | >>> ls(dest) |
---|
236 | - demo-0.3-py2.4.egg |
---|
237 | - demoneeded-1.1-py2.4.egg |
---|
238 | |
---|
239 | We can also set a default by calling the always_unzip function: |
---|
240 | |
---|
241 | >>> zc.buildout.easy_install.always_unzip(True) |
---|
242 | False |
---|
243 | |
---|
244 | The old default is returned: |
---|
245 | |
---|
246 | >>> rmdir(dest) |
---|
247 | >>> dest = tmpdir('sample-install') |
---|
248 | >>> ws = zc.buildout.easy_install.install( |
---|
249 | ... ['demo'], dest, links=[link_server], index=link_server+'index/') |
---|
250 | |
---|
251 | >>> ls(dest) |
---|
252 | d demo-0.3-py2.4.egg |
---|
253 | d demoneeded-1.1-py2.4.egg |
---|
254 | |
---|
255 | |
---|
256 | >>> zc.buildout.easy_install.always_unzip(False) |
---|
257 | True |
---|
258 | |
---|
259 | >>> rmdir(dest) |
---|
260 | >>> dest = tmpdir('sample-install') |
---|
261 | >>> ws = zc.buildout.easy_install.install( |
---|
262 | ... ['demo'], dest, links=[link_server], index=link_server+'index/') |
---|
263 | |
---|
264 | >>> ls(dest) |
---|
265 | - demo-0.3-py2.4.egg |
---|
266 | - demoneeded-1.1-py2.4.egg |
---|
267 | |
---|
268 | >>> rmdir(dest) |
---|
269 | >>> dest = tmpdir('sample-install') |
---|
270 | >>> ws = zc.buildout.easy_install.install( |
---|
271 | ... ['demo'], dest, links=[link_server], index=link_server+'index/', |
---|
272 | ... always_unzip=True) |
---|
273 | |
---|
274 | >>> ls(dest) |
---|
275 | d demo-0.3-py2.4.egg |
---|
276 | d demoneeded-1.1-py2.4.egg |
---|
277 | |
---|
278 | Specifying version information independent of requirements |
---|
279 | ---------------------------------------------------------- |
---|
280 | |
---|
281 | Sometimes it's useful to specify version information independent of |
---|
282 | normal requirements specifications. For example, a buildout may need |
---|
283 | to lock down a set of versions, without having to put put version |
---|
284 | numbers in setup files or part definitions. If a dictionary is passed |
---|
285 | to the install function, mapping project names to version numbers, |
---|
286 | then the versions numbers will be used. |
---|
287 | |
---|
288 | >>> ws = zc.buildout.easy_install.install( |
---|
289 | ... ['demo'], dest, links=[link_server], index=link_server+'index/', |
---|
290 | ... versions = dict(demo='0.2', demoneeded='1.0')) |
---|
291 | >>> [d.version for d in ws] |
---|
292 | ['0.2', '1.0'] |
---|
293 | |
---|
294 | In this example, we specified a version for demoneeded, even though we |
---|
295 | didn't define a requirement for it. The versions specified apply to |
---|
296 | dependencies as well as the specified requirements. |
---|
297 | |
---|
298 | If we specify a version that's incompatible with a requirement, then |
---|
299 | we'll get an error: |
---|
300 | |
---|
301 | >>> from zope.testing.loggingsupport import InstalledHandler |
---|
302 | >>> handler = InstalledHandler('zc.buildout.easy_install') |
---|
303 | >>> import logging |
---|
304 | >>> logging.getLogger('zc.buildout.easy_install').propagate = False |
---|
305 | |
---|
306 | >>> ws = zc.buildout.easy_install.install( |
---|
307 | ... ['demo >0.2'], dest, links=[link_server], |
---|
308 | ... index=link_server+'index/', |
---|
309 | ... versions = dict(demo='0.2', demoneeded='1.0')) |
---|
310 | Traceback (most recent call last): |
---|
311 | ... |
---|
312 | IncompatibleVersionError: Bad version 0.2 |
---|
313 | |
---|
314 | >>> print handler |
---|
315 | zc.buildout.easy_install DEBUG |
---|
316 | Installing 'demo >0.2'. |
---|
317 | zc.buildout.easy_install ERROR |
---|
318 | The version, 0.2, is not consistent with the requirement, 'demo>0.2'. |
---|
319 | |
---|
320 | >>> handler.clear() |
---|
321 | |
---|
322 | If no versions are specified, a debugging message will be output |
---|
323 | reporting that a version was picked automatically: |
---|
324 | |
---|
325 | >>> ws = zc.buildout.easy_install.install( |
---|
326 | ... ['demo'], dest, links=[link_server], index=link_server+'index/', |
---|
327 | ... ) |
---|
328 | |
---|
329 | >>> print handler |
---|
330 | zc.buildout.easy_install DEBUG |
---|
331 | Installing 'demo'. |
---|
332 | zc.buildout.easy_install DEBUG |
---|
333 | We have the best distribution that satisfies 'demo'. |
---|
334 | zc.buildout.easy_install DEBUG |
---|
335 | Picked: demo = 0.3 |
---|
336 | zc.buildout.easy_install DEBUG |
---|
337 | Getting required 'demoneeded' |
---|
338 | zc.buildout.easy_install DEBUG |
---|
339 | required by demo 0.3. |
---|
340 | zc.buildout.easy_install DEBUG |
---|
341 | We have the best distribution that satisfies 'demoneeded'. |
---|
342 | zc.buildout.easy_install DEBUG |
---|
343 | Picked: demoneeded = 1.1 |
---|
344 | |
---|
345 | >>> handler.uninstall() |
---|
346 | >>> logging.getLogger('zc.buildout.easy_install').propagate = True |
---|
347 | |
---|
348 | We can request that we get an error if versions are picked: |
---|
349 | |
---|
350 | >>> zc.buildout.easy_install.allow_picked_versions(False) |
---|
351 | True |
---|
352 | |
---|
353 | (The old setting is returned.) |
---|
354 | |
---|
355 | >>> ws = zc.buildout.easy_install.install( |
---|
356 | ... ['demo'], dest, links=[link_server], index=link_server+'index/', |
---|
357 | ... ) |
---|
358 | Traceback (most recent call last): |
---|
359 | ... |
---|
360 | UserError: Picked: demo = 0.3 |
---|
361 | |
---|
362 | >>> zc.buildout.easy_install.allow_picked_versions(True) |
---|
363 | False |
---|
364 | |
---|
365 | The function default_versions can be used to get and set default |
---|
366 | version information to be used when no version information is passes. |
---|
367 | If called with an argument, it sets the default versions: |
---|
368 | |
---|
369 | >>> zc.buildout.easy_install.default_versions(dict(demoneeded='1')) |
---|
370 | {} |
---|
371 | |
---|
372 | It always returns the previous default versions. If called without an |
---|
373 | argument, it simply returns the default versions without changing |
---|
374 | them: |
---|
375 | |
---|
376 | >>> zc.buildout.easy_install.default_versions() |
---|
377 | {'demoneeded': '1'} |
---|
378 | |
---|
379 | So with the default versions set, we'll get the requested version even |
---|
380 | if the versions option isn't used: |
---|
381 | |
---|
382 | >>> ws = zc.buildout.easy_install.install( |
---|
383 | ... ['demo'], dest, links=[link_server], index=link_server+'index/', |
---|
384 | ... ) |
---|
385 | |
---|
386 | >>> [d.version for d in ws] |
---|
387 | ['0.3', '1.0'] |
---|
388 | |
---|
389 | Of course, we can unset the default versions by passing an empty |
---|
390 | dictionary: |
---|
391 | |
---|
392 | >>> zc.buildout.easy_install.default_versions({}) |
---|
393 | {'demoneeded': '1'} |
---|
394 | |
---|
395 | >>> ws = zc.buildout.easy_install.install( |
---|
396 | ... ['demo'], dest, links=[link_server], index=link_server+'index/', |
---|
397 | ... ) |
---|
398 | |
---|
399 | >>> [d.version for d in ws] |
---|
400 | ['0.3', '1.1'] |
---|
401 | |
---|
402 | Dependency links |
---|
403 | ---------------- |
---|
404 | |
---|
405 | Setuptools allows metadata that describes where to search for package |
---|
406 | dependencies. This option is called dependency_links. Buildout has its |
---|
407 | own notion of where to look for dependencies, but it also uses the |
---|
408 | setup tools dependency_links information if it's available. |
---|
409 | |
---|
410 | Let's demo this by creating an egg that specifies dependency_links. |
---|
411 | |
---|
412 | To begin, let's create a new egg repository. This repository hold a |
---|
413 | newer version of the 'demoneeded' egg than the sample repository does. |
---|
414 | |
---|
415 | >>> repoloc = tmpdir('repo') |
---|
416 | >>> from zc.buildout.tests import create_egg |
---|
417 | >>> create_egg('demoneeded', '1.2', repoloc) |
---|
418 | >>> link_server2 = start_server(repoloc) |
---|
419 | |
---|
420 | Turn on logging on this server so that we can see when eggs are pulled |
---|
421 | from it. |
---|
422 | |
---|
423 | >>> get(link_server2 + 'enable_server_logging') |
---|
424 | GET 200 /enable_server_logging |
---|
425 | '' |
---|
426 | |
---|
427 | Now we can create an egg that specifies that its dependencies are |
---|
428 | found on this server. |
---|
429 | |
---|
430 | >>> repoloc = tmpdir('repo2') |
---|
431 | >>> create_egg('hasdeps', '1.0', repoloc, |
---|
432 | ... install_requires = "'demoneeded'", |
---|
433 | ... dependency_links = [link_server2]) |
---|
434 | |
---|
435 | Let's add the egg to another repository. |
---|
436 | |
---|
437 | >>> link_server3 = start_server(repoloc) |
---|
438 | |
---|
439 | Now let's install the egg. |
---|
440 | |
---|
441 | >>> example_dest = tmpdir('example-install') |
---|
442 | >>> workingset = zc.buildout.easy_install.install( |
---|
443 | ... ['hasdeps'], example_dest, |
---|
444 | ... links=[link_server3], index=link_server3+'index/') |
---|
445 | GET 200 / |
---|
446 | GET 200 /demoneeded-1.2-pyN.N.egg |
---|
447 | |
---|
448 | The server logs show that the dependency was retrieved from the server |
---|
449 | specified in the dependency_links. |
---|
450 | |
---|
451 | Now let's see what happens if we provide two different ways to retrieve |
---|
452 | the dependencies. |
---|
453 | |
---|
454 | >>> rmdir(example_dest) |
---|
455 | >>> example_dest = tmpdir('example-install') |
---|
456 | >>> workingset = zc.buildout.easy_install.install( |
---|
457 | ... ['hasdeps'], example_dest, index=link_server+'index/', |
---|
458 | ... links=[link_server, link_server3]) |
---|
459 | GET 200 / |
---|
460 | GET 200 /demoneeded-1.2-pyN.N.egg |
---|
461 | |
---|
462 | Once again the dependency is fetched from the logging server even |
---|
463 | though it is also available from the non-logging server. This is |
---|
464 | because the version on the logging server is newer and buildout |
---|
465 | normally chooses the newest egg available. |
---|
466 | |
---|
467 | If you wish to control where dependencies come from regardless of |
---|
468 | dependency_links setup metadata use the 'use_dependency_links' option |
---|
469 | to zc.buildout.easy_install.install(). |
---|
470 | |
---|
471 | >>> rmdir(example_dest) |
---|
472 | >>> example_dest = tmpdir('example-install') |
---|
473 | >>> workingset = zc.buildout.easy_install.install( |
---|
474 | ... ['hasdeps'], example_dest, index=link_server+'index/', |
---|
475 | ... links=[link_server, link_server3], |
---|
476 | ... use_dependency_links=False) |
---|
477 | |
---|
478 | Notice that this time the dependency egg is not fetched from the |
---|
479 | logging server. When you specify not to use dependency_links, eggs |
---|
480 | will only be searched for using the links you explicitly provide. |
---|
481 | |
---|
482 | Another way to control this option is with the |
---|
483 | zc.buildout.easy_install.use_dependency_links() function. This |
---|
484 | function sets the default behavior for the zc.buildout.easy_install() |
---|
485 | function. |
---|
486 | |
---|
487 | >>> zc.buildout.easy_install.use_dependency_links(False) |
---|
488 | True |
---|
489 | |
---|
490 | The function returns its previous setting. |
---|
491 | |
---|
492 | >>> rmdir(example_dest) |
---|
493 | >>> example_dest = tmpdir('example-install') |
---|
494 | >>> workingset = zc.buildout.easy_install.install( |
---|
495 | ... ['hasdeps'], example_dest, index=link_server+'index/', |
---|
496 | ... links=[link_server, link_server3]) |
---|
497 | |
---|
498 | It can be overridden by passing a keyword argument to the install |
---|
499 | function. |
---|
500 | |
---|
501 | >>> rmdir(example_dest) |
---|
502 | >>> example_dest = tmpdir('example-install') |
---|
503 | >>> workingset = zc.buildout.easy_install.install( |
---|
504 | ... ['hasdeps'], example_dest, index=link_server+'index/', |
---|
505 | ... links=[link_server, link_server3], |
---|
506 | ... use_dependency_links=True) |
---|
507 | GET 200 /demoneeded-1.2-pyN.N.egg |
---|
508 | |
---|
509 | To return the dependency_links behavior to normal call the function again. |
---|
510 | |
---|
511 | >>> zc.buildout.easy_install.use_dependency_links(True) |
---|
512 | False |
---|
513 | >>> rmdir(example_dest) |
---|
514 | >>> example_dest = tmpdir('example-install') |
---|
515 | >>> workingset = zc.buildout.easy_install.install( |
---|
516 | ... ['hasdeps'], example_dest, index=link_server+'index/', |
---|
517 | ... links=[link_server, link_server3]) |
---|
518 | GET 200 /demoneeded-1.2-pyN.N.egg |
---|
519 | |
---|
520 | |
---|
521 | Script generation |
---|
522 | ----------------- |
---|
523 | |
---|
524 | The easy_install module provides support for creating scripts from |
---|
525 | eggs. It provides a function similar to setuptools except that it |
---|
526 | provides facilities for baking a script's path into the script. This |
---|
527 | has two advantages: |
---|
528 | |
---|
529 | - The eggs to be used by a script are not chosen at run time, making |
---|
530 | startup faster and, more importantly, deterministic. |
---|
531 | |
---|
532 | - The script doesn't have to import pkg_resources because the logic |
---|
533 | that pkg_resources would execute at run time is executed at |
---|
534 | script-creation time. |
---|
535 | |
---|
536 | The scripts method can be used to generate scripts. Let's create a |
---|
537 | destination directory for it to place them in: |
---|
538 | |
---|
539 | >>> import tempfile |
---|
540 | >>> bin = tmpdir('bin') |
---|
541 | |
---|
542 | Now, we'll use the scripts method to generate scripts in this directory |
---|
543 | from the demo egg: |
---|
544 | |
---|
545 | >>> import sys |
---|
546 | >>> scripts = zc.buildout.easy_install.scripts( |
---|
547 | ... ['demo'], ws, sys.executable, bin) |
---|
548 | |
---|
549 | the four arguments we passed were: |
---|
550 | |
---|
551 | 1. A sequence of distribution requirements. These are of the same |
---|
552 | form as setuptools requirements. Here we passed a single |
---|
553 | requirement, for the version 0.1 demo distribution. |
---|
554 | |
---|
555 | 2. A working set, |
---|
556 | |
---|
557 | 3. The Python executable to use, and |
---|
558 | |
---|
559 | 3. The destination directory. |
---|
560 | |
---|
561 | The bin directory now contains a generated script: |
---|
562 | |
---|
563 | >>> ls(bin) |
---|
564 | - demo |
---|
565 | |
---|
566 | The return value is a list of the scripts generated: |
---|
567 | |
---|
568 | >>> import os, sys |
---|
569 | >>> if sys.platform == 'win32': |
---|
570 | ... scripts == [os.path.join(bin, 'demo.exe'), |
---|
571 | ... os.path.join(bin, 'demo-script.py')] |
---|
572 | ... else: |
---|
573 | ... scripts == [os.path.join(bin, 'demo')] |
---|
574 | True |
---|
575 | |
---|
576 | Note that in Windows, 2 files are generated for each script. A script |
---|
577 | file, ending in '-script.py', and an exe file that allows the script |
---|
578 | to be invoked directly without having to specify the Python |
---|
579 | interpreter and without having to provide a '.py' suffix. |
---|
580 | |
---|
581 | The demo script run the entry point defined in the demo egg: |
---|
582 | |
---|
583 | >>> cat(bin, 'demo') # doctest: +NORMALIZE_WHITESPACE |
---|
584 | #!/usr/local/bin/python2.4 |
---|
585 | <BLANKLINE> |
---|
586 | import sys |
---|
587 | sys.path[0:0] = [ |
---|
588 | '/sample-install/demo-0.3-py2.4.egg', |
---|
589 | '/sample-install/demoneeded-1.1-py2.4.egg', |
---|
590 | ] |
---|
591 | <BLANKLINE> |
---|
592 | import eggrecipedemo |
---|
593 | <BLANKLINE> |
---|
594 | if __name__ == '__main__': |
---|
595 | eggrecipedemo.main() |
---|
596 | |
---|
597 | Some things to note: |
---|
598 | |
---|
599 | - The demo and demoneeded eggs are added to the beginning of sys.path. |
---|
600 | |
---|
601 | - The module for the script entry point is imported and the entry |
---|
602 | point, in this case, 'main', is run. |
---|
603 | |
---|
604 | Rather than requirement strings, you can pass tuples containing 3 |
---|
605 | strings: |
---|
606 | |
---|
607 | - A script name, |
---|
608 | |
---|
609 | - A module, |
---|
610 | |
---|
611 | - An attribute expression for an entry point within the module. |
---|
612 | |
---|
613 | For example, we could have passed entry point information directly |
---|
614 | rather than passing a requirement: |
---|
615 | |
---|
616 | >>> scripts = zc.buildout.easy_install.scripts( |
---|
617 | ... [('demo', 'eggrecipedemo', 'main')], |
---|
618 | ... ws, sys.executable, bin) |
---|
619 | |
---|
620 | >>> cat(bin, 'demo') # doctest: +NORMALIZE_WHITESPACE |
---|
621 | #!/usr/local/bin/python2.4 |
---|
622 | <BLANKLINE> |
---|
623 | import sys |
---|
624 | sys.path[0:0] = [ |
---|
625 | '/sample-install/demo-0.3-py2.4.egg', |
---|
626 | '/sample-install/demoneeded-1.1-py2.4.egg', |
---|
627 | ] |
---|
628 | <BLANKLINE> |
---|
629 | import eggrecipedemo |
---|
630 | <BLANKLINE> |
---|
631 | if __name__ == '__main__': |
---|
632 | eggrecipedemo.main() |
---|
633 | |
---|
634 | Passing entry-point information directly is handy when using eggs (or |
---|
635 | distributions) that don't declare their entry points, such as |
---|
636 | distributions that aren't based on setuptools. |
---|
637 | |
---|
638 | The interpreter keyword argument can be used to generate a script that can |
---|
639 | be used to invoke the Python interactive interpreter with the path set |
---|
640 | based on the working set. This generated script can also be used to |
---|
641 | run other scripts with the path set on the working set: |
---|
642 | |
---|
643 | >>> scripts = zc.buildout.easy_install.scripts( |
---|
644 | ... ['demo'], ws, sys.executable, bin, interpreter='py') |
---|
645 | |
---|
646 | |
---|
647 | >>> ls(bin) |
---|
648 | - demo |
---|
649 | - py |
---|
650 | |
---|
651 | >>> if sys.platform == 'win32': |
---|
652 | ... scripts == [os.path.join(bin, 'demo.exe'), |
---|
653 | ... os.path.join(bin, 'demo-script.py'), |
---|
654 | ... os.path.join(bin, 'py.exe'), |
---|
655 | ... os.path.join(bin, 'py-script.py')] |
---|
656 | ... else: |
---|
657 | ... scripts == [os.path.join(bin, 'demo'), |
---|
658 | ... os.path.join(bin, 'py')] |
---|
659 | True |
---|
660 | |
---|
661 | The py script simply runs the Python interactive interpreter with |
---|
662 | the path set: |
---|
663 | |
---|
664 | >>> cat(bin, 'py') # doctest: +NORMALIZE_WHITESPACE |
---|
665 | #!/usr/local/bin/python2.4 |
---|
666 | import sys |
---|
667 | <BLANKLINE> |
---|
668 | sys.path[0:0] = [ |
---|
669 | '/sample-install/demo-0.3-py2.4.egg', |
---|
670 | '/sample-install/demoneeded-1.1-py2.4.egg', |
---|
671 | ] |
---|
672 | <BLANKLINE> |
---|
673 | _interactive = True |
---|
674 | if len(sys.argv) > 1: |
---|
675 | import getopt |
---|
676 | _options, _args = getopt.getopt(sys.argv[1:], 'ic:') |
---|
677 | _interactive = False |
---|
678 | for (_opt, _val) in _options: |
---|
679 | if _opt == '-i': |
---|
680 | _interactive = True |
---|
681 | elif _opt == '-c': |
---|
682 | exec _val |
---|
683 | <BLANKLINE> |
---|
684 | if _args: |
---|
685 | sys.argv[:] = _args |
---|
686 | execfile(sys.argv[0]) |
---|
687 | <BLANKLINE> |
---|
688 | if _interactive: |
---|
689 | import code |
---|
690 | code.interact(banner="", local=globals()) |
---|
691 | |
---|
692 | If invoked with a script name and arguments, it will run that script, instead. |
---|
693 | |
---|
694 | An additional argument can be passed to define which scripts to install |
---|
695 | and to provide script names. The argument is a dictionary mapping |
---|
696 | original script names to new script names. |
---|
697 | |
---|
698 | >>> bin = tmpdir('bin2') |
---|
699 | >>> scripts = zc.buildout.easy_install.scripts( |
---|
700 | ... ['demo'], ws, sys.executable, bin, dict(demo='run')) |
---|
701 | |
---|
702 | >>> if sys.platform == 'win32': |
---|
703 | ... scripts == [os.path.join(bin, 'run.exe'), |
---|
704 | ... os.path.join(bin, 'run-script.py')] |
---|
705 | ... else: |
---|
706 | ... scripts == [os.path.join(bin, 'run')] |
---|
707 | True |
---|
708 | >>> ls(bin) |
---|
709 | - run |
---|
710 | |
---|
711 | >>> print system(os.path.join(bin, 'run')), |
---|
712 | 3 1 |
---|
713 | |
---|
714 | Including extra paths in scripts |
---|
715 | -------------------------------- |
---|
716 | |
---|
717 | We can pass a keyword argument, extra paths, to cause additional paths |
---|
718 | to be included in the a generated script: |
---|
719 | |
---|
720 | >>> scripts = zc.buildout.easy_install.scripts( |
---|
721 | ... ['demo'], ws, sys.executable, bin, dict(demo='run'), |
---|
722 | ... extra_paths=['/foo/bar']) |
---|
723 | |
---|
724 | >>> cat(bin, 'run') # doctest: +NORMALIZE_WHITESPACE |
---|
725 | #!/usr/local/bin/python2.4 |
---|
726 | <BLANKLINE> |
---|
727 | import sys |
---|
728 | sys.path[0:0] = [ |
---|
729 | '/sample-install/demo-0.3-py2.4.egg', |
---|
730 | '/sample-install/demoneeded-1.1-py2.4.egg', |
---|
731 | '/foo/bar', |
---|
732 | ] |
---|
733 | <BLANKLINE> |
---|
734 | import eggrecipedemo |
---|
735 | <BLANKLINE> |
---|
736 | if __name__ == '__main__': |
---|
737 | eggrecipedemo.main() |
---|
738 | |
---|
739 | Providing script arguments |
---|
740 | -------------------------- |
---|
741 | |
---|
742 | An "argument" keyword argument can be used to pass arguments to an |
---|
743 | entry point. The value passed is a source string to be placed between the |
---|
744 | parentheses in the call: |
---|
745 | |
---|
746 | >>> scripts = zc.buildout.easy_install.scripts( |
---|
747 | ... ['demo'], ws, sys.executable, bin, dict(demo='run'), |
---|
748 | ... arguments='1, 2') |
---|
749 | |
---|
750 | >>> cat(bin, 'run') # doctest: +NORMALIZE_WHITESPACE |
---|
751 | #!/usr/local/bin/python2.4 |
---|
752 | import sys |
---|
753 | sys.path[0:0] = [ |
---|
754 | '/sample-install/demo-0.3-py2.4.egg', |
---|
755 | '/sample-install/demoneeded-1.1-py2.4.egg', |
---|
756 | ] |
---|
757 | <BLANKLINE> |
---|
758 | import eggrecipedemo |
---|
759 | <BLANKLINE> |
---|
760 | if __name__ == '__main__': |
---|
761 | eggrecipedemo.main(1, 2) |
---|
762 | |
---|
763 | Passing initialization code |
---|
764 | --------------------------- |
---|
765 | |
---|
766 | You can also pass script initialization code: |
---|
767 | |
---|
768 | >>> scripts = zc.buildout.easy_install.scripts( |
---|
769 | ... ['demo'], ws, sys.executable, bin, dict(demo='run'), |
---|
770 | ... arguments='1, 2', |
---|
771 | ... initialization='import os\nos.chdir("foo")') |
---|
772 | |
---|
773 | >>> cat(bin, 'run') # doctest: +NORMALIZE_WHITESPACE |
---|
774 | #!/usr/local/bin/python2.4 |
---|
775 | import sys |
---|
776 | sys.path[0:0] = [ |
---|
777 | '/sample-install/demo-0.3-py2.4.egg', |
---|
778 | '/sample-install/demoneeded-1.1-py2.4.egg', |
---|
779 | ] |
---|
780 | <BLANKLINE> |
---|
781 | import os |
---|
782 | os.chdir("foo") |
---|
783 | <BLANKLINE> |
---|
784 | import eggrecipedemo |
---|
785 | <BLANKLINE> |
---|
786 | if __name__ == '__main__': |
---|
787 | eggrecipedemo.main(1, 2) |
---|
788 | |
---|
789 | Relative paths |
---|
790 | -------------- |
---|
791 | |
---|
792 | Sometimes, you want to be able to move a buildout directory around and |
---|
793 | have scripts still work without having to rebuild them. We can |
---|
794 | control this using the relative_paths option to install. You need |
---|
795 | to pass a common base directory of the scripts and eggs: |
---|
796 | |
---|
797 | >>> bo = tmpdir('bo') |
---|
798 | >>> mkdir(bo, 'eggs') |
---|
799 | >>> mkdir(bo, 'bin') |
---|
800 | >>> mkdir(bo, 'other') |
---|
801 | |
---|
802 | >>> ws = zc.buildout.easy_install.install( |
---|
803 | ... ['demo'], join(bo, 'eggs'), links=[link_server], |
---|
804 | ... index=link_server+'index/') |
---|
805 | |
---|
806 | >>> scripts = zc.buildout.easy_install.scripts( |
---|
807 | ... ['demo'], ws, sys.executable, join(bo, 'bin'), dict(demo='run'), |
---|
808 | ... extra_paths=[os.path.sep+'foo', join(bo, 'bar')], |
---|
809 | ... interpreter='py', |
---|
810 | ... relative_paths=bo) |
---|
811 | |
---|
812 | >>> cat(bo, 'bin', 'run') |
---|
813 | #!/usr/local/bin/python2.4 |
---|
814 | <BLANKLINE> |
---|
815 | import os |
---|
816 | <BLANKLINE> |
---|
817 | join = os.path.join |
---|
818 | base = os.path.dirname(__file__) |
---|
819 | base = os.path.dirname(base) |
---|
820 | <BLANKLINE> |
---|
821 | import sys |
---|
822 | sys.path[0:0] = [ |
---|
823 | join(base, 'eggs/demo-0.3-pyN.N.egg'), |
---|
824 | join(base, 'eggs/demoneeded-1.1-pyN.N.egg'), |
---|
825 | '/foo', |
---|
826 | join(base, 'bar'), |
---|
827 | ] |
---|
828 | <BLANKLINE> |
---|
829 | import eggrecipedemo |
---|
830 | <BLANKLINE> |
---|
831 | if __name__ == '__main__': |
---|
832 | eggrecipedemo.main() |
---|
833 | |
---|
834 | Note that the extra path we specified that was outside the directory |
---|
835 | passed as relative_paths wasn't converted to a relative path. |
---|
836 | |
---|
837 | Of course, running the script works: |
---|
838 | |
---|
839 | >>> print system(join(bo, 'bin', 'run')), |
---|
840 | 3 1 |
---|
841 | |
---|
842 | We specified an interpreter and its paths are adjusted too: |
---|
843 | |
---|
844 | >>> cat(bo, 'bin', 'py') |
---|
845 | #!/usr/local/bin/python2.4 |
---|
846 | <BLANKLINE> |
---|
847 | import os |
---|
848 | <BLANKLINE> |
---|
849 | join = os.path.join |
---|
850 | base = os.path.dirname(__file__) |
---|
851 | base = os.path.dirname(base) |
---|
852 | <BLANKLINE> |
---|
853 | import sys |
---|
854 | <BLANKLINE> |
---|
855 | sys.path[0:0] = [ |
---|
856 | join(base, 'eggs/demo-0.3-pyN.N.egg'), |
---|
857 | join(base, 'eggs/demoneeded-1.1-pyN.N.egg'), |
---|
858 | '/foo', |
---|
859 | join(base, 'bar'), |
---|
860 | ] |
---|
861 | <BLANKLINE> |
---|
862 | _interactive = True |
---|
863 | if len(sys.argv) > 1: |
---|
864 | import getopt |
---|
865 | _options, _args = getopt.getopt(sys.argv[1:], 'ic:') |
---|
866 | _interactive = False |
---|
867 | for (_opt, _val) in _options: |
---|
868 | if _opt == '-i': |
---|
869 | _interactive = True |
---|
870 | elif _opt == '-c': |
---|
871 | exec _val |
---|
872 | <BLANKLINE> |
---|
873 | if _args: |
---|
874 | sys.argv[:] = _args |
---|
875 | execfile(sys.argv[0]) |
---|
876 | <BLANKLINE> |
---|
877 | if _interactive: |
---|
878 | import code |
---|
879 | code.interact(banner="", local=globals()) |
---|
880 | |
---|
881 | |
---|
882 | Handling custom build options for extensions provided in source distributions |
---|
883 | ----------------------------------------------------------------------------- |
---|
884 | |
---|
885 | Sometimes, we need to control how extension modules are built. The |
---|
886 | build function provides this level of control. It takes a single |
---|
887 | package specification, downloads a source distribution, and builds it |
---|
888 | with specified custom build options. |
---|
889 | |
---|
890 | The build function takes 3 positional arguments: |
---|
891 | |
---|
892 | spec |
---|
893 | A package specification for a source distribution |
---|
894 | |
---|
895 | dest |
---|
896 | A destination directory |
---|
897 | |
---|
898 | build_ext |
---|
899 | A dictionary of options to be passed to the distutils build_ext |
---|
900 | command when building extensions. |
---|
901 | |
---|
902 | It supports a number of optional keyword arguments: |
---|
903 | |
---|
904 | links |
---|
905 | a sequence of URLs, file names, or directories to look for |
---|
906 | links to distributions, |
---|
907 | |
---|
908 | index |
---|
909 | The URL of an index server, or almost any other valid URL. :) |
---|
910 | |
---|
911 | If not specified, the Python Package Index, |
---|
912 | http://pypi.python.org/simple/, is used. You can specify an |
---|
913 | alternate index with this option. If you use the links option and |
---|
914 | if the links point to the needed distributions, then the index can |
---|
915 | be anything and will be largely ignored. In the examples, here, |
---|
916 | we'll just point to an empty directory on our link server. This |
---|
917 | will make our examples run a little bit faster. |
---|
918 | |
---|
919 | executable |
---|
920 | A path to a Python executable. Distributions will be installed |
---|
921 | using this executable and will be for the matching Python version. |
---|
922 | |
---|
923 | path |
---|
924 | A list of additional directories to search for locally-installed |
---|
925 | distributions. |
---|
926 | |
---|
927 | newest |
---|
928 | A boolean value indicating whether to search for new distributions |
---|
929 | when already-installed distributions meet the requirement. When |
---|
930 | this is true, the default, and when the destination directory is |
---|
931 | not None, then the install function will search for the newest |
---|
932 | distributions that satisfy the requirements. |
---|
933 | |
---|
934 | versions |
---|
935 | A dictionary mapping project names to version numbers to be used |
---|
936 | when selecting distributions. This can be used to specify a set of |
---|
937 | distribution versions independent of other requirements. |
---|
938 | |
---|
939 | |
---|
940 | Our link server included a source distribution that includes a simple |
---|
941 | extension, extdemo.c:: |
---|
942 | |
---|
943 | #include <Python.h> |
---|
944 | #include <extdemo.h> |
---|
945 | |
---|
946 | static PyMethodDef methods[] = {}; |
---|
947 | |
---|
948 | PyMODINIT_FUNC |
---|
949 | initextdemo(void) |
---|
950 | { |
---|
951 | PyObject *m; |
---|
952 | m = Py_InitModule3("extdemo", methods, ""); |
---|
953 | #ifdef TWO |
---|
954 | PyModule_AddObject(m, "val", PyInt_FromLong(2)); |
---|
955 | #else |
---|
956 | PyModule_AddObject(m, "val", PyInt_FromLong(EXTDEMO)); |
---|
957 | #endif |
---|
958 | } |
---|
959 | |
---|
960 | The extension depends on a system-dependent include file, extdemo.h, |
---|
961 | that defines a constant, EXTDEMO, that is exposed by the extension. |
---|
962 | |
---|
963 | We'll add an include directory to our sample buildout and add the |
---|
964 | needed include file to it: |
---|
965 | |
---|
966 | >>> mkdir('include') |
---|
967 | >>> write('include', 'extdemo.h', |
---|
968 | ... """ |
---|
969 | ... #define EXTDEMO 42 |
---|
970 | ... """) |
---|
971 | |
---|
972 | Now, we can use the build function to create an egg from the source |
---|
973 | distribution: |
---|
974 | |
---|
975 | >>> zc.buildout.easy_install.build( |
---|
976 | ... 'extdemo', dest, |
---|
977 | ... {'include-dirs': os.path.join(sample_buildout, 'include')}, |
---|
978 | ... links=[link_server], index=link_server+'index/') |
---|
979 | ['/sample-install/extdemo-1.4-py2.4-unix-i686.egg'] |
---|
980 | |
---|
981 | The function returns the list of eggs |
---|
982 | |
---|
983 | Now if we look in our destination directory, we see we have an extdemo egg: |
---|
984 | |
---|
985 | >>> ls(dest) |
---|
986 | - demo-0.2-py2.4.egg |
---|
987 | d demo-0.3-py2.4.egg |
---|
988 | - demoneeded-1.0-py2.4.egg |
---|
989 | d demoneeded-1.1-py2.4.egg |
---|
990 | d extdemo-1.4-py2.4-unix-i686.egg |
---|
991 | |
---|
992 | Let's update our link server with a new version of extdemo: |
---|
993 | |
---|
994 | >>> update_extdemo() |
---|
995 | >>> print get(link_server), |
---|
996 | <html><body> |
---|
997 | <a href="bigdemo-0.1-py2.4.egg">bigdemo-0.1-py2.4.egg</a><br> |
---|
998 | <a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br> |
---|
999 | <a href="demo-0.2-py2.4.egg">demo-0.2-py2.4.egg</a><br> |
---|
1000 | <a href="demo-0.3-py2.4.egg">demo-0.3-py2.4.egg</a><br> |
---|
1001 | <a href="demo-0.4c1-py2.4.egg">demo-0.4c1-py2.4.egg</a><br> |
---|
1002 | <a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br> |
---|
1003 | <a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br> |
---|
1004 | <a href="demoneeded-1.2c1.zip">demoneeded-1.2c1.zip</a><br> |
---|
1005 | <a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br> |
---|
1006 | <a href="extdemo-1.5.zip">extdemo-1.5.zip</a><br> |
---|
1007 | <a href="index/">index/</a><br> |
---|
1008 | <a href="other-1.0-py2.4.egg">other-1.0-py2.4.egg</a><br> |
---|
1009 | </body></html> |
---|
1010 | |
---|
1011 | The easy_install caches information about servers to reduce network |
---|
1012 | access. To see the update, we have to call the clear_index_cache |
---|
1013 | function to clear the index cache: |
---|
1014 | |
---|
1015 | >>> zc.buildout.easy_install.clear_index_cache() |
---|
1016 | |
---|
1017 | If we run build with newest set to False, we won't get an update: |
---|
1018 | |
---|
1019 | >>> zc.buildout.easy_install.build( |
---|
1020 | ... 'extdemo', dest, |
---|
1021 | ... {'include-dirs': os.path.join(sample_buildout, 'include')}, |
---|
1022 | ... links=[link_server], index=link_server+'index/', |
---|
1023 | ... newest=False) |
---|
1024 | ['/sample-install/extdemo-1.4-py2.4-linux-i686.egg'] |
---|
1025 | |
---|
1026 | >>> ls(dest) |
---|
1027 | - demo-0.2-py2.4.egg |
---|
1028 | d demo-0.3-py2.4.egg |
---|
1029 | - demoneeded-1.0-py2.4.egg |
---|
1030 | d demoneeded-1.1-py2.4.egg |
---|
1031 | d extdemo-1.4-py2.4-unix-i686.egg |
---|
1032 | |
---|
1033 | But if we run it with the default True setting for newest, then we'll |
---|
1034 | get an updated egg: |
---|
1035 | |
---|
1036 | >>> zc.buildout.easy_install.build( |
---|
1037 | ... 'extdemo', dest, |
---|
1038 | ... {'include-dirs': os.path.join(sample_buildout, 'include')}, |
---|
1039 | ... links=[link_server], index=link_server+'index/') |
---|
1040 | ['/sample-install/extdemo-1.5-py2.4-unix-i686.egg'] |
---|
1041 | |
---|
1042 | >>> ls(dest) |
---|
1043 | - demo-0.2-py2.4.egg |
---|
1044 | d demo-0.3-py2.4.egg |
---|
1045 | - demoneeded-1.0-py2.4.egg |
---|
1046 | d demoneeded-1.1-py2.4.egg |
---|
1047 | d extdemo-1.4-py2.4-unix-i686.egg |
---|
1048 | d extdemo-1.5-py2.4-unix-i686.egg |
---|
1049 | |
---|
1050 | The versions option also influences the versions used. For example, |
---|
1051 | if we specify a version for extdemo, then that will be used, even |
---|
1052 | though it isn't the newest. Let's clean out the destination directory |
---|
1053 | first: |
---|
1054 | |
---|
1055 | >>> import os |
---|
1056 | >>> for name in os.listdir(dest): |
---|
1057 | ... remove(dest, name) |
---|
1058 | |
---|
1059 | >>> zc.buildout.easy_install.build( |
---|
1060 | ... 'extdemo', dest, |
---|
1061 | ... {'include-dirs': os.path.join(sample_buildout, 'include')}, |
---|
1062 | ... links=[link_server], index=link_server+'index/', |
---|
1063 | ... versions=dict(extdemo='1.4')) |
---|
1064 | ['/sample-install/extdemo-1.4-py2.4-unix-i686.egg'] |
---|
1065 | |
---|
1066 | >>> ls(dest) |
---|
1067 | d extdemo-1.4-py2.4-unix-i686.egg |
---|
1068 | |
---|
1069 | Handling custom build options for extensions in develop eggs |
---|
1070 | ------------------------------------------------------------ |
---|
1071 | |
---|
1072 | The develop function is similar to the build function, except that, |
---|
1073 | rather than building an egg from a source directory containing a |
---|
1074 | setup.py script. |
---|
1075 | |
---|
1076 | The develop function takes 2 positional arguments: |
---|
1077 | |
---|
1078 | setup |
---|
1079 | The path to a setup script, typically named "setup.py", or a |
---|
1080 | directory containing a setup.py script. |
---|
1081 | |
---|
1082 | dest |
---|
1083 | The directory to install the egg link to |
---|
1084 | |
---|
1085 | It supports some optional keyword argument: |
---|
1086 | |
---|
1087 | build_ext |
---|
1088 | A dictionary of options to be passed to the distutils build_ext |
---|
1089 | command when building extensions. |
---|
1090 | |
---|
1091 | executable |
---|
1092 | A path to a Python executable. Distributions will be installed |
---|
1093 | using this executable and will be for the matching Python version. |
---|
1094 | |
---|
1095 | We have a local directory containing the extdemo source: |
---|
1096 | |
---|
1097 | >>> ls(extdemo) |
---|
1098 | - MANIFEST |
---|
1099 | - MANIFEST.in |
---|
1100 | - README |
---|
1101 | - extdemo.c |
---|
1102 | - setup.py |
---|
1103 | |
---|
1104 | Now, we can use the develop function to create a develop egg from the source |
---|
1105 | distribution: |
---|
1106 | |
---|
1107 | >>> zc.buildout.easy_install.develop( |
---|
1108 | ... extdemo, dest, |
---|
1109 | ... {'include-dirs': os.path.join(sample_buildout, 'include')}) |
---|
1110 | '/sample-install/extdemo.egg-link' |
---|
1111 | |
---|
1112 | The name of the egg link created is returned. |
---|
1113 | |
---|
1114 | Now if we look in our destination directory, we see we have an extdemo |
---|
1115 | egg link: |
---|
1116 | |
---|
1117 | >>> ls(dest) |
---|
1118 | d extdemo-1.4-py2.4-unix-i686.egg |
---|
1119 | - extdemo.egg-link |
---|
1120 | |
---|
1121 | And that the source directory contains the compiled extension: |
---|
1122 | |
---|
1123 | >>> ls(extdemo) |
---|
1124 | - MANIFEST |
---|
1125 | - MANIFEST.in |
---|
1126 | - README |
---|
1127 | d build |
---|
1128 | - extdemo.c |
---|
1129 | d extdemo.egg-info |
---|
1130 | - extdemo.so |
---|
1131 | - setup.py |
---|
1132 | |
---|
1133 | Download cache |
---|
1134 | -------------- |
---|
1135 | |
---|
1136 | Normally, when distributions are installed, if any processing is |
---|
1137 | needed, they are downloaded from the internet to a temporary directory |
---|
1138 | and then installed from there. A download cache can be used to avoid |
---|
1139 | the download step. This can be useful to reduce network access and to |
---|
1140 | create source distributions of an entire buildout. |
---|
1141 | |
---|
1142 | A download cache is specified by calling the download_cache |
---|
1143 | function. The function always returns the previous setting. If no |
---|
1144 | argument is passed, then the setting is unchanged. If an argument is |
---|
1145 | passed, the download cache is set to the given path, which must point |
---|
1146 | to an existing directory. Passing None clears the cache setting. |
---|
1147 | |
---|
1148 | To see this work, we'll create a directory and set it as the cache |
---|
1149 | directory: |
---|
1150 | |
---|
1151 | >>> cache = tmpdir('cache') |
---|
1152 | >>> zc.buildout.easy_install.download_cache(cache) |
---|
1153 | |
---|
1154 | We'll recreate our destination directory: |
---|
1155 | |
---|
1156 | >>> remove(dest) |
---|
1157 | >>> dest = tmpdir('sample-install') |
---|
1158 | |
---|
1159 | We'd like to see what is being fetched from the server, so we'll |
---|
1160 | enable server logging: |
---|
1161 | |
---|
1162 | >>> get(link_server+'enable_server_logging') |
---|
1163 | GET 200 /enable_server_logging |
---|
1164 | '' |
---|
1165 | |
---|
1166 | Now, if we install demo, and extdemo: |
---|
1167 | |
---|
1168 | >>> ws = zc.buildout.easy_install.install( |
---|
1169 | ... ['demo==0.2'], dest, |
---|
1170 | ... links=[link_server], index=link_server+'index/', |
---|
1171 | ... always_unzip=True) |
---|
1172 | GET 200 / |
---|
1173 | GET 404 /index/demo/ |
---|
1174 | GET 200 /index/ |
---|
1175 | GET 200 /demo-0.2-py2.4.egg |
---|
1176 | GET 404 /index/demoneeded/ |
---|
1177 | GET 200 /demoneeded-1.1.zip |
---|
1178 | GET 404 /index/setuptools/ |
---|
1179 | |
---|
1180 | >>> zc.buildout.easy_install.build( |
---|
1181 | ... 'extdemo', dest, |
---|
1182 | ... {'include-dirs': os.path.join(sample_buildout, 'include')}, |
---|
1183 | ... links=[link_server], index=link_server+'index/') |
---|
1184 | GET 404 /index/extdemo/ |
---|
1185 | GET 200 /extdemo-1.5.zip |
---|
1186 | ['/sample-install/extdemo-1.5-py2.4-linux-i686.egg'] |
---|
1187 | |
---|
1188 | Not only will we get eggs in our destination directory: |
---|
1189 | |
---|
1190 | >>> ls(dest) |
---|
1191 | d demo-0.2-py2.4.egg |
---|
1192 | d demoneeded-1.1-py2.4.egg |
---|
1193 | d extdemo-1.5-py2.4-linux-i686.egg |
---|
1194 | |
---|
1195 | But we'll get distributions in the cache directory: |
---|
1196 | |
---|
1197 | >>> ls(cache) |
---|
1198 | - demo-0.2-py2.4.egg |
---|
1199 | - demoneeded-1.1.zip |
---|
1200 | - extdemo-1.5.zip |
---|
1201 | |
---|
1202 | The cache directory contains uninstalled distributions, such as zipped |
---|
1203 | eggs or source distributions. |
---|
1204 | |
---|
1205 | Let's recreate our destination directory and clear the index cache: |
---|
1206 | |
---|
1207 | >>> remove(dest) |
---|
1208 | >>> dest = tmpdir('sample-install') |
---|
1209 | >>> zc.buildout.easy_install.clear_index_cache() |
---|
1210 | |
---|
1211 | Now when we install the distributions: |
---|
1212 | |
---|
1213 | >>> ws = zc.buildout.easy_install.install( |
---|
1214 | ... ['demo==0.2'], dest, |
---|
1215 | ... links=[link_server], index=link_server+'index/', |
---|
1216 | ... always_unzip=True) |
---|
1217 | GET 200 / |
---|
1218 | GET 404 /index/demo/ |
---|
1219 | GET 200 /index/ |
---|
1220 | GET 404 /index/demoneeded/ |
---|
1221 | GET 404 /index/setuptools/ |
---|
1222 | |
---|
1223 | >>> zc.buildout.easy_install.build( |
---|
1224 | ... 'extdemo', dest, |
---|
1225 | ... {'include-dirs': os.path.join(sample_buildout, 'include')}, |
---|
1226 | ... links=[link_server], index=link_server+'index/') |
---|
1227 | GET 404 /index/extdemo/ |
---|
1228 | ['/sample-install/extdemo-1.5-py2.4-linux-i686.egg'] |
---|
1229 | |
---|
1230 | >>> ls(dest) |
---|
1231 | d demo-0.2-py2.4.egg |
---|
1232 | d demoneeded-1.1-py2.4.egg |
---|
1233 | d extdemo-1.5-py2.4-linux-i686.egg |
---|
1234 | |
---|
1235 | Note that we didn't download the distributions from the link server. |
---|
1236 | |
---|
1237 | If we remove the restriction on demo, we'll download a newer version |
---|
1238 | from the link server: |
---|
1239 | |
---|
1240 | >>> ws = zc.buildout.easy_install.install( |
---|
1241 | ... ['demo'], dest, |
---|
1242 | ... links=[link_server], index=link_server+'index/', |
---|
1243 | ... always_unzip=True) |
---|
1244 | GET 200 /demo-0.3-py2.4.egg |
---|
1245 | |
---|
1246 | Normally, the download cache is the preferred source of downloads, but |
---|
1247 | not the only one. |
---|
1248 | |
---|
1249 | Installing solely from a download cache |
---|
1250 | --------------------------------------- |
---|
1251 | |
---|
1252 | A download cache can be used as the basis of application source |
---|
1253 | releases. In an application source release, we want to distribute an |
---|
1254 | application that can be built without making any network accesses. In |
---|
1255 | this case, we distribute a download cache and tell the easy_install |
---|
1256 | module to install from the download cache only, without making network |
---|
1257 | accesses. The install_from_cache function can be used to signal that |
---|
1258 | packages should be installed only from the download cache. The |
---|
1259 | function always returns the previous setting. Calling it with no |
---|
1260 | arguments returns the current setting without changing it: |
---|
1261 | |
---|
1262 | >>> zc.buildout.easy_install.install_from_cache() |
---|
1263 | False |
---|
1264 | |
---|
1265 | Calling it with a boolean value changes the setting and returns the |
---|
1266 | previous setting: |
---|
1267 | |
---|
1268 | >>> zc.buildout.easy_install.install_from_cache(True) |
---|
1269 | False |
---|
1270 | |
---|
1271 | Let's remove demo-0.3-py2.4.egg from the cache, clear the index cache, |
---|
1272 | recreate the destination directory, and reinstall demo: |
---|
1273 | |
---|
1274 | >>> for f in os.listdir(cache): |
---|
1275 | ... if f.startswith('demo-0.3-'): |
---|
1276 | ... remove(cache, f) |
---|
1277 | |
---|
1278 | >>> zc.buildout.easy_install.clear_index_cache() |
---|
1279 | >>> remove(dest) |
---|
1280 | >>> dest = tmpdir('sample-install') |
---|
1281 | |
---|
1282 | >>> ws = zc.buildout.easy_install.install( |
---|
1283 | ... ['demo'], dest, |
---|
1284 | ... links=[link_server], index=link_server+'index/', |
---|
1285 | ... always_unzip=True) |
---|
1286 | |
---|
1287 | >>> ls(dest) |
---|
1288 | d demo-0.2-py2.4.egg |
---|
1289 | d demoneeded-1.1-py2.4.egg |
---|
1290 | |
---|
1291 | This time, we didn't download from or even query the link server. |
---|
1292 | |
---|
1293 | .. Disable the download cache: |
---|
1294 | |
---|
1295 | >>> zc.buildout.easy_install.download_cache(None) |
---|
1296 | '/cache' |
---|
1297 | |
---|
1298 | >>> zc.buildout.easy_install.install_from_cache(False) |
---|
1299 | True |
---|