easy_install.txt 42 KB
Newer Older
1 2
Python API for egg and script installation
==========================================
3

4 5 6
The easy_install module provides some functions to provide support for
egg and script installation.  It provides functionality at the python
level that is similar to easy_install, with a few exceptions:
7 8 9 10

- By default, we look for new packages *and* the packages that
  they depend on.  This is somewhat like (and uses) the --upgrade
  option of easy_install, except that we also upgrade required
11
  packages.
12 13 14 15 16 17 18 19 20

- If the highest-revision package satisfying a specification is
  already present, then we don't try to get another one.  This saves a
  lot of search time in the common case that packages are pegged to
  specific versions.

- If there is a develop egg that satisfies a requirement, we don't
  look for additional distributions.  We always give preference to
  develop eggs.
21

22 23
- Distutils options for building extensions can be passed.

24 25 26 27
Distribution installation
-------------------------

The easy_install module provides a function, install, for installing one
28 29
or more packages and their dependencies.  The install function takes 2
positional arguments:
30

31 32
- An iterable of setuptools requirement strings for the distributions
  to be installed, and
33

34 35 36
- A destination directory to install to and to satisfy requirements
  from.  The destination directory can be None, in which case, no new
  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 43
   A sequence of URLs, file names, or directories to look for
   links to distributions.
44

45 46 47 48
index
   The URL of an index server, or almost any other valid URL. :)

   If not specified, the Python Package Index,
49
   http://pypi.python.org/simple/, is used.  You can specify an
50 51 52
   alternate index with this option.  If you use the links option and
   if the links point to the needed distributions, then the index can
   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
Fred Drake's avatar
Fred Drake committed
57
   A path to a Python executable.  Distributions will be installed
58 59 60 61 62 63 64 65 66 67
   using this executable and will be for the matching Python version.

path
   A list of additional directories to search for locally-installed
   distributions.

always_unzip
   A flag indicating that newly-downloaded distributions should be
   directories even if they could be installed as zip files.

68
working_set
69
   An existing working set to be augmented with additional
70 71 72 73
   distributions, if necessary to satisfy requirements.  This allows
   you to call install multiple times, if necessary, to gather
   multiple sets of requirements.

74
newest
75
   A boolean value indicating whether to search for new distributions
76 77 78 79 80
   when already-installed distributions meet the requirement.  When
   this is true, the default, and when the destination directory is
   not None, then the install function will search for the newest
   distributions that satisfy the requirements.

Jim Fulton's avatar
Jim Fulton committed
81 82 83 84 85
versions
   A dictionary mapping project names to version numbers to be used
   when selecting distributions.  This can be used to specify a set of
   distribution versions independent of other requirements.

86 87 88 89 90 91
use_dependency_links
   A flag indicating whether to search for dependencies using the
   setup dependency_links metadata or not. If true, links are searched
   for using dependency_links in preference to other
   locations. Defaults to true.

92 93 94 95 96
relative_paths
   Adjust egg paths so they are relative to the script path.  This
   allows scripts to work when scripts and eggs are moved, as long as
   they are both moved in the same way.

97 98 99 100 101 102 103
The install method returns a working set containing the distributions
needed to meet the given requirements.

We have a link server that has a number of eggs:

    >>> print get(link_server),
    <html><body>
104
    <a href="bigdemo-0.1-py2.4.egg">bigdemo-0.1-py2.4.egg</a><br>
105 106 107
    <a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br>
    <a href="demo-0.2-py2.4.egg">demo-0.2-py2.4.egg</a><br>
    <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 110
    <a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br>
    <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 114 115 116
    <a href="index/">index/</a><br>
    <a href="other-1.0-py2.4.egg">other-1.0-py2.4.egg</a><br>
    </body></html>

Fred Drake's avatar
Fred Drake committed
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 122 123
    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo==0.2'], dest,
    ...     links=[link_server], index=link_server+'index/')
124

125 126
We requested version 0.2 of the demo distribution to be installed into
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 129 130 131 132 133 134 135 136
index directory as a package index.

The working set contains the distributions we retrieved.

    >>> for dist in ws:
    ...     print dist
    demo 0.2
    demoneeded 1.1

137 138
We got demoneeded because it was a dependency of demo.

139 140 141
And the actual eggs were added to the eggs directory.

    >>> ls(dest)
142 143
    -  demo-0.2-py2.4.egg
    -  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 149 150 151 152 153 154

    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], dest, links=[link_server], index=link_server+'index/',
    ...     newest=False)
    >>> ls(dest)
    -  demo-0.2-py2.4.egg
    -  demoneeded-1.1-py2.4.egg

155
If we leave off the newest option, we'll get an update for demo:
156 157 158

    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], dest, links=[link_server], index=link_server+'index/')
159
    >>> ls(dest)
160 161 162
    -  demo-0.2-py2.4.egg
    -  demo-0.3-py2.4.egg
    -  demoneeded-1.1-py2.4.egg
163

164
Note that we didn't get the newest versions available.  There were
165 166
release candidates for newer versions of both packages. By default,
final releases are preferred.  We can change this behavior using the
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
prefer_final function:

    >>> zc.buildout.easy_install.prefer_final(False)
    True

The old setting is returned.

    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], dest, links=[link_server], index=link_server+'index/')
    >>> for dist in ws:
    ...     print dist
    demo 0.4c1
    demoneeded 1.2c1

    >>> ls(dest)
    -  demo-0.2-py2.4.egg
    -  demo-0.3-py2.4.egg
    -  demo-0.4c1-py2.4.egg
    -  demoneeded-1.1-py2.4.egg
    -  demoneeded-1.2c1-py2.4.egg

Let's put the setting back to the default.

    >>> zc.buildout.easy_install.prefer_final(True)
    False

193 194
We can supply additional distributions.  We can also supply
specifications for distributions that would normally be found via
195
dependencies.  We might do this to specify a specific version.
196 197 198 199 200 201 202 203 204 205 206 207

    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo', 'other', 'demoneeded==1.0'], dest,
    ...     links=[link_server], index=link_server+'index/')

    >>> for dist in ws:
    ...     print dist
    demo 0.3
    other 1.0
    demoneeded 1.0

    >>> ls(dest)
208 209
    -  demo-0.2-py2.4.egg
    -  demo-0.3-py2.4.egg
210
    -  demo-0.4c1-py2.4.egg
211 212
    -  demoneeded-1.0-py2.4.egg
    -  demoneeded-1.1-py2.4.egg
213
    -  demoneeded-1.2c1-py2.4.egg
Jim Fulton's avatar
Jim Fulton committed
214
    d  other-1.0-py2.4.egg
215

216 217
We can request that eggs be unzipped even if they are zip safe.  This
can be useful when debugging.
218

219 220
    >>> rmdir(dest)
    >>> dest = tmpdir('sample-install')
221 222
    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], dest, links=[link_server], index=link_server+'index/',
223
    ...     always_unzip=True)
224 225

    >>> ls(dest)
226 227
    d  demo-0.3-py2.4.egg
    d  demoneeded-1.1-py2.4.egg
228

229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
    >>> rmdir(dest)
    >>> dest = tmpdir('sample-install')
    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], dest, links=[link_server], index=link_server+'index/',
    ...     always_unzip=False)

    >>> ls(dest)
    -  demo-0.3-py2.4.egg
    -  demoneeded-1.1-py2.4.egg

We can also set a default by calling the always_unzip function:

    >>> zc.buildout.easy_install.always_unzip(True)
    False

The old default is returned:

    >>> rmdir(dest)
    >>> dest = tmpdir('sample-install')
    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], dest, links=[link_server], index=link_server+'index/')

    >>> ls(dest)
    d  demo-0.3-py2.4.egg
    d  demoneeded-1.1-py2.4.egg


    >>> zc.buildout.easy_install.always_unzip(False)
    True

    >>> rmdir(dest)
    >>> dest = tmpdir('sample-install')
    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], dest, links=[link_server], index=link_server+'index/')

    >>> ls(dest)
    -  demo-0.3-py2.4.egg
    -  demoneeded-1.1-py2.4.egg

268 269
    >>> rmdir(dest)
    >>> dest = tmpdir('sample-install')
270 271
    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], dest, links=[link_server], index=link_server+'index/',
272
    ...     always_unzip=True)
273 274 275

    >>> ls(dest)
    d  demo-0.3-py2.4.egg
276 277
    d  demoneeded-1.1-py2.4.egg

278
Specifying version information independent of requirements
Jim Fulton's avatar
Jim Fulton committed
279
----------------------------------------------------------
Jim Fulton's avatar
Jim Fulton committed
280

281
Sometimes it's useful to specify version information independent of
Jim Fulton's avatar
Jim Fulton committed
282 283 284 285 286 287 288 289 290 291 292 293 294 295
normal requirements specifications.  For example, a buildout may need
to lock down a set of versions, without having to put put version
numbers in setup files or part definitions.  If a dictionary is passed
to the install function, mapping project names to version numbers,
then the versions numbers will be used.

    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], dest, links=[link_server], index=link_server+'index/',
    ...     versions = dict(demo='0.2', demoneeded='1.0'))
    >>> [d.version for d in ws]
    ['0.2', '1.0']

In this example, we specified a version for demoneeded, even though we
didn't define a requirement for it.  The versions specified apply to
296
dependencies as well as the specified requirements.
Jim Fulton's avatar
Jim Fulton committed
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315

If we specify a version that's incompatible with a requirement, then
we'll get an error:

    >>> from zope.testing.loggingsupport import InstalledHandler
    >>> handler = InstalledHandler('zc.buildout.easy_install')
    >>> import logging
    >>> logging.getLogger('zc.buildout.easy_install').propagate = False

    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo >0.2'], dest, links=[link_server],
    ...     index=link_server+'index/',
    ...     versions = dict(demo='0.2', demoneeded='1.0'))
    Traceback (most recent call last):
    ...
    IncompatibleVersionError: Bad version 0.2

    >>> print handler
    zc.buildout.easy_install DEBUG
316
      Installing 'demo >0.2'.
Jim Fulton's avatar
Jim Fulton committed
317
    zc.buildout.easy_install ERROR
318
      The version, 0.2, is not consistent with the requirement, 'demo>0.2'.
Jim Fulton's avatar
Jim Fulton committed
319 320 321

    >>> handler.clear()

322
If no versions are specified, a debugging message will be output
Jim Fulton's avatar
Jim Fulton committed
323 324 325 326 327 328 329 330
reporting that a version was picked automatically:

    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], dest, links=[link_server], index=link_server+'index/',
    ...     )

    >>> print handler
    zc.buildout.easy_install DEBUG
331
      Installing 'demo'.
Jim Fulton's avatar
Jim Fulton committed
332
    zc.buildout.easy_install DEBUG
333
      We have the best distribution that satisfies 'demo'.
Jim Fulton's avatar
Jim Fulton committed
334
    zc.buildout.easy_install DEBUG
335
      Picked: demo = 0.3
Jim Fulton's avatar
Jim Fulton committed
336
    zc.buildout.easy_install DEBUG
337 338 339 340 341 342 343
      Getting required 'demoneeded'
    zc.buildout.easy_install DEBUG
        required by demo 0.3.
    zc.buildout.easy_install DEBUG
      We have the best distribution that satisfies 'demoneeded'.
    zc.buildout.easy_install DEBUG
      Picked: demoneeded = 1.1
Jim Fulton's avatar
Jim Fulton committed
344 345 346 347

    >>> handler.uninstall()
    >>> logging.getLogger('zc.buildout.easy_install').propagate = True

Jim Fulton's avatar
Jim Fulton committed
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
We can request that we get an error if versions are picked:

    >>> zc.buildout.easy_install.allow_picked_versions(False)
    True

(The old setting is returned.)

    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], dest, links=[link_server], index=link_server+'index/',
    ...     )
    Traceback (most recent call last):
    ...
    UserError: Picked: demo = 0.3

    >>> zc.buildout.easy_install.allow_picked_versions(True)
    False

365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
The function default_versions can be used to get and set default
version information to be used when no version information is passes.
If called with an argument, it sets the default versions:

    >>> zc.buildout.easy_install.default_versions(dict(demoneeded='1'))
    {}

It always returns the previous default versions.  If called without an
argument, it simply returns the default versions without changing
them:

    >>> zc.buildout.easy_install.default_versions()
    {'demoneeded': '1'}

So with the default versions set, we'll get the requested version even
if the versions option isn't used:

    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], dest, links=[link_server], index=link_server+'index/',
    ...     )

    >>> [d.version for d in ws]
    ['0.3', '1.0']

Of course, we can unset the default versions by passing an empty
dictionary:

    >>> zc.buildout.easy_install.default_versions({})
    {'demoneeded': '1'}

    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], dest, links=[link_server], index=link_server+'index/',
    ...     )

    >>> [d.version for d in ws]
    ['0.3', '1.1']
401 402 403 404 405 406 407 408 409

Dependency links
----------------

Setuptools allows metadata that describes where to search for package
dependencies. This option is called dependency_links. Buildout has its
own notion of where to look for dependencies, but it also uses the
setup tools dependency_links information if it's available.

410
Let's demo this by creating an egg that specifies dependency_links.
411 412 413 414 415 416 417 418 419 420 421

To begin, let's create a new egg repository. This repository hold a
newer version of the 'demoneeded' egg than the sample repository does.

    >>> repoloc = tmpdir('repo')
    >>> from zc.buildout.tests import create_egg
    >>> create_egg('demoneeded', '1.2', repoloc)
    >>> link_server2 = start_server(repoloc)

Turn on logging on this server so that we can see when eggs are pulled
from it.
422

423 424 425 426 427 428 429 430
    >>> get(link_server2 + 'enable_server_logging')
    GET 200 /enable_server_logging
    ''

Now we can create an egg that specifies that its dependencies are
found on this server.

    >>> repoloc = tmpdir('repo2')
431
    >>> create_egg('hasdeps', '1.0', repoloc,
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
    ...            install_requires = "'demoneeded'",
    ...            dependency_links = [link_server2])

Let's add the egg to another repository.

    >>> link_server3 = start_server(repoloc)

Now let's install the egg.

    >>> example_dest = tmpdir('example-install')
    >>> workingset = zc.buildout.easy_install.install(
    ...     ['hasdeps'], example_dest,
    ...     links=[link_server3], index=link_server3+'index/')
    GET 200 /
    GET 200 /demoneeded-1.2-pyN.N.egg

The server logs show that the dependency was retrieved from the server
specified in the dependency_links.

Now let's see what happens if we provide two different ways to retrieve
the dependencies.

    >>> rmdir(example_dest)
    >>> example_dest = tmpdir('example-install')
    >>> workingset = zc.buildout.easy_install.install(
    ...     ['hasdeps'], example_dest, index=link_server+'index/',
    ...     links=[link_server, link_server3])
    GET 200 /
    GET 200 /demoneeded-1.2-pyN.N.egg

Once again the dependency is fetched from the logging server even
though it is also available from the non-logging server. This is
because the version on the logging server is newer and buildout
normally chooses the newest egg available.

If you wish to control where dependencies come from regardless of
dependency_links setup metadata use the 'use_dependency_links' option
to zc.buildout.easy_install.install().

    >>> rmdir(example_dest)
    >>> example_dest = tmpdir('example-install')
    >>> workingset = zc.buildout.easy_install.install(
    ...     ['hasdeps'], example_dest, index=link_server+'index/',
    ...     links=[link_server, link_server3],
    ...     use_dependency_links=False)

Notice that this time the dependency egg is not fetched from the
logging server. When you specify not to use dependency_links, eggs
will only be searched for using the links you explicitly provide.

Another way to control this option is with the
zc.buildout.easy_install.use_dependency_links() function. This
function sets the default behavior for the zc.buildout.easy_install()
function.

    >>> zc.buildout.easy_install.use_dependency_links(False)
    True

The function returns its previous setting.

    >>> rmdir(example_dest)
    >>> example_dest = tmpdir('example-install')
    >>> workingset = zc.buildout.easy_install.install(
    ...     ['hasdeps'], example_dest, index=link_server+'index/',
    ...     links=[link_server, link_server3])

It can be overridden by passing a keyword argument to the install
function.

    >>> rmdir(example_dest)
    >>> example_dest = tmpdir('example-install')
    >>> workingset = zc.buildout.easy_install.install(
    ...     ['hasdeps'], example_dest, index=link_server+'index/',
    ...     links=[link_server, link_server3],
    ...	    use_dependency_links=True)
    GET 200 /demoneeded-1.2-pyN.N.egg

To return the dependency_links behavior to normal call the function again.

    >>> zc.buildout.easy_install.use_dependency_links(True)
    False
    >>> rmdir(example_dest)
    >>> example_dest = tmpdir('example-install')
    >>> workingset = zc.buildout.easy_install.install(
    ...     ['hasdeps'], example_dest, index=link_server+'index/',
    ...     links=[link_server, link_server3])
    GET 200 /demoneeded-1.2-pyN.N.egg

520

521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
Script generation
-----------------

The easy_install module provides support for creating scripts from
eggs.  It provides a function similar to setuptools except that it
provides facilities for baking a script's path into the script.  This
has two advantages:

- The eggs to be used by a script are not chosen at run time, making
  startup faster and, more importantly, deterministic.

- The script doesn't have to import pkg_resources because the logic
  that pkg_resources would execute at run time is executed at
  script-creation time.

The scripts method can be used to generate scripts. Let's create a
destination directory for it to place them in:

    >>> import tempfile
540
    >>> bin = tmpdir('bin')
541 542 543 544

Now, we'll use the scripts method to generate scripts in this directory
from the demo egg:

545
    >>> import sys
546
    >>> scripts = zc.buildout.easy_install.scripts(
547
    ...     ['demo'], ws, sys.executable, bin)
548 549 550 551 552 553 554 555 556

the four arguments we passed were:

1. A sequence of distribution requirements.  These are of the same
   form as setuptools requirements.  Here we passed a single
   requirement, for the version 0.1 demo distribution.

2. A working set,

557
3. The Python executable to use, and
558

559 560
3. The destination directory.

561
The bin directory now contains a generated script:
562 563 564 565 566

    >>> ls(bin)
    -  demo

The return value is a list of the scripts generated:
567

Jim Fulton's avatar
Jim Fulton committed
568 569
    >>> import os, sys
    >>> if sys.platform == 'win32':
570
    ...     scripts == [os.path.join(bin, 'demo.exe'),
571
    ...                 os.path.join(bin, 'demo-script.py')]
Jim Fulton's avatar
Jim Fulton committed
572
    ... else:
573
    ...     scripts == [os.path.join(bin, 'demo')]
574 575
    True

576 577 578 579 580
Note that in Windows, 2 files are generated for each script.  A script
file, ending in '-script.py', and an exe file that allows the script
to be invoked directly without having to specify the Python
interpreter and without having to provide a '.py' suffix.

581 582
The demo script run the entry point defined in the demo egg:

583
    >>> cat(bin, 'demo') # doctest: +NORMALIZE_WHITESPACE
584
    #!/usr/local/bin/python2.4
585 586 587
    <BLANKLINE>
    import sys
    sys.path[0:0] = [
588 589
      '/sample-install/demo-0.3-py2.4.egg',
      '/sample-install/demoneeded-1.1-py2.4.egg',
590 591 592 593 594 595 596 597 598 599 600 601 602 603
      ]
    <BLANKLINE>
    import eggrecipedemo
    <BLANKLINE>
    if __name__ == '__main__':
        eggrecipedemo.main()

Some things to note:

- The demo and demoneeded eggs are added to the beginning of sys.path.

- The module for the script entry point is imported and the entry
  point, in this case, 'main', is run.

604 605 606 607 608 609 610 611 612
Rather than requirement strings, you can pass tuples containing 3
strings:

  - A script name,

  - A module,

  - An attribute expression for an entry point within the module.

613
For example, we could have passed entry point information directly
614 615 616 617
rather than passing a requirement:

    >>> scripts = zc.buildout.easy_install.scripts(
    ...     [('demo', 'eggrecipedemo', 'main')],
618
    ...     ws, sys.executable, bin)
619 620

    >>> cat(bin, 'demo') # doctest: +NORMALIZE_WHITESPACE
621
    #!/usr/local/bin/python2.4
622 623 624
    <BLANKLINE>
    import sys
    sys.path[0:0] = [
625 626
      '/sample-install/demo-0.3-py2.4.egg',
      '/sample-install/demoneeded-1.1-py2.4.egg',
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643
      ]
    <BLANKLINE>
    import eggrecipedemo
    <BLANKLINE>
    if __name__ == '__main__':
        eggrecipedemo.main()

Passing entry-point information directly is handy when using eggs (or
distributions) that don't declare their entry points, such as
distributions that aren't based on setuptools.

The interpreter keyword argument can be used to generate a script that can
be used to invoke the Python interactive interpreter with the path set
based on the working set.  This generated script can also be used to
run other scripts with the path set on the working set:

    >>> scripts = zc.buildout.easy_install.scripts(
644
    ...     ['demo'], ws, sys.executable, bin, interpreter='py')
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661


    >>> ls(bin)
    -  demo
    -  py

    >>> if sys.platform == 'win32':
    ...     scripts == [os.path.join(bin, 'demo.exe'),
    ...                 os.path.join(bin, 'demo-script.py'),
    ...                 os.path.join(bin, 'py.exe'),
    ...                 os.path.join(bin, 'py-script.py')]
    ... else:
    ...     scripts == [os.path.join(bin, 'demo'),
    ...                 os.path.join(bin, 'py')]
    True

The py script simply runs the Python interactive interpreter with
662 663
the path set:

664
    >>> cat(bin, 'py') # doctest: +NORMALIZE_WHITESPACE
665
    #!/usr/local/bin/python2.4
Jim Fulton's avatar
Jim Fulton committed
666
    <BLANKLINE>
667
    import sys
668
    <BLANKLINE>
669
    sys.path[0:0] = [
Jim Fulton's avatar
Jim Fulton committed
670 671
      '/sample-install/demo-0.3-pyN.N.egg',
      '/sample-install/demoneeded-1.1-pyN.N.egg',
672
      ]
673
    <BLANKLINE>
Jim Fulton's avatar
Jim Fulton committed
674 675
    _interactive = True
    if len(sys.argv) > 1:
Jim Fulton's avatar
Jim Fulton committed
676
        _options, _args = __import__("getopt").getopt(sys.argv[1:], 'ic:m:')
Jim Fulton's avatar
Jim Fulton committed
677 678 679 680 681 682
        _interactive = False
        for (_opt, _val) in _options:
            if _opt == '-i':
                _interactive = True
            elif _opt == '-c':
                exec _val
Jim Fulton's avatar
Jim Fulton committed
683 684 685 686 687
            elif _opt == '-m':
                sys.argv[1:] = _args
                _args = []
                __import__("runpy").run_module(
                     _val, {}, "__main__", alter_sys=True)
Jim Fulton's avatar
Jim Fulton committed
688 689 690
    <BLANKLINE>
        if _args:
            sys.argv[:] = _args
Jim Fulton's avatar
Jim Fulton committed
691
            __file__ = _args[0]
Jim Fulton's avatar
Jim Fulton committed
692
            del _options, _args
Jim Fulton's avatar
Jim Fulton committed
693
            execfile(__file__)
Jim Fulton's avatar
Jim Fulton committed
694 695
    <BLANKLINE>
    if _interactive:
Jim Fulton's avatar
Jim Fulton committed
696 697
        del _interactive
        __import__("code").interact(banner="", local=globals())
698 699

If invoked with a script name and arguments, it will run that script, instead.
700

Jim Fulton's avatar
Jim Fulton committed
701 702 703 704 705 706 707 708 709
    >>> write('ascript', '''
    ... "demo doc"
    ... print sys.argv
    ... print (__name__, __file__, __doc__)
    ... ''')
    >>> print system(join(bin, 'py')+' ascript a b c'),
    ['ascript', 'a', 'b', 'c']
    ('__main__', 'ascript', 'demo doc')

Jim Fulton's avatar
Jim Fulton committed
710 711 712 713 714 715 716 717 718
For Python 2.5 and higher, you can also use the -m option to run a
module:

    >>> print system(join(bin, 'py')+' -m pdb'),
    usage: pdb.py scriptfile [arg] ...

    >>> print system(join(bin, 'py')+' -m pdb what'),
    Error: what does not exist

719
An additional argument can be passed to define which scripts to install
720
and to provide script names. The argument is a dictionary mapping
721 722
original script names to new script names.

723
    >>> bin = tmpdir('bin2')
724
    >>> scripts = zc.buildout.easy_install.scripts(
725
    ...    ['demo'], ws, sys.executable, bin, dict(demo='run'))
Jim Fulton's avatar
Jim Fulton committed
726 727 728 729 730 731

    >>> if sys.platform == 'win32':
    ...     scripts == [os.path.join(bin, 'run.exe'),
    ...                 os.path.join(bin, 'run-script.py')]
    ... else:
    ...     scripts == [os.path.join(bin, 'run')]
732 733 734
    True
    >>> ls(bin)
    -  run
735

736 737
    >>> print system(os.path.join(bin, 'run')),
    3 1
738

739 740 741
Including extra paths in scripts
--------------------------------

742
We can pass a keyword argument, extra paths, to cause additional paths
743 744
to be included in the a generated script:

745
    >>> foo = tmpdir('foo')
746
    >>> scripts = zc.buildout.easy_install.scripts(
747
    ...    ['demo'], ws, sys.executable, bin, dict(demo='run'),
748
    ...    extra_paths=[foo])
749 750

    >>> cat(bin, 'run') # doctest: +NORMALIZE_WHITESPACE
751
    #!/usr/local/bin/python2.4
752 753 754
    <BLANKLINE>
    import sys
    sys.path[0:0] = [
755 756
      '/sample-install/demo-0.3-py2.4.egg',
      '/sample-install/demoneeded-1.1-py2.4.egg',
757
      '/foo',
758 759 760 761 762 763 764 765 766 767
      ]
    <BLANKLINE>
    import eggrecipedemo
    <BLANKLINE>
    if __name__ == '__main__':
        eggrecipedemo.main()

Providing script arguments
--------------------------

768 769
An "argument" keyword argument can be used to pass arguments to an
entry point.  The value passed is a source string to be placed between the
770 771 772
parentheses in the call:

    >>> scripts = zc.buildout.easy_install.scripts(
773
    ...    ['demo'], ws, sys.executable, bin, dict(demo='run'),
774 775 776
    ...    arguments='1, 2')

    >>> cat(bin, 'run') # doctest: +NORMALIZE_WHITESPACE
777
    #!/usr/local/bin/python2.4
778 779
    import sys
    sys.path[0:0] = [
780 781
      '/sample-install/demo-0.3-py2.4.egg',
      '/sample-install/demoneeded-1.1-py2.4.egg',
782 783 784 785 786 787 788
      ]
    <BLANKLINE>
    import eggrecipedemo
    <BLANKLINE>
    if __name__ == '__main__':
        eggrecipedemo.main(1, 2)

789 790 791 792 793 794 795
Passing initialization code
---------------------------

You can also pass script initialization code:

    >>> scripts = zc.buildout.easy_install.scripts(
    ...    ['demo'], ws, sys.executable, bin, dict(demo='run'),
796
    ...    arguments='1, 2',
797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813
    ...    initialization='import os\nos.chdir("foo")')

    >>> cat(bin, 'run') # doctest: +NORMALIZE_WHITESPACE
    #!/usr/local/bin/python2.4
    import sys
    sys.path[0:0] = [
      '/sample-install/demo-0.3-py2.4.egg',
      '/sample-install/demoneeded-1.1-py2.4.egg',
      ]
    <BLANKLINE>
    import os
    os.chdir("foo")
    <BLANKLINE>
    import eggrecipedemo
    <BLANKLINE>
    if __name__ == '__main__':
        eggrecipedemo.main(1, 2)
814

815 816 817 818 819 820 821 822 823
Relative paths
--------------

Sometimes, you want to be able to move a buildout directory around and
have scripts still work without having to rebuild them.  We can
control this using the relative_paths option to install.  You need
to pass a common base directory of the scripts and eggs:

    >>> bo = tmpdir('bo')
824
    >>> ba = tmpdir('ba')
825 826 827 828 829 830 831 832 833 834
    >>> mkdir(bo, 'eggs')
    >>> mkdir(bo, 'bin')
    >>> mkdir(bo, 'other')

    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], join(bo, 'eggs'), links=[link_server],
    ...     index=link_server+'index/')

    >>> scripts = zc.buildout.easy_install.scripts(
    ...    ['demo'], ws, sys.executable, join(bo, 'bin'), dict(demo='run'),
835
    ...    extra_paths=[ba, join(bo, 'bar')],
836 837 838 839 840 841 842 843 844
    ...    interpreter='py',
    ...    relative_paths=bo)

    >>> cat(bo, 'bin', 'run')
    #!/usr/local/bin/python2.4
    <BLANKLINE>
    import os
    <BLANKLINE>
    join = os.path.join
Jim Fulton's avatar
Jim Fulton committed
845
    base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
846
    base = os.path.dirname(base)
847 848 849
    <BLANKLINE>
    import sys
    sys.path[0:0] = [
850 851
      join(base, 'eggs/demo-0.3-pyN.N.egg'),
      join(base, 'eggs/demoneeded-1.1-pyN.N.egg'),
852
      '/ba',
853
      join(base, 'bar'),
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876
      ]
    <BLANKLINE>
    import eggrecipedemo
    <BLANKLINE>
    if __name__ == '__main__':
        eggrecipedemo.main()

Note that the extra path we specified that was outside the directory
passed as relative_paths wasn't converted to a relative path.

Of course, running the script works:

    >>> print system(join(bo, 'bin', 'run')),
    3 1

We specified an interpreter and its paths are adjusted too:

    >>> cat(bo, 'bin', 'py')
    #!/usr/local/bin/python2.4
    <BLANKLINE>
    import os
    <BLANKLINE>
    join = os.path.join
Jim Fulton's avatar
Jim Fulton committed
877
    base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
878
    base = os.path.dirname(base)
879 880 881 882
    <BLANKLINE>
    import sys
    <BLANKLINE>
    sys.path[0:0] = [
883 884
      join(base, 'eggs/demo-0.3-pyN.N.egg'),
      join(base, 'eggs/demoneeded-1.1-pyN.N.egg'),
885
      '/ba',
886
      join(base, 'bar'),
887 888 889 890
      ]
    <BLANKLINE>
    _interactive = True
    if len(sys.argv) > 1:
Jim Fulton's avatar
Jim Fulton committed
891
        _options, _args = __import__("getopt").getopt(sys.argv[1:], 'ic:m:')
892 893 894 895 896 897
        _interactive = False
        for (_opt, _val) in _options:
            if _opt == '-i':
                _interactive = True
            elif _opt == '-c':
                exec _val
Jim Fulton's avatar
Jim Fulton committed
898 899 900 901 902
            elif _opt == '-m':
                sys.argv[1:] = _args
                _args = []
                __import__("runpy").run_module(
                     _val, {}, "__main__", alter_sys=True)
903 904 905
    <BLANKLINE>
        if _args:
            sys.argv[:] = _args
Jim Fulton's avatar
Jim Fulton committed
906
            __file__ = _args[0]
Jim Fulton's avatar
Jim Fulton committed
907
            del _options, _args
Jim Fulton's avatar
Jim Fulton committed
908
            execfile(__file__)
909 910
    <BLANKLINE>
    if _interactive:
Jim Fulton's avatar
Jim Fulton committed
911 912
        del _interactive
        __import__("code").interact(banner="", local=globals())
913

914

915 916
Handling custom build options for extensions provided in source distributions
-----------------------------------------------------------------------------
917 918

Sometimes, we need to control how extension modules are built.  The
919
build function provides this level of control.  It takes a single
920 921 922
package specification, downloads a source distribution, and builds it
with specified custom build options.

923
The build function takes 3 positional arguments:
924 925

spec
926
   A package specification for a source distribution
927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944

dest
   A destination directory

build_ext
   A dictionary of options to be passed to the distutils build_ext
   command when building extensions.

It supports a number of optional keyword arguments:

links
   a sequence of URLs, file names, or directories to look for
   links to distributions,

index
   The URL of an index server, or almost any other valid URL. :)

   If not specified, the Python Package Index,
945
   http://pypi.python.org/simple/, is used.  You can specify an
946 947 948
   alternate index with this option.  If you use the links option and
   if the links point to the needed distributions, then the index can
   be anything and will be largely ignored.  In the examples, here,
949
   we'll just point to an empty directory on our link server.  This
950 951 952
   will make our examples run a little bit faster.

executable
953
   A path to a Python executable.  Distributions will be installed
954 955 956 957 958 959
   using this executable and will be for the matching Python version.

path
   A list of additional directories to search for locally-installed
   distributions.

960
newest
961
   A boolean value indicating whether to search for new distributions
962 963 964 965 966
   when already-installed distributions meet the requirement.  When
   this is true, the default, and when the destination directory is
   not None, then the install function will search for the newest
   distributions that satisfy the requirements.

Jim Fulton's avatar
Jim Fulton committed
967 968 969 970 971
versions
   A dictionary mapping project names to version numbers to be used
   when selecting distributions.  This can be used to specify a set of
   distribution versions independent of other requirements.

972 973 974 975 976 977 978 979 980 981 982 983

Our link server included a source distribution that includes a simple
extension, extdemo.c::

  #include <Python.h>
  #include <extdemo.h>

  static PyMethodDef methods[] = {};

  PyMODINIT_FUNC
  initextdemo(void)
  {
984 985 986 987 988 989 990
      PyObject *m;
      m = Py_InitModule3("extdemo", methods, "");
  #ifdef TWO
      PyModule_AddObject(m, "val", PyInt_FromLong(2));
  #else
      PyModule_AddObject(m, "val", PyInt_FromLong(EXTDEMO));
  #endif
991 992
  }

993
The extension depends on a system-dependent include file, extdemo.h,
994 995 996 997 998
that defines a constant, EXTDEMO, that is exposed by the extension.

We'll add an include directory to our sample buildout and add the
needed include file to it:

999 1000 1001 1002 1003
    >>> mkdir('include')
    >>> write('include', 'extdemo.h',
    ... """
    ... #define EXTDEMO 42
    ... """)
1004 1005 1006 1007 1008

Now, we can use the build function to create an egg from the source
distribution:

    >>> zc.buildout.easy_install.build(
1009
    ...   'extdemo', dest,
1010 1011
    ...   {'include-dirs': os.path.join(sample_buildout, 'include')},
    ...   links=[link_server], index=link_server+'index/')
1012
    ['/sample-install/extdemo-1.4-py2.4-unix-i686.egg']
1013

1014
The function returns the list of eggs
1015 1016 1017 1018

Now if we look in our destination directory, we see we have an extdemo egg:

    >>> ls(dest)
Jim Fulton's avatar
Jim Fulton committed
1019
    -  demo-0.2-py2.4.egg
1020
    d  demo-0.3-py2.4.egg
Jim Fulton's avatar
Jim Fulton committed
1021
    -  demoneeded-1.0-py2.4.egg
1022
    d  demoneeded-1.1-py2.4.egg
1023
    d  extdemo-1.4-py2.4-unix-i686.egg
1024

1025 1026 1027 1028 1029
Let's update our link server with a new version of extdemo:

    >>> update_extdemo()
    >>> print get(link_server),
    <html><body>
1030
    <a href="bigdemo-0.1-py2.4.egg">bigdemo-0.1-py2.4.egg</a><br>
1031 1032 1033
    <a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br>
    <a href="demo-0.2-py2.4.egg">demo-0.2-py2.4.egg</a><br>
    <a href="demo-0.3-py2.4.egg">demo-0.3-py2.4.egg</a><br>
1034
    <a href="demo-0.4c1-py2.4.egg">demo-0.4c1-py2.4.egg</a><br>
1035 1036
    <a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br>
    <a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br>
1037
    <a href="demoneeded-1.2c1.zip">demoneeded-1.2c1.zip</a><br>
1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
    <a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br>
    <a href="extdemo-1.5.zip">extdemo-1.5.zip</a><br>
    <a href="index/">index/</a><br>
    <a href="other-1.0-py2.4.egg">other-1.0-py2.4.egg</a><br>
    </body></html>

The easy_install caches information about servers to reduce network
access. To see the update, we have to call the clear_index_cache
function to clear the index cache:

    >>> zc.buildout.easy_install.clear_index_cache()

If we run build with newest set to False, we won't get an update:

    >>> zc.buildout.easy_install.build(
1053
    ...   'extdemo', dest,
1054 1055 1056
    ...   {'include-dirs': os.path.join(sample_buildout, 'include')},
    ...   links=[link_server], index=link_server+'index/',
    ...   newest=False)
1057
    ['/sample-install/extdemo-1.4-py2.4-linux-i686.egg']
1058 1059

    >>> ls(dest)
Jim Fulton's avatar
Jim Fulton committed
1060
    -  demo-0.2-py2.4.egg
1061
    d  demo-0.3-py2.4.egg
Jim Fulton's avatar
Jim Fulton committed
1062
    -  demoneeded-1.0-py2.4.egg
1063 1064 1065 1066 1067 1068 1069
    d  demoneeded-1.1-py2.4.egg
    d  extdemo-1.4-py2.4-unix-i686.egg

But if we run it with the default True setting for newest, then we'll
get an updated egg:

    >>> zc.buildout.easy_install.build(
1070
    ...   'extdemo', dest,
1071 1072
    ...   {'include-dirs': os.path.join(sample_buildout, 'include')},
    ...   links=[link_server], index=link_server+'index/')
1073
    ['/sample-install/extdemo-1.5-py2.4-unix-i686.egg']
1074

Jim Fulton's avatar
Jim Fulton committed
1075 1076
    >>> ls(dest)
    -  demo-0.2-py2.4.egg
1077
    d  demo-0.3-py2.4.egg
Jim Fulton's avatar
Jim Fulton committed
1078
    -  demoneeded-1.0-py2.4.egg
1079 1080 1081 1082
    d  demoneeded-1.1-py2.4.egg
    d  extdemo-1.4-py2.4-unix-i686.egg
    d  extdemo-1.5-py2.4-unix-i686.egg

Jim Fulton's avatar
Jim Fulton committed
1083 1084
The versions option also influences the versions used.  For example,
if we specify a version for extdemo, then that will be used, even
1085
though it isn't the newest.  Let's clean out the destination directory
Jim Fulton's avatar
Jim Fulton committed
1086 1087 1088 1089 1090 1091 1092
first:

    >>> import os
    >>> for name in os.listdir(dest):
    ...     remove(dest, name)

    >>> zc.buildout.easy_install.build(
1093
    ...   'extdemo', dest,
Jim Fulton's avatar
Jim Fulton committed
1094 1095 1096
    ...   {'include-dirs': os.path.join(sample_buildout, 'include')},
    ...   links=[link_server], index=link_server+'index/',
    ...   versions=dict(extdemo='1.4'))
1097
    ['/sample-install/extdemo-1.4-py2.4-unix-i686.egg']
Jim Fulton's avatar
Jim Fulton committed
1098 1099 1100

    >>> ls(dest)
    d  extdemo-1.4-py2.4-unix-i686.egg
1101

1102 1103 1104 1105 1106
Handling custom build options for extensions in develop eggs
------------------------------------------------------------

The develop function is similar to the build function, except that,
rather than building an egg from a source directory containing a
1107
setup.py script.
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124

The develop function takes 2 positional arguments:

setup
   The path to a setup script, typically named "setup.py", or a
   directory containing a setup.py script.

dest
   The directory to install the egg link to

It supports some optional keyword argument:

build_ext
   A dictionary of options to be passed to the distutils build_ext
   command when building extensions.

executable
1125
   A path to a Python executable.  Distributions will be installed
1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140
   using this executable and will be for the matching Python version.

We have a local directory containing the extdemo source:

    >>> ls(extdemo)
    -  MANIFEST
    -  MANIFEST.in
    -  README
    -  extdemo.c
    -  setup.py

Now, we can use the develop function to create a develop egg from the source
distribution:

    >>> zc.buildout.easy_install.develop(
1141
    ...   extdemo, dest,
1142 1143 1144 1145 1146 1147 1148 1149 1150
    ...   {'include-dirs': os.path.join(sample_buildout, 'include')})
    '/sample-install/extdemo.egg-link'

The name of the egg link created is returned.

Now if we look in our destination directory, we see we have an extdemo
egg link:

    >>> ls(dest)
Jim Fulton's avatar
Jim Fulton committed
1151
    d  extdemo-1.4-py2.4-unix-i686.egg
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164
    -  extdemo.egg-link

And that the source directory contains the compiled extension:

    >>> ls(extdemo)
    -  MANIFEST
    -  MANIFEST.in
    -  README
    d  build
    -  extdemo.c
    d  extdemo.egg-info
    -  extdemo.so
    -  setup.py
1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176

Download cache
--------------

Normally, when distributions are installed, if any processing is
needed, they are downloaded from the internet to a temporary directory
and then installed from there.  A download cache can be used to avoid
the download step.  This can be useful to reduce network access and to
create source distributions of an entire buildout.

A download cache is specified by calling the download_cache
function.  The function always returns the previous setting. If no
Jim Fulton's avatar
Jim Fulton committed
1177
argument is passed, then the setting is unchanged.  If an argument is
1178 1179 1180 1181 1182 1183 1184 1185 1186
passed, the download cache is set to the given path, which must point
to an existing directory.  Passing None clears the cache setting.

To see this work, we'll create a directory and set it as the cache
directory:

    >>> cache = tmpdir('cache')
    >>> zc.buildout.easy_install.download_cache(cache)

Jim Fulton's avatar
Jim Fulton committed
1187
We'll recreate our destination directory:
1188 1189 1190 1191 1192 1193

    >>> remove(dest)
    >>> dest = tmpdir('sample-install')

We'd like to see what is being fetched from the server, so we'll
enable server logging:
1194

1195 1196 1197 1198 1199 1200 1201 1202
    >>> get(link_server+'enable_server_logging')
    GET 200 /enable_server_logging
    ''

Now, if we install demo, and extdemo:

    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo==0.2'], dest,
1203
    ...     links=[link_server], index=link_server+'index/',
1204 1205 1206 1207 1208 1209 1210 1211 1212 1213
    ...     always_unzip=True)
    GET 200 /
    GET 404 /index/demo/
    GET 200 /index/
    GET 200 /demo-0.2-py2.4.egg
    GET 404 /index/demoneeded/
    GET 200 /demoneeded-1.1.zip
    GET 404 /index/setuptools/

    >>> zc.buildout.easy_install.build(
1214
    ...   'extdemo', dest,
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235
    ...   {'include-dirs': os.path.join(sample_buildout, 'include')},
    ...   links=[link_server], index=link_server+'index/')
    GET 404 /index/extdemo/
    GET 200 /extdemo-1.5.zip
    ['/sample-install/extdemo-1.5-py2.4-linux-i686.egg']

Not only will we get eggs in our destination directory:

    >>> ls(dest)
    d  demo-0.2-py2.4.egg
    d  demoneeded-1.1-py2.4.egg
    d  extdemo-1.5-py2.4-linux-i686.egg

But we'll get distributions in the cache directory:

    >>> ls(cache)
    -  demo-0.2-py2.4.egg
    -  demoneeded-1.1.zip
    -  extdemo-1.5.zip

The cache directory contains uninstalled distributions, such as zipped
1236
eggs or source distributions.
1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247

Let's recreate our destination directory and clear the index cache:

    >>> remove(dest)
    >>> dest = tmpdir('sample-install')
    >>> zc.buildout.easy_install.clear_index_cache()

Now when we install the distributions:

    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo==0.2'], dest,
1248
    ...     links=[link_server], index=link_server+'index/',
1249 1250 1251 1252 1253 1254 1255 1256
    ...     always_unzip=True)
    GET 200 /
    GET 404 /index/demo/
    GET 200 /index/
    GET 404 /index/demoneeded/
    GET 404 /index/setuptools/

    >>> zc.buildout.easy_install.build(
1257
    ...   'extdemo', dest,
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
    ...   {'include-dirs': os.path.join(sample_buildout, 'include')},
    ...   links=[link_server], index=link_server+'index/')
    GET 404 /index/extdemo/
    ['/sample-install/extdemo-1.5-py2.4-linux-i686.egg']

    >>> ls(dest)
    d  demo-0.2-py2.4.egg
    d  demoneeded-1.1-py2.4.egg
    d  extdemo-1.5-py2.4-linux-i686.egg

Note that we didn't download the distributions from the link server.

1270 1271 1272 1273 1274
If we remove the restriction on demo, we'll download a newer version
from the link server:

    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], dest,
1275
    ...     links=[link_server], index=link_server+'index/',
1276 1277 1278
    ...     always_unzip=True)
    GET 200 /demo-0.3-py2.4.egg

1279
Normally, the download cache is the preferred source of downloads, but
1280 1281 1282
not the only one.

Installing solely from a download cache
1283
---------------------------------------
1284

1285
A download cache can be used as the basis of application source
1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306
releases.  In an application source release, we want to distribute an
application that can be built without making any network accesses.  In
this case, we distribute a download cache and tell the easy_install
module to install from the download cache only, without making network
accesses.  The install_from_cache function can be used to signal that
packages should be installed only from the download cache.  The
function always returns the previous setting.  Calling it with no
arguments returns the current setting without changing it:

    >>> zc.buildout.easy_install.install_from_cache()
    False

Calling it with a boolean value changes the setting and returns the
previous setting:

    >>> zc.buildout.easy_install.install_from_cache(True)
    False

Let's remove demo-0.3-py2.4.egg from the cache, clear the index cache,
recreate the destination directory, and reinstall demo:

1307 1308 1309 1310
    >>> for  f in os.listdir(cache):
    ...     if f.startswith('demo-0.3-'):
    ...         remove(cache, f)

1311 1312 1313 1314 1315 1316
    >>> zc.buildout.easy_install.clear_index_cache()
    >>> remove(dest)
    >>> dest = tmpdir('sample-install')

    >>> ws = zc.buildout.easy_install.install(
    ...     ['demo'], dest,
1317
    ...     links=[link_server], index=link_server+'index/',
1318 1319 1320 1321 1322 1323 1324 1325
    ...     always_unzip=True)

    >>> ls(dest)
    d  demo-0.2-py2.4.egg
    d  demoneeded-1.1-py2.4.egg

This time, we didn't download from or even query the link server.

1326 1327 1328 1329
.. Disable the download cache:

    >>> zc.buildout.easy_install.download_cache(None)
    '/cache'
1330 1331 1332

    >>> zc.buildout.easy_install.install_from_cache(False)
    True