PageRenderTime 38ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/src/zc/buildout/tests.py

https://github.com/koodaamo/buildout
Python | 3306 lines | 3265 code | 21 blank | 20 comment | 10 complexity | 17f211f52168eb2f48e7f7461bf54ebf MD5 | raw file
Possible License(s): GPL-2.0
  1. ##############################################################################
  2. #
  3. # Copyright (c) 2004-2009 Zope Foundation and Contributors.
  4. # All Rights Reserved.
  5. #
  6. # This software is subject to the provisions of the Zope Public License,
  7. # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
  8. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
  9. # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  10. # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
  11. # FOR A PARTICULAR PURPOSE.
  12. #
  13. ##############################################################################
  14. from zc.buildout.buildout import print_
  15. from zope.testing import renormalizing
  16. import doctest
  17. import manuel.capture
  18. import manuel.doctest
  19. import manuel.testing
  20. import os
  21. import pkg_resources
  22. import re
  23. import shutil
  24. import sys
  25. import tempfile
  26. import unittest
  27. import zc.buildout.easy_install
  28. import zc.buildout.testing
  29. import zipfile
  30. os_path_sep = os.path.sep
  31. if os_path_sep == '\\':
  32. os_path_sep *= 2
  33. def develop_w_non_setuptools_setup_scripts():
  34. """
  35. We should be able to deal with setup scripts that aren't setuptools based.
  36. >>> mkdir('foo')
  37. >>> write('foo', 'setup.py',
  38. ... '''
  39. ... from distutils.core import setup
  40. ... setup(name="foo")
  41. ... ''')
  42. >>> write('buildout.cfg',
  43. ... '''
  44. ... [buildout]
  45. ... develop = foo
  46. ... parts =
  47. ... ''')
  48. >>> print_(system(join('bin', 'buildout')), end='')
  49. Develop: '/sample-buildout/foo'
  50. >>> ls('develop-eggs')
  51. - foo.egg-link
  52. - zc.recipe.egg.egg-link
  53. """
  54. def develop_verbose():
  55. """
  56. We should be able to deal with setup scripts that aren't setuptools based.
  57. >>> mkdir('foo')
  58. >>> write('foo', 'setup.py',
  59. ... '''
  60. ... from setuptools import setup
  61. ... setup(name="foo")
  62. ... ''')
  63. >>> write('buildout.cfg',
  64. ... '''
  65. ... [buildout]
  66. ... develop = foo
  67. ... parts =
  68. ... ''')
  69. >>> print_(system(join('bin', 'buildout')+' -vv'), end='')
  70. ... # doctest: +ELLIPSIS
  71. Installing...
  72. Develop: '/sample-buildout/foo'
  73. ...
  74. Installed /sample-buildout/foo
  75. ...
  76. >>> ls('develop-eggs')
  77. - foo.egg-link
  78. - zc.recipe.egg.egg-link
  79. >>> print_(system(join('bin', 'buildout')+' -vvv'), end='')
  80. ... # doctest: +ELLIPSIS
  81. Installing...
  82. Develop: '/sample-buildout/foo'
  83. in: '/sample-buildout/foo'
  84. ... -q develop -mxN -d /sample-buildout/develop-eggs/...
  85. """
  86. def buildout_error_handling():
  87. r"""Buildout error handling
  88. Asking for a section that doesn't exist, yields a missing section error:
  89. >>> import os
  90. >>> os.chdir(sample_buildout)
  91. >>> import zc.buildout.buildout
  92. >>> buildout = zc.buildout.buildout.Buildout('buildout.cfg', [])
  93. >>> buildout['eek']
  94. Traceback (most recent call last):
  95. ...
  96. MissingSection: The referenced section, 'eek', was not defined.
  97. Asking for an option that doesn't exist, a MissingOption error is raised:
  98. >>> buildout['buildout']['eek']
  99. Traceback (most recent call last):
  100. ...
  101. MissingOption: Missing option: buildout:eek
  102. It is an error to create a variable-reference cycle:
  103. >>> write(sample_buildout, 'buildout.cfg',
  104. ... '''
  105. ... [buildout]
  106. ... parts =
  107. ... x = ${buildout:y}
  108. ... y = ${buildout:z}
  109. ... z = ${buildout:x}
  110. ... ''')
  111. >>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout')),
  112. ... end='')
  113. ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
  114. While:
  115. Initializing.
  116. Getting section buildout.
  117. Initializing section buildout.
  118. Getting option buildout:x.
  119. Getting option buildout:y.
  120. Getting option buildout:z.
  121. Getting option buildout:x.
  122. Error: Circular reference in substitutions.
  123. It is an error to use funny characters in variable refereces:
  124. >>> write(sample_buildout, 'buildout.cfg',
  125. ... '''
  126. ... [buildout]
  127. ... develop = recipes
  128. ... parts = data_dir debug
  129. ... x = ${bui$ldout:y}
  130. ... ''')
  131. >>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout')),
  132. ... end='')
  133. While:
  134. Initializing.
  135. Getting section buildout.
  136. Initializing section buildout.
  137. Getting option buildout:x.
  138. Error: The section name in substitution, ${bui$ldout:y},
  139. has invalid characters.
  140. >>> write(sample_buildout, 'buildout.cfg',
  141. ... '''
  142. ... [buildout]
  143. ... develop = recipes
  144. ... parts = data_dir debug
  145. ... x = ${buildout:y{z}
  146. ... ''')
  147. >>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout')),
  148. ... end='')
  149. While:
  150. Initializing.
  151. Getting section buildout.
  152. Initializing section buildout.
  153. Getting option buildout:x.
  154. Error: The option name in substitution, ${buildout:y{z},
  155. has invalid characters.
  156. and too have too many or too few colons:
  157. >>> write(sample_buildout, 'buildout.cfg',
  158. ... '''
  159. ... [buildout]
  160. ... develop = recipes
  161. ... parts = data_dir debug
  162. ... x = ${parts}
  163. ... ''')
  164. >>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout')),
  165. ... end='')
  166. While:
  167. Initializing.
  168. Getting section buildout.
  169. Initializing section buildout.
  170. Getting option buildout:x.
  171. Error: The substitution, ${parts},
  172. doesn't contain a colon.
  173. >>> write(sample_buildout, 'buildout.cfg',
  174. ... '''
  175. ... [buildout]
  176. ... develop = recipes
  177. ... parts = data_dir debug
  178. ... x = ${buildout:y:z}
  179. ... ''')
  180. >>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout')),
  181. ... end='')
  182. While:
  183. Initializing.
  184. Getting section buildout.
  185. Initializing section buildout.
  186. Getting option buildout:x.
  187. Error: The substitution, ${buildout:y:z},
  188. has too many colons.
  189. Al parts have to have a section:
  190. >>> write(sample_buildout, 'buildout.cfg',
  191. ... '''
  192. ... [buildout]
  193. ... parts = x
  194. ... ''')
  195. >>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout')),
  196. ... end='')
  197. While:
  198. Installing.
  199. Getting section x.
  200. Error: The referenced section, 'x', was not defined.
  201. and all parts have to have a specified recipe:
  202. >>> write(sample_buildout, 'buildout.cfg',
  203. ... '''
  204. ... [buildout]
  205. ... parts = x
  206. ...
  207. ... [x]
  208. ... foo = 1
  209. ... ''')
  210. >>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout')),
  211. ... end='')
  212. While:
  213. Installing.
  214. Error: Missing option: x:recipe
  215. """
  216. make_dist_that_requires_setup_py_template = """
  217. from setuptools import setup
  218. setup(name=%r, version=%r,
  219. install_requires=%r,
  220. )
  221. """
  222. def make_dist_that_requires(dest, name, requires=[], version=1, egg=''):
  223. os.mkdir(os.path.join(dest, name))
  224. open(os.path.join(dest, name, 'setup.py'), 'w').write(
  225. make_dist_that_requires_setup_py_template
  226. % (name, version, requires)
  227. )
  228. def show_who_requires_when_there_is_a_conflict():
  229. """
  230. It's a pain when we require eggs that have requirements that are
  231. incompatible. We want the error we get to tell us what is missing.
  232. Let's make a few develop distros, some of which have incompatible
  233. requirements.
  234. >>> make_dist_that_requires(sample_buildout, 'sampley',
  235. ... ['demoneeded ==1.0'])
  236. >>> make_dist_that_requires(sample_buildout, 'samplez',
  237. ... ['demoneeded ==1.1'])
  238. Now, let's create a buildout that requires y and z:
  239. >>> write('buildout.cfg',
  240. ... '''
  241. ... [buildout]
  242. ... parts = eggs
  243. ... develop = sampley samplez
  244. ... find-links = %(link_server)s
  245. ...
  246. ... [eggs]
  247. ... recipe = zc.recipe.egg
  248. ... eggs = sampley
  249. ... samplez
  250. ... ''' % globals())
  251. >>> print_(system(buildout), end='')
  252. Develop: '/sample-buildout/sampley'
  253. Develop: '/sample-buildout/samplez'
  254. Installing eggs.
  255. Getting distribution for 'demoneeded==1.1'.
  256. Got demoneeded 1.1.
  257. While:
  258. Installing eggs.
  259. Error: There is a version conflict.
  260. We already have: demoneeded 1.1
  261. but sampley 1 requires 'demoneeded==1.0'.
  262. Here, we see that sampley required an older version of demoneeded. What
  263. if we hadn't required sampley ourselves:
  264. >>> make_dist_that_requires(sample_buildout, 'samplea', ['sampleb'])
  265. >>> make_dist_that_requires(sample_buildout, 'sampleb',
  266. ... ['sampley', 'samplea'])
  267. >>> write('buildout.cfg',
  268. ... '''
  269. ... [buildout]
  270. ... parts = eggs
  271. ... develop = sampley samplez samplea sampleb
  272. ... find-links = %(link_server)s
  273. ...
  274. ... [eggs]
  275. ... recipe = zc.recipe.egg
  276. ... eggs = samplea
  277. ... samplez
  278. ... ''' % globals())
  279. If we use the verbose switch, we can see where requirements are coming from:
  280. >>> print_(system(buildout+' -v'), end='') # doctest: +ELLIPSIS
  281. Installing 'zc.buildout >=1.99', 'distribute'.
  282. We have a develop egg: zc.buildout 1.0.0
  283. We have the best distribution that satisfies 'distribute'.
  284. Picked: distribute = 0.6
  285. Develop: '/sample-buildout/sampley'
  286. Develop: '/sample-buildout/samplez'
  287. Develop: '/sample-buildout/samplea'
  288. Develop: '/sample-buildout/sampleb'
  289. ...Installing eggs.
  290. Installing 'samplea', 'samplez'.
  291. We have a develop egg: samplea 1
  292. We have a develop egg: samplez 1
  293. Getting required 'demoneeded==1.1'
  294. required by samplez 1.
  295. We have the distribution that satisfies 'demoneeded==1.1'.
  296. Getting required 'sampleb'
  297. required by samplea 1.
  298. We have a develop egg: sampleb 1
  299. Getting required 'sampley'
  300. required by sampleb 1.
  301. We have a develop egg: sampley 1
  302. While:
  303. Installing eggs.
  304. Error: There is a version conflict.
  305. We already have: demoneeded 1.1
  306. but sampley 1 requires 'demoneeded==1.0'.
  307. """
  308. def show_who_requires_missing_distributions():
  309. """
  310. When working with a lot of eggs, which require eggs recursively, it
  311. can be hard to tell why we're requiring things we can't
  312. find. Fortunately, buildout will tell us who's asking for something
  313. that we can't find. when run in verbose mode
  314. >>> make_dist_that_requires(sample_buildout, 'sampley', ['demoneeded'])
  315. >>> make_dist_that_requires(sample_buildout, 'samplea', ['sampleb'])
  316. >>> make_dist_that_requires(sample_buildout, 'sampleb',
  317. ... ['sampley', 'samplea'])
  318. >>> write('buildout.cfg',
  319. ... '''
  320. ... [buildout]
  321. ... parts = eggs
  322. ... develop = sampley samplea sampleb
  323. ...
  324. ... [eggs]
  325. ... recipe = zc.recipe.egg
  326. ... eggs = samplea
  327. ... ''')
  328. >>> print_(system(buildout+' -v'), end='') # doctest: +ELLIPSIS
  329. Installing ...
  330. Installing 'samplea'.
  331. We have a develop egg: samplea 1
  332. Getting required 'sampleb'
  333. required by samplea 1.
  334. We have a develop egg: sampleb 1
  335. Getting required 'sampley'
  336. required by sampleb 1.
  337. We have a develop egg: sampley 1
  338. Getting required 'demoneeded'
  339. required by sampley 1.
  340. We have no distributions for demoneeded that satisfies 'demoneeded'.
  341. ...
  342. While:
  343. Installing eggs.
  344. Getting distribution for 'demoneeded'.
  345. Error: Couldn't find a distribution for 'demoneeded'.
  346. """
  347. def test_comparing_saved_options_with_funny_characters():
  348. """
  349. If an option has newlines, extra/odd spaces or a %, we need to make sure
  350. the comparison with the saved value works correctly.
  351. >>> mkdir(sample_buildout, 'recipes')
  352. >>> write(sample_buildout, 'recipes', 'debug.py',
  353. ... '''
  354. ... class Debug:
  355. ... def __init__(self, buildout, name, options):
  356. ... options['debug'] = \"\"\" <zodb>
  357. ...
  358. ... <filestorage>
  359. ... path foo
  360. ... </filestorage>
  361. ...
  362. ... </zodb>
  363. ... \"\"\"
  364. ... options['debug1'] = \"\"\"
  365. ... <zodb>
  366. ...
  367. ... <filestorage>
  368. ... path foo
  369. ... </filestorage>
  370. ...
  371. ... </zodb>
  372. ... \"\"\"
  373. ... options['debug2'] = ' x '
  374. ... options['debug3'] = '42'
  375. ... options['format'] = '%3d'
  376. ...
  377. ... def install(self):
  378. ... open('t', 'w').write('t')
  379. ... return 't'
  380. ...
  381. ... update = install
  382. ... ''')
  383. >>> write(sample_buildout, 'recipes', 'setup.py',
  384. ... '''
  385. ... from setuptools import setup
  386. ... setup(
  387. ... name = "recipes",
  388. ... entry_points = {'zc.buildout': ['default = debug:Debug']},
  389. ... )
  390. ... ''')
  391. >>> write(sample_buildout, 'recipes', 'README.txt', " ")
  392. >>> write(sample_buildout, 'buildout.cfg',
  393. ... '''
  394. ... [buildout]
  395. ... develop = recipes
  396. ... parts = debug
  397. ...
  398. ... [debug]
  399. ... recipe = recipes
  400. ... ''')
  401. >>> os.chdir(sample_buildout)
  402. >>> buildout = os.path.join(sample_buildout, 'bin', 'buildout')
  403. >>> print_(system(buildout), end='')
  404. Develop: '/sample-buildout/recipes'
  405. Installing debug.
  406. If we run the buildout again, we shoudn't get a message about
  407. uninstalling anything because the configuration hasn't changed.
  408. >>> print_(system(buildout), end='')
  409. Develop: '/sample-buildout/recipes'
  410. Updating debug.
  411. """
  412. def finding_eggs_as_local_directories():
  413. r"""
  414. It is possible to set up find-links so that we could install from
  415. a local directory that may contained unzipped eggs.
  416. >>> src = tmpdir('src')
  417. >>> write(src, 'setup.py',
  418. ... '''
  419. ... from setuptools import setup
  420. ... setup(name='demo', py_modules=[''],
  421. ... zip_safe=False, version='1.0', author='bob', url='bob',
  422. ... author_email='bob')
  423. ... ''')
  424. >>> write(src, 't.py', '#\n')
  425. >>> write(src, 'README.txt', '')
  426. >>> _ = system(join('bin', 'buildout')+' setup ' + src + ' bdist_egg')
  427. Install it so it gets unzipped:
  428. >>> d1 = tmpdir('d1')
  429. >>> ws = zc.buildout.easy_install.install(
  430. ... ['demo'], d1, links=[join(src, 'dist')],
  431. ... )
  432. >>> ls(d1)
  433. d demo-1.0-py2.4.egg
  434. Then try to install it again:
  435. >>> d2 = tmpdir('d2')
  436. >>> ws = zc.buildout.easy_install.install(
  437. ... ['demo'], d2, links=[d1],
  438. ... )
  439. >>> ls(d2)
  440. d demo-1.0-py2.4.egg
  441. """
  442. def create_sections_on_command_line():
  443. """
  444. >>> write('buildout.cfg',
  445. ... '''
  446. ... [buildout]
  447. ... parts =
  448. ... x = ${foo:bar}
  449. ... ''')
  450. >>> print_(system(buildout + ' foo:bar=1 -vv'), end='')
  451. ... # doctest: +ELLIPSIS
  452. Installing 'zc.buildout >=1.99', 'distribute'.
  453. ...
  454. [foo]
  455. bar = 1
  456. ...
  457. """
  458. def test_help():
  459. """
  460. >>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout')+' -h'))
  461. ... # doctest: +ELLIPSIS
  462. Usage: buildout [options] [assignments] [command [command arguments]]
  463. <BLANKLINE>
  464. Options:
  465. <BLANKLINE>
  466. -h, --help
  467. ...
  468. >>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout')
  469. ... +' --help'))
  470. ... # doctest: +ELLIPSIS
  471. Usage: buildout [options] [assignments] [command [command arguments]]
  472. <BLANKLINE>
  473. Options:
  474. <BLANKLINE>
  475. -h, --help
  476. ...
  477. """
  478. def test_bootstrap_with_extension():
  479. """
  480. We had a problem running a bootstrap with an extension. Let's make
  481. sure it is fixed. Basically, we don't load extensions when
  482. bootstrapping.
  483. >>> d = tmpdir('sample-bootstrap')
  484. >>> write(d, 'buildout.cfg',
  485. ... '''
  486. ... [buildout]
  487. ... extensions = some_awsome_extension
  488. ... parts =
  489. ... ''')
  490. >>> os.chdir(d)
  491. >>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout')
  492. ... + ' bootstrap'), end='')
  493. Creating directory '/sample-bootstrap/bin'.
  494. Creating directory '/sample-bootstrap/parts'.
  495. Creating directory '/sample-bootstrap/eggs'.
  496. Creating directory '/sample-bootstrap/develop-eggs'.
  497. Generated script '/sample-bootstrap/bin/buildout'.
  498. """
  499. def bug_92891_bootstrap_crashes_with_egg_recipe_in_buildout_section():
  500. """
  501. >>> d = tmpdir('sample-bootstrap')
  502. >>> write(d, 'buildout.cfg',
  503. ... '''
  504. ... [buildout]
  505. ... parts = buildout
  506. ... eggs-directory = eggs
  507. ...
  508. ... [buildout]
  509. ... recipe = zc.recipe.egg
  510. ... eggs = zc.buildout
  511. ... scripts = buildout=buildout
  512. ... ''')
  513. >>> os.chdir(d)
  514. >>> print_(system(os.path.join(sample_buildout, 'bin', 'buildout')
  515. ... + ' bootstrap'), end='')
  516. Creating directory '/sample-bootstrap/bin'.
  517. Creating directory '/sample-bootstrap/parts'.
  518. Creating directory '/sample-bootstrap/eggs'.
  519. Creating directory '/sample-bootstrap/develop-eggs'.
  520. Generated script '/sample-bootstrap/bin/buildout'.
  521. >>> print_(system(os.path.join('bin', 'buildout')), end='')
  522. Unused options for buildout: 'scripts' 'eggs'.
  523. """
  524. def removing_eggs_from_develop_section_causes_egg_link_to_be_removed():
  525. '''
  526. >>> cd(sample_buildout)
  527. Create a develop egg:
  528. >>> mkdir('foo')
  529. >>> write('foo', 'setup.py',
  530. ... """
  531. ... from setuptools import setup
  532. ... setup(name='foox')
  533. ... """)
  534. >>> write('buildout.cfg',
  535. ... """
  536. ... [buildout]
  537. ... develop = foo
  538. ... parts =
  539. ... """)
  540. >>> print_(system(join('bin', 'buildout')), end='')
  541. Develop: '/sample-buildout/foo'
  542. >>> ls('develop-eggs')
  543. - foox.egg-link
  544. - zc.recipe.egg.egg-link
  545. Create another:
  546. >>> mkdir('bar')
  547. >>> write('bar', 'setup.py',
  548. ... """
  549. ... from setuptools import setup
  550. ... setup(name='fooy')
  551. ... """)
  552. >>> write('buildout.cfg',
  553. ... """
  554. ... [buildout]
  555. ... develop = foo bar
  556. ... parts =
  557. ... """)
  558. >>> print_(system(join('bin', 'buildout')), end='')
  559. Develop: '/sample-buildout/foo'
  560. Develop: '/sample-buildout/bar'
  561. >>> ls('develop-eggs')
  562. - foox.egg-link
  563. - fooy.egg-link
  564. - zc.recipe.egg.egg-link
  565. Remove one:
  566. >>> write('buildout.cfg',
  567. ... """
  568. ... [buildout]
  569. ... develop = bar
  570. ... parts =
  571. ... """)
  572. >>> print_(system(join('bin', 'buildout')), end='')
  573. Develop: '/sample-buildout/bar'
  574. It is gone
  575. >>> ls('develop-eggs')
  576. - fooy.egg-link
  577. - zc.recipe.egg.egg-link
  578. Remove the other:
  579. >>> write('buildout.cfg',
  580. ... """
  581. ... [buildout]
  582. ... parts =
  583. ... """)
  584. >>> print_(system(join('bin', 'buildout')), end='')
  585. All gone
  586. >>> ls('develop-eggs')
  587. - zc.recipe.egg.egg-link
  588. '''
  589. def add_distribute_to_dependencies_when_namespace_packages():
  590. '''
  591. Often, a package depends on distribute soley by virtue of using
  592. namespace packages. In this situation, package authors often forget to
  593. declare distribute as a dependency. This is a mistake, but,
  594. unfortunately, a common one that we need to work around. If an egg
  595. uses namespace packages and does not include distribute as a depenency,
  596. we will still include distribute in the working set. If we see this for
  597. a devlop egg, we will also generate a warning.
  598. >>> mkdir('foo')
  599. >>> mkdir('foo', 'src')
  600. >>> mkdir('foo', 'src', 'stuff')
  601. >>> write('foo', 'src', 'stuff', '__init__.py',
  602. ... """__import__('pkg_resources').declare_namespace(__name__)
  603. ... """)
  604. >>> mkdir('foo', 'src', 'stuff', 'foox')
  605. >>> write('foo', 'src', 'stuff', 'foox', '__init__.py', '')
  606. >>> write('foo', 'setup.py',
  607. ... """
  608. ... from setuptools import setup
  609. ... setup(name='foox',
  610. ... namespace_packages = ['stuff'],
  611. ... package_dir = {'': 'src'},
  612. ... packages = ['stuff', 'stuff.foox'],
  613. ... )
  614. ... """)
  615. >>> write('foo', 'README.txt', '')
  616. >>> write('buildout.cfg',
  617. ... """
  618. ... [buildout]
  619. ... develop = foo
  620. ... parts =
  621. ... """)
  622. >>> print_(system(join('bin', 'buildout')), end='')
  623. Develop: '/sample-buildout/foo'
  624. Now, if we generate a working set using the egg link, we will get a warning
  625. and we will get distribute included in the working set.
  626. >>> import logging, zope.testing.loggingsupport
  627. >>> handler = zope.testing.loggingsupport.InstalledHandler(
  628. ... 'zc.buildout.easy_install', level=logging.WARNING)
  629. >>> logging.getLogger('zc.buildout.easy_install').propagate = False
  630. >>> [dist.project_name
  631. ... for dist in zc.buildout.easy_install.working_set(
  632. ... ['foox'], sys.executable,
  633. ... [join(sample_buildout, 'eggs'),
  634. ... join(sample_buildout, 'develop-eggs'),
  635. ... ])]
  636. ['foox', 'distribute']
  637. >>> print_(handler)
  638. zc.buildout.easy_install WARNING
  639. Develop distribution: foox 0.0.0
  640. uses namespace packages but the distribution does not require distribute.
  641. >>> handler.clear()
  642. On the other hand, if we have a regular egg, rather than a develop egg:
  643. >>> os.remove(join('develop-eggs', 'foox.egg-link'))
  644. >>> _ = system(join('bin', 'buildout') + ' setup foo bdist_egg -d'
  645. ... + join(sample_buildout, 'eggs'))
  646. >>> ls('develop-eggs')
  647. - zc.recipe.egg.egg-link
  648. >>> ls('eggs') # doctest: +ELLIPSIS
  649. - distribute.eggpyN.N.egg
  650. - foox-0.0.0-py2.4.egg
  651. ...
  652. We do not get a warning, but we do get distribute included in the working set:
  653. >>> [dist.project_name
  654. ... for dist in zc.buildout.easy_install.working_set(
  655. ... ['foox'], sys.executable,
  656. ... [join(sample_buildout, 'eggs'),
  657. ... join(sample_buildout, 'develop-eggs'),
  658. ... ])]
  659. ['foox', 'distribute']
  660. >>> print_(handler, end='')
  661. We get the same behavior if the it is a depedency that uses a
  662. namespace package.
  663. >>> mkdir('bar')
  664. >>> write('bar', 'setup.py',
  665. ... """
  666. ... from setuptools import setup
  667. ... setup(name='bar', install_requires = ['foox'])
  668. ... """)
  669. >>> write('bar', 'README.txt', '')
  670. >>> write('buildout.cfg',
  671. ... """
  672. ... [buildout]
  673. ... develop = foo bar
  674. ... parts =
  675. ... """)
  676. >>> print_(system(join('bin', 'buildout')), end='')
  677. Develop: '/sample-buildout/foo'
  678. Develop: '/sample-buildout/bar'
  679. >>> [dist.project_name
  680. ... for dist in zc.buildout.easy_install.working_set(
  681. ... ['bar'], sys.executable,
  682. ... [join(sample_buildout, 'eggs'),
  683. ... join(sample_buildout, 'develop-eggs'),
  684. ... ])]
  685. ['bar', 'foox', 'distribute']
  686. >>> print_(handler, end='')
  687. zc.buildout.easy_install WARNING
  688. Develop distribution: foox 0.0.0
  689. uses namespace packages but the distribution does not require distribute.
  690. >>> logging.getLogger('zc.buildout.easy_install').propagate = True
  691. >>> handler.uninstall()
  692. '''
  693. def develop_preserves_existing_setup_cfg():
  694. """
  695. See "Handling custom build options for extensions in develop eggs" in
  696. easy_install.txt. This will be very similar except that we'll have an
  697. existing setup.cfg:
  698. >>> write(extdemo, "setup.cfg",
  699. ... '''
  700. ... # sampe cfg file
  701. ...
  702. ... [foo]
  703. ... bar = 1
  704. ...
  705. ... [build_ext]
  706. ... define = X,Y
  707. ... ''')
  708. >>> mkdir('include')
  709. >>> write('include', 'extdemo.h',
  710. ... '''
  711. ... #define EXTDEMO 42
  712. ... ''')
  713. >>> dest = tmpdir('dest')
  714. >>> zc.buildout.easy_install.develop(
  715. ... extdemo, dest,
  716. ... {'include-dirs': os.path.join(sample_buildout, 'include')})
  717. '/dest/extdemo.egg-link'
  718. >>> ls(dest)
  719. - extdemo.egg-link
  720. >>> cat(extdemo, "setup.cfg")
  721. <BLANKLINE>
  722. # sampe cfg file
  723. <BLANKLINE>
  724. [foo]
  725. bar = 1
  726. <BLANKLINE>
  727. [build_ext]
  728. define = X,Y
  729. """
  730. def uninstall_recipes_used_for_removal():
  731. r"""
  732. Uninstall recipes need to be called when a part is removed too:
  733. >>> mkdir("recipes")
  734. >>> write("recipes", "setup.py",
  735. ... '''
  736. ... from setuptools import setup
  737. ... setup(name='recipes',
  738. ... entry_points={
  739. ... 'zc.buildout': ["demo=demo:Install"],
  740. ... 'zc.buildout.uninstall': ["demo=demo:uninstall"],
  741. ... })
  742. ... ''')
  743. >>> write("recipes", "demo.py",
  744. ... r'''
  745. ... import sys
  746. ... class Install:
  747. ... def __init__(*args): pass
  748. ... def install(self):
  749. ... sys.stdout.write('installing\n')
  750. ... return ()
  751. ... def uninstall(name, options):
  752. ... sys.stdout.write('uninstalling\n')
  753. ... ''')
  754. >>> write('buildout.cfg', '''
  755. ... [buildout]
  756. ... develop = recipes
  757. ... parts = demo
  758. ... [demo]
  759. ... recipe = recipes:demo
  760. ... ''')
  761. >>> print_(system(join('bin', 'buildout')), end='')
  762. Develop: '/sample-buildout/recipes'
  763. Installing demo.
  764. installing
  765. >>> write('buildout.cfg', '''
  766. ... [buildout]
  767. ... develop = recipes
  768. ... parts = demo
  769. ... [demo]
  770. ... recipe = recipes:demo
  771. ... x = 1
  772. ... ''')
  773. >>> print_(system(join('bin', 'buildout')), end='')
  774. Develop: '/sample-buildout/recipes'
  775. Uninstalling demo.
  776. Running uninstall recipe.
  777. uninstalling
  778. Installing demo.
  779. installing
  780. >>> write('buildout.cfg', '''
  781. ... [buildout]
  782. ... develop = recipes
  783. ... parts =
  784. ... ''')
  785. >>> print_(system(join('bin', 'buildout')), end='')
  786. Develop: '/sample-buildout/recipes'
  787. Uninstalling demo.
  788. Running uninstall recipe.
  789. uninstalling
  790. """
  791. def extensions_installed_as_eggs_work_in_offline_mode():
  792. '''
  793. >>> mkdir('demo')
  794. >>> write('demo', 'demo.py',
  795. ... r"""
  796. ... import sys
  797. ... def print_(*args):
  798. ... sys.stdout.write(' '.join(map(str, args)) + '\\n')
  799. ... def ext(buildout):
  800. ... print_('ext', list(buildout))
  801. ... """)
  802. >>> write('demo', 'setup.py',
  803. ... """
  804. ... from setuptools import setup
  805. ...
  806. ... setup(
  807. ... name = "demo",
  808. ... py_modules=['demo'],
  809. ... entry_points = {'zc.buildout.extension': ['ext = demo:ext']},
  810. ... )
  811. ... """)
  812. >>> bdist_egg(join(sample_buildout, "demo"), sys.executable,
  813. ... join(sample_buildout, "eggs"))
  814. >>> write(sample_buildout, 'buildout.cfg',
  815. ... """
  816. ... [buildout]
  817. ... extensions = demo
  818. ... parts =
  819. ... offline = true
  820. ... """)
  821. >>> print_(system(join(sample_buildout, 'bin', 'buildout')), end='')
  822. ext ['buildout']
  823. '''
  824. def changes_in_svn_or_CVS_dont_affect_sig():
  825. """
  826. If we have a develop recipe, it's signature shouldn't be affected to
  827. changes in .svn or CVS directories.
  828. >>> mkdir('recipe')
  829. >>> write('recipe', 'setup.py',
  830. ... '''
  831. ... from setuptools import setup
  832. ... setup(name='recipe',
  833. ... entry_points={'zc.buildout': ['default=foo:Foo']})
  834. ... ''')
  835. >>> write('recipe', 'foo.py',
  836. ... '''
  837. ... class Foo:
  838. ... def __init__(*args): pass
  839. ... def install(*args): return ()
  840. ... update = install
  841. ... ''')
  842. >>> write('buildout.cfg',
  843. ... '''
  844. ... [buildout]
  845. ... develop = recipe
  846. ... parts = foo
  847. ...
  848. ... [foo]
  849. ... recipe = recipe
  850. ... ''')
  851. >>> print_(system(join(sample_buildout, 'bin', 'buildout')), end='')
  852. Develop: '/sample-buildout/recipe'
  853. Installing foo.
  854. >>> mkdir('recipe', '.svn')
  855. >>> mkdir('recipe', 'CVS')
  856. >>> print_(system(join(sample_buildout, 'bin', 'buildout')), end='')
  857. Develop: '/sample-buildout/recipe'
  858. Updating foo.
  859. >>> write('recipe', '.svn', 'x', '1')
  860. >>> write('recipe', 'CVS', 'x', '1')
  861. >>> print_(system(join(sample_buildout, 'bin', 'buildout')), end='')
  862. Develop: '/sample-buildout/recipe'
  863. Updating foo.
  864. """
  865. if hasattr(os, 'symlink'):
  866. def bug_250537_broken_symlink_doesnt_affect_sig():
  867. """
  868. If we have a develop recipe, it's signature shouldn't be affected by
  869. broken symlinks, and better yet, computing the hash should not break
  870. because of the missing target file.
  871. >>> mkdir('recipe')
  872. >>> write('recipe', 'setup.py',
  873. ... '''
  874. ... from setuptools import setup
  875. ... setup(name='recipe',
  876. ... entry_points={'zc.buildout': ['default=foo:Foo']})
  877. ... ''')
  878. >>> write('recipe', 'foo.py',
  879. ... '''
  880. ... class Foo:
  881. ... def __init__(*args): pass
  882. ... def install(*args): return ()
  883. ... update = install
  884. ... ''')
  885. >>> write('buildout.cfg',
  886. ... '''
  887. ... [buildout]
  888. ... develop = recipe
  889. ... parts = foo
  890. ...
  891. ... [foo]
  892. ... recipe = recipe
  893. ... ''')
  894. >>> print_(system(join(sample_buildout, 'bin', 'buildout')), end='')
  895. Develop: '/sample-buildout/recipe'
  896. Installing foo.
  897. >>> write('recipe', 'some-file', '1')
  898. >>> os.symlink(join('recipe', 'some-file'),
  899. ... join('recipe', 'another-file'))
  900. >>> remove('recipe', 'some-file')
  901. >>> print_(system(join(sample_buildout, 'bin', 'buildout')), end='')
  902. Develop: '/sample-buildout/recipe'
  903. Updating foo.
  904. """
  905. def o_option_sets_offline():
  906. """
  907. >>> print_(system(join(sample_buildout, 'bin', 'buildout')+' -vvo'), end='')
  908. ... # doctest: +ELLIPSIS
  909. <BLANKLINE>
  910. ...
  911. offline = true
  912. ...
  913. """
  914. def recipe_upgrade():
  915. r"""
  916. The buildout will upgrade recipes in newest (and non-offline) mode.
  917. Let's create a recipe egg
  918. >>> mkdir('recipe')
  919. >>> write('recipe', 'recipe.py',
  920. ... r'''
  921. ... import sys
  922. ... class Recipe:
  923. ... def __init__(*a): pass
  924. ... def install(self):
  925. ... sys.stdout.write('recipe v1\n')
  926. ... return ()
  927. ... update = install
  928. ... ''')
  929. >>> write('recipe', 'setup.py',
  930. ... '''
  931. ... from setuptools import setup
  932. ... setup(name='recipe', version='1', py_modules=['recipe'],
  933. ... entry_points={'zc.buildout': ['default = recipe:Recipe']},
  934. ... )
  935. ... ''')
  936. >>> write('recipe', 'README', '')
  937. >>> print_(system(buildout+' setup recipe bdist_egg')) # doctest: +ELLIPSIS
  938. Running setup script 'recipe/setup.py'.
  939. ...
  940. >>> rmdir('recipe', 'build')
  941. And update our buildout to use it.
  942. >>> write('buildout.cfg',
  943. ... '''
  944. ... [buildout]
  945. ... parts = foo
  946. ... find-links = %s
  947. ...
  948. ... [foo]
  949. ... recipe = recipe
  950. ... ''' % join('recipe', 'dist'))
  951. >>> print_(system(buildout), end='')
  952. Getting distribution for 'recipe'.
  953. Got recipe 1.
  954. Installing foo.
  955. recipe v1
  956. Now, if we update the recipe egg:
  957. >>> write('recipe', 'recipe.py',
  958. ... r'''
  959. ... import sys
  960. ... class Recipe:
  961. ... def __init__(*a): pass
  962. ... def install(self):
  963. ... sys.stdout.write('recipe v2\n')
  964. ... return ()
  965. ... update = install
  966. ... ''')
  967. >>> write('recipe', 'setup.py',
  968. ... '''
  969. ... from setuptools import setup
  970. ... setup(name='recipe', version='2', py_modules=['recipe'],
  971. ... entry_points={'zc.buildout': ['default = recipe:Recipe']},
  972. ... )
  973. ... ''')
  974. >>> print_(system(buildout+' setup recipe bdist_egg')) # doctest: +ELLIPSIS
  975. Running setup script 'recipe/setup.py'.
  976. ...
  977. We won't get the update if we specify -N:
  978. >>> print_(system(buildout+' -N'), end='')
  979. Updating foo.
  980. recipe v1
  981. or if we use -o:
  982. >>> print_(system(buildout+' -o'), end='')
  983. Updating foo.
  984. recipe v1
  985. But we will if we use neither of these:
  986. >>> print_(system(buildout), end='')
  987. Getting distribution for 'recipe'.
  988. Got recipe 2.
  989. Uninstalling foo.
  990. Installing foo.
  991. recipe v2
  992. We can also select a particular recipe version:
  993. >>> write('buildout.cfg',
  994. ... '''
  995. ... [buildout]
  996. ... parts = foo
  997. ... find-links = %s
  998. ...
  999. ... [foo]
  1000. ... recipe = recipe ==1
  1001. ... ''' % join('recipe', 'dist'))
  1002. >>> print_(system(buildout), end='')
  1003. Uninstalling foo.
  1004. Installing foo.
  1005. recipe v1
  1006. """
  1007. def update_adds_to_uninstall_list():
  1008. """
  1009. Paths returned by the update method are added to the list of paths to
  1010. uninstall
  1011. >>> mkdir('recipe')
  1012. >>> write('recipe', 'setup.py',
  1013. ... '''
  1014. ... from setuptools import setup
  1015. ... setup(name='recipe',
  1016. ... entry_points={'zc.buildout': ['default = recipe:Recipe']},
  1017. ... )
  1018. ... ''')
  1019. >>> write('recipe', 'recipe.py',
  1020. ... '''
  1021. ... import os
  1022. ... class Recipe:
  1023. ... def __init__(*_): pass
  1024. ... def install(self):
  1025. ... r = ('a', 'b', 'c')
  1026. ... for p in r: os.mkdir(p)
  1027. ... return r
  1028. ... def update(self):
  1029. ... r = ('c', 'd', 'e')
  1030. ... for p in r:
  1031. ... if not os.path.exists(p):
  1032. ... os.mkdir(p)
  1033. ... return r
  1034. ... ''')
  1035. >>> write('buildout.cfg',
  1036. ... '''
  1037. ... [buildout]
  1038. ... develop = recipe
  1039. ... parts = foo
  1040. ...
  1041. ... [foo]
  1042. ... recipe = recipe
  1043. ... ''')
  1044. >>> print_(system(buildout), end='')
  1045. Develop: '/sample-buildout/recipe'
  1046. Installing foo.
  1047. >>> print_(system(buildout), end='')
  1048. Develop: '/sample-buildout/recipe'
  1049. Updating foo.
  1050. >>> cat('.installed.cfg') # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
  1051. [buildout]
  1052. ...
  1053. [foo]
  1054. __buildout_installed__ = a
  1055. b
  1056. c
  1057. d
  1058. e
  1059. __buildout_signature__ = ...
  1060. """
  1061. def log_when_there_are_not_local_distros():
  1062. """
  1063. >>> from zope.testing.loggingsupport import InstalledHandler
  1064. >>> handler = InstalledHandler('zc.buildout.easy_install')
  1065. >>> import logging
  1066. >>> logger = logging.getLogger('zc.buildout.easy_install')
  1067. >>> old_propogate = logger.propagate
  1068. >>> logger.propagate = False
  1069. >>> dest = tmpdir('sample-install')
  1070. >>> import zc.buildout.easy_install
  1071. >>> ws = zc.buildout.easy_install.install(
  1072. ... ['demo==0.2'], dest,
  1073. ... links=[link_server], index=link_server+'index/')
  1074. >>> print_(handler) # doctest: +ELLIPSIS
  1075. zc.buildout.easy_install DEBUG
  1076. Installing 'demo==0.2'.
  1077. zc.buildout.easy_install DEBUG
  1078. We have no distributions for demo that satisfies 'demo==0.2'.
  1079. ...
  1080. >>> handler.uninstall()
  1081. >>> logger.propagate = old_propogate
  1082. """
  1083. def internal_errors():
  1084. """Internal errors are clearly marked and don't generate tracebacks:
  1085. >>> mkdir(sample_buildout, 'recipes')
  1086. >>> write(sample_buildout, 'recipes', 'mkdir.py',
  1087. ... '''
  1088. ... class Mkdir:
  1089. ... def __init__(self, buildout, name, options):
  1090. ... self.name, self.options = name, options
  1091. ... options['path'] = os.path.join(
  1092. ... buildout['buildout']['directory'],
  1093. ... options['path'],
  1094. ... )
  1095. ... ''')
  1096. >>> write(sample_buildout, 'recipes', 'setup.py',
  1097. ... '''
  1098. ... from setuptools import setup
  1099. ... setup(name = "recipes",
  1100. ... entry_points = {'zc.buildout': ['mkdir = mkdir:Mkdir']},
  1101. ... )
  1102. ... ''')
  1103. >>> write(sample_buildout, 'buildout.cfg',
  1104. ... '''
  1105. ... [buildout]
  1106. ... develop = recipes
  1107. ... parts = data-dir
  1108. ...
  1109. ... [data-dir]
  1110. ... recipe = recipes:mkdir
  1111. ... ''')
  1112. >>> print_(system(buildout), end='') # doctest: +ELLIPSIS
  1113. Develop: '/sample-buildout/recipes'
  1114. While:
  1115. Installing.
  1116. Getting section data-dir.
  1117. Initializing part data-dir.
  1118. <BLANKLINE>
  1119. An internal error occured due to a bug in either zc.buildout or in a
  1120. recipe being used:
  1121. Traceback (most recent call last):
  1122. ...
  1123. NameError: global name 'os' is not defined
  1124. """
  1125. def whine_about_unused_options():
  1126. '''
  1127. >>> write('foo.py',
  1128. ... """
  1129. ... class Foo:
  1130. ...
  1131. ... def __init__(self, buildout, name, options):
  1132. ... self.name, self.options = name, options
  1133. ... options['x']
  1134. ...
  1135. ... def install(self):
  1136. ... self.options['y']
  1137. ... return ()
  1138. ... """)
  1139. >>> write('setup.py',
  1140. ... """
  1141. ... from setuptools import setup
  1142. ... setup(name = "foo",
  1143. ... entry_points = {'zc.buildout': ['default = foo:Foo']},
  1144. ... )
  1145. ... """)
  1146. >>> write('buildout.cfg',
  1147. ... """
  1148. ... [buildout]
  1149. ... develop = .
  1150. ... parts = foo
  1151. ... a = 1
  1152. ...
  1153. ... [foo]
  1154. ... recipe = foo
  1155. ... x = 1
  1156. ... y = 1
  1157. ... z = 1
  1158. ... """)
  1159. >>> print_(system(buildout), end='')
  1160. Develop: '/sample-buildout/.'
  1161. Unused options for buildout: 'a'.
  1162. Installing foo.
  1163. Unused options for foo: 'z'.
  1164. '''
  1165. def abnormal_exit():
  1166. """
  1167. People sometimes hit control-c while running a builout. We need to make
  1168. sure that the installed database Isn't corrupted. To test this, we'll create
  1169. some evil recipes that exit uncleanly:
  1170. >>> mkdir('recipes')
  1171. >>> write('recipes', 'recipes.py',
  1172. ... '''
  1173. ... import os
  1174. ...
  1175. ... class Clean:
  1176. ... def __init__(*_): pass
  1177. ... def install(_): return ()
  1178. ... def update(_): pass
  1179. ...
  1180. ... class EvilInstall(Clean):
  1181. ... def install(_): os._exit(1)
  1182. ...
  1183. ... class EvilUpdate(Clean):
  1184. ... def update(_): os._exit(1)
  1185. ... ''')
  1186. >>> write('recipes', 'setup.py',
  1187. ... '''
  1188. ... import setuptools
  1189. ... setuptools.setup(name='recipes',
  1190. ... entry_points = {
  1191. ... 'zc.buildout': [
  1192. ... 'clean = recipes:Clean',
  1193. ... 'evil_install = recipes:EvilInstall',
  1194. ... 'evil_update = recipes:EvilUpdate',
  1195. ... 'evil_uninstall = recipes:Clean',
  1196. ... ],
  1197. ... },
  1198. ... )
  1199. ... ''')
  1200. Now let's look at 3 cases:
  1201. 1. We exit during installation after installing some other parts:
  1202. >>> write('buildout.cfg',
  1203. ... '''
  1204. ... [buildout]
  1205. ... develop = recipes
  1206. ... parts = p1 p2 p3 p4
  1207. ...
  1208. ... [p1]
  1209. ... recipe = recipes:clean
  1210. ...
  1211. ... [p2]
  1212. ... recipe = recipes:clean
  1213. ...
  1214. ... [p3]
  1215. ... recipe = recipes:evil_install
  1216. ...
  1217. ... [p4]
  1218. ... recipe = recipes:clean
  1219. ... ''')
  1220. >>> print_(system(buildout), end='')
  1221. Develop: '/sample-buildout/recipes'
  1222. Installing p1.
  1223. Installing p2.
  1224. Installing p3.
  1225. >>> print_(system(buildout), end='')
  1226. Develop: '/sample-buildout/recipes'
  1227. Updating p1.
  1228. Updating p2.
  1229. Installing p3.
  1230. >>> print_(system(buildout+' buildout:parts='), end='')
  1231. Develop: '/sample-buildout/recipes'
  1232. Uninstalling p2.
  1233. Uninstalling p1.
  1234. 2. We exit while updating:
  1235. >>> write('buildout.cfg',
  1236. ... '''
  1237. ... [buildout]
  1238. ... develop = recipes
  1239. ... parts = p1 p2 p3 p4
  1240. ...
  1241. ... [p1]
  1242. ... recipe = recipes:clean
  1243. ...
  1244. ... [p2]
  1245. ... recipe = recipes:clean
  1246. ...
  1247. ... [p3]
  1248. ... recipe = recipes:evil_update
  1249. ...
  1250. ... [p4]
  1251. ... recipe = recipes:clean
  1252. ... ''')
  1253. >>> print_(system(buildout), end='')
  1254. Develop: '/sample-buildout/recipes'
  1255. Installing p1.
  1256. Installing p2.
  1257. Installing p3.
  1258. Installing p4.
  1259. >>> print_(system(buildout), end='')
  1260. Develop: '/sample-buildout/recipes'
  1261. Updating p1.
  1262. Updating p2.
  1263. Updating p3.
  1264. >>> print_(system(buildout+' buildout:parts='), end='')
  1265. Develop: '/sample-buildout/recipes'
  1266. Uninstalling p2.
  1267. Uninstalling p1.
  1268. Uninstalling p4.
  1269. Uninstalling p3.
  1270. 3. We exit while installing or updating after uninstalling:
  1271. >>> write('buildout.cfg',
  1272. ... '''
  1273. ... [buildout]
  1274. ... develop = recipes
  1275. ... parts = p1 p2 p3 p4
  1276. ...
  1277. ... [p1]
  1278. ... recipe = recipes:evil_update
  1279. ...
  1280. ... [p2]
  1281. ... recipe = recipes:clean
  1282. ...
  1283. ... [p3]
  1284. ... recipe = recipes:clean
  1285. ...
  1286. ... [p4]
  1287. ... recipe = recipes:clean
  1288. ... ''')
  1289. >>> print_(system(buildout), end='')
  1290. Develop: '/sample-buildout/recipes'
  1291. Installing p1.
  1292. Installing p2.
  1293. Installing p3.
  1294. Installing p4.
  1295. >>> write('buildout.cfg',
  1296. ... '''
  1297. ... [buildout]
  1298. ... develop = recipes
  1299. ... parts = p1 p2 p3 p4
  1300. ...
  1301. ... [p1]
  1302. ... recipe = recipes:evil_update
  1303. ...
  1304. ... [p2]
  1305. ... recipe = recipes:clean
  1306. ...
  1307. ... [p3]
  1308. ... recipe = recipes:clean
  1309. ...
  1310. ... [p4]
  1311. ... recipe = recipes:clean
  1312. ... x = 1
  1313. ... ''')
  1314. >>> print_(system(buildout), end='')
  1315. Develop: '/sample-buildout/recipes'
  1316. Uninstalling p4.
  1317. Updating p1.
  1318. >>> write('buildout.cfg',
  1319. ... '''
  1320. ... [buildout]
  1321. ... develop = recipes
  1322. ... parts = p1 p2 p3 p4
  1323. ...
  1324. ... [p1]
  1325. ... recipe = recipes:clean
  1326. ...
  1327. ... [p2]
  1328. ... recipe = recipes:clean
  1329. ...
  1330. ... [p3]
  1331. ... recipe = recipes:clean
  1332. ...
  1333. ... [p4]
  1334. ... recipe = recipes:clean
  1335. ... ''')
  1336. >>> print_(system(buildout), end='')
  1337. Develop: '/sample-buildout/recipes'
  1338. Uninstalling p1.
  1339. Installing p1.
  1340. Updating p2.
  1341. Updating p3.
  1342. Installing p4.
  1343. """
  1344. def install_source_dist_with_bad_py():
  1345. r"""
  1346. >>> mkdir('badegg')
  1347. >>> mkdir('badegg', 'badegg')
  1348. >>> write('badegg', 'badegg', '__init__.py', '#\\n')
  1349. >>> mkdir('badegg', 'badegg', 'scripts')
  1350. >>> write('badegg', 'badegg', 'scripts', '__init__.py', '#\\n')
  1351. >>> write('badegg', 'badegg', 'scripts', 'one.py',
  1352. ... '''
  1353. ... return 1
  1354. ... ''')
  1355. >>> write('badegg', 'setup.py',
  1356. ... '''
  1357. ... from setuptools import setup, find_packages
  1358. ... setup(
  1359. ... name='badegg',
  1360. ... version='1',
  1361. ... packages = find_packages('.'),
  1362. ... zip_safe=False)
  1363. ... ''')
  1364. >>> print_(system(buildout+' setup badegg sdist'), end='') # doctest: +ELLIPSIS
  1365. Running setup script 'badegg/setup.py'.
  1366. ...
  1367. >>> dist = join('badegg', 'dist')
  1368. >>> write('buildout.cfg',
  1369. ... '''
  1370. ... [buildout]
  1371. ... parts = eggs bo
  1372. ... find-links = %(dist)s
  1373. ...
  1374. ... [eggs]
  1375. ... recipe = zc.recipe.egg
  1376. ... eggs = badegg
  1377. ...
  1378. ... [bo]
  1379. ... recipe = zc.recipe.egg
  1380. ... eggs = zc.buildout
  1381. ... scripts = buildout=bo
  1382. ... ''' % globals())
  1383. >>> print_(system(buildout));print_('X') # doctest: +ELLIPSIS
  1384. Installing eggs.
  1385. Getting distribution for 'badegg'.
  1386. Got badegg 1.
  1387. Installing bo.
  1388. ...
  1389. SyntaxError: ...'return' outside function...
  1390. ...
  1391. SyntaxError: ...'return' outside function...
  1392. ...
  1393. >>> ls('eggs') # doctest: +ELLIPSIS
  1394. d badegg-1-py2.4.egg
  1395. ...
  1396. >>> ls('bin')
  1397. - bo
  1398. - buildout
  1399. """
  1400. def version_requirements_in_build_honored():
  1401. '''
  1402. >>> update_extdemo()
  1403. >>> dest = tmpdir('sample-install')
  1404. >>> mkdir('include')
  1405. >>> write('include', 'extdemo.h',
  1406. ... """
  1407. ... #define EXTDEMO 42
  1408. ... """)
  1409. >>> zc.buildout.easy_install.build(
  1410. ... 'extdemo ==1.4', dest,
  1411. ... {'include-dirs': os.path.join(sample_buildout, 'include')},
  1412. ... links=[link_server], index=link_server+'index/',
  1413. ... newest=False)
  1414. ['/sample-install/extdemo-1.4-py2.4-linux-i686.egg']
  1415. '''
  1416. def bug_105081_Specific_egg_versions_are_ignored_when_newer_eggs_are_around():
  1417. """
  1418. Buildout might ignore a specific egg requirement for a recipe:
  1419. - Have a newer version of an egg in your eggs directory
  1420. - Use 'recipe==olderversion' in your buildout.cfg to request an
  1421. older version
  1422. Buildout will go and fetch the older version, but it will *use*
  1423. the newer version when installing a part with this recipe.
  1424. >>> write('buildout.cfg',
  1425. ... '''
  1426. ... [buildout]
  1427. ... parts = x
  1428. ... find-links = %(sample_eggs)s
  1429. ...
  1430. ... [x]
  1431. ... recipe = zc.recipe.egg
  1432. ... eggs = demo
  1433. ... ''' % globals())
  1434. >>> print_(system(buildout), end='')
  1435. Installing x.
  1436. Getting distribution for 'demo'.
  1437. Got demo 0.3.
  1438. Getting distribution for 'demoneeded'.
  1439. Got demoneeded 1.1.
  1440. Generated script '/sample-buildout/bin/demo'.
  1441. >>> print_(system(join('bin', 'demo')), end='')
  1442. 3 1
  1443. >>> write('buildout.cfg',
  1444. ... '''
  1445. ... [buildout]
  1446. ... parts = x
  1447. ... find-links = %(sample_eggs)s
  1448. ...
  1449. ... [x]
  1450. ... recipe = zc.recipe.egg
  1451. ... eggs = demo ==0.1
  1452. ... ''' % globals())
  1453. >>> print_(system(buildout), end='')
  1454. Uninstalling x.
  1455. Installing x.
  1456. Getting distribution for 'demo==0.1'.
  1457. Got demo 0.1.
  1458. Generated script '/sample-buildout/bin/demo'.
  1459. >>> print_(system(join('bin', 'demo')), end='')
  1460. 1 1
  1461. """
  1462. if sys.version_info > (2, 4):
  1463. def test_exit_codes():
  1464. """
  1465. >>> import subprocess
  1466. >>> def call(s):
  1467. ... p = subprocess.Popen(s, stdin=subprocess.PIPE,
  1468. ... stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
  1469. ... p.stdin.close()
  1470. ... print_(p.stdout.read().decode())
  1471. ... print_('Exit:', bool(p.wait()))
  1472. >>> call(buildout)
  1473. <BLANKLINE>
  1474. Exit: False
  1475. >>> write('buildout.cfg',
  1476. ... '''
  1477. ... [buildout]
  1478. ... parts = x
  1479. ... ''')
  1480. >>> call(buildout) # doctest: +NORMALIZE_WHITESPACE
  1481. While:
  1482. Installing.
  1483. Getting section x.
  1484. Error: The referenced section, 'x', was not defined.
  1485. <BLANKLINE>
  1486. Exit: True
  1487. >>> write('setup.py',
  1488. ... '''
  1489. ... from setuptools import setup
  1490. ... setup(name='zc.buildout.testexit', entry_points={
  1491. ... 'zc.buildout': ['default = testexitrecipe:x']})
  1492. ... ''')
  1493. >>> write('testexitrecipe.py',
  1494. ... '''
  1495. ... x y
  1496. ... ''')
  1497. >>> write('buildout.cfg',
  1498. ... '''
  1499. ... [buildout]
  1500. ... parts = x
  1501. ... develop = .
  1502. ...
  1503. ... [x]
  1504. ... recipe = zc.buildout.testexit
  1505. ... ''')
  1506. >>> call(buildout) # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
  1507. Develop: '/sample-buildout/.'
  1508. While:
  1509. Installing.
  1510. Getting section x.
  1511. Initializing section x.
  1512. Loading zc.buildout recipe entry zc.buildout.testexit:default.
  1513. <BLANKLINE>
  1514. An internal error occured due to a bug in either zc.buildout or in a
  1515. recipe being used:
  1516. Traceback (most recent call last):
  1517. ...
  1518. x y
  1519. ^
  1520. SyntaxError: invalid syntax
  1521. <BLANKLINE>
  1522. Exit: True
  1523. """
  1524. def bug_59270_recipes_always_start_in_buildout_dir():
  1525. r"""
  1526. Recipes can rely on running from buildout directory
  1527. >>> mkdir('bad_start')
  1528. >>> write('bad_recipe.py',
  1529. ... r'''
  1530. ... import os, sys
  1531. ... def print_(*args):
  1532. ... sys.stdout.write(' '.join(map(str, args)) + '\n')
  1533. ... class Bad:
  1534. ... def __init__(self, *_):
  1535. ... print_(os.getcwd())
  1536. ... def install(self):
  1537. ... sys.stdout.write(os.getcwd()+'\n')
  1538. ... os.chdir('bad_start')
  1539. ... sys.stdout.write(os.getcwd()+'\n')
  1540. ... return ()
  1541. ... ''')
  1542. >>> write('setup.py',
  1543. ... '''
  1544. ... from setuptools import setup
  1545. ... setup(name='bad.test',
  1546. ... entry_points={'zc.buildout': ['default=bad_recipe:Bad']},)
  1547. ... ''')
  1548. >>> write('buildout.cfg',
  1549. ... '''
  1550. ... [buildout]
  1551. ... develop = .
  1552. ... parts = b1 b2
  1553. ... [b1]
  1554. ... recipe = bad.test
  1555. ... [b2]
  1556. ... recipe = bad.test
  1557. ... ''')
  1558. >>> os.chdir('bad_start')
  1559. >>> print_(system(join(sample_buildout, 'bin', 'buildout')
  1560. ... +' -c '+join(sample_buildout, 'buildout.cfg')), end='')
  1561. Develop: '/sample-buildout/.'
  1562. /sample-buildout
  1563. /sample-buildout
  1564. Installing b1.
  1565. /sample-buildout
  1566. /sample-buildout/bad_start
  1567. Installing b2.
  1568. /sample-buildout
  1569. /sample-buildout/bad_start
  1570. """
  1571. def bug_61890_file_urls_dont_seem_to_work_in_find_dash_links():
  1572. """
  1573. This bug arises from the fact that setuptools is overly restrictive
  1574. about file urls, requiring that file urls pointing at directories
  1575. must end in a slash.
  1576. >>> dest = tmpdir('sample-install')
  1577. >>> import zc.buildout.easy_install
  1578. >>> sample_eggs = sample_eggs.replace(os.path.sep, '/')
  1579. >>> ws = zc.buildout.easy_install.install(
  1580. ... ['demo==0.2'], dest,
  1581. ... links=['file://'+sample_eggs], index=link_server+'index/')
  1582. >>> for dist in ws:
  1583. ... print_(dist)
  1584. demo 0.2
  1585. demoneeded 1.1
  1586. >>> ls(dest)
  1587. d demo-0.2-py2.4.egg
  1588. d demoneeded-1.1-py2.4.egg
  1589. """
  1590. def bug_75607_buildout_should_not_run_if_it_creates_an_empty_buildout_cfg():
  1591. """
  1592. >>> remove('buildout.cfg')
  1593. >>> print_(system(buildout), end='')
  1594. While:
  1595. Initializing.
  1596. Error: Couldn't open /sample-buildout/buildout.cfg
  1597. """
  1598. def dealing_with_extremely_insane_dependencies():
  1599. r"""
  1600. There was a problem with analysis of dependencies taking a long
  1601. time, in part because the analysis would get repeated every time a
  1602. package was encountered in a dependency list. Now, we don't do
  1603. the analysis any more:
  1604. >>> import os
  1605. >>> for i in range(5):
  1606. ... p = 'pack%s' % i
  1607. ... deps = [('pack%s' % j) for j in range(5) if j is not i]
  1608. ... if i == 4:
  1609. ... deps.append('pack5')
  1610. ... mkdir(p)
  1611. ... write(p, 'setup.py',
  1612. ... 'from setuptools import setup\n'
  1613. ... 'setup(name=%r, install_requires=%r,\n'
  1614. ... ' url="u", author="a", author_email="e")\n'
  1615. ... % (p, deps))
  1616. >>> write('buildout.cfg',
  1617. ... '''
  1618. ... [buildout]
  1619. ... develop = pack0 pack1 pack2 pack3 pack4
  1620. ... parts = pack1
  1621. ...
  1622. ... [pack1]
  1623. ... recipe = zc.recipe.egg:eggs
  1624. ... eggs = pack0
  1625. ... ''')
  1626. >>> print_(system(buildout), end='') # doctest: +ELLIPSIS
  1627. Develop: '/sample-buildout/pack0'
  1628. Develop: '/sample-buildout/pack1'
  1629. Develop: '/sample-buildout/pack2'
  1630. Develop: '/sample-buildout/pack3'
  1631. Develop: '/sample-buildout/pack4'
  1632. Installing pack1.
  1633. ...
  1634. While:
  1635. Installing pack1.
  1636. Getting distribution for 'pack5'.
  1637. Error: Couldn't find a distribution for 'pack5'.
  1638. However, if we run in verbose mode, we can see why packages were included:
  1639. >>> print_(system(buildout+' -v'), end='') # doctest: +ELLIPSIS
  1640. Installing 'zc.buildout >=1.99', 'distribute'.
  1641. We have a develop egg: zc.buildout 1.0.0
  1642. We have the best distribution that satisfies 'distribute'.
  1643. Picked: distribute = 0.6
  1644. Develop: '/sample-buildout/pack0'
  1645. Develop: '/sample-buildout/pack1'
  1646. Develop: '/sample-buildout/pack2'
  1647. Develop: '/sample-buildout/pack3'
  1648. Develop: '/sample-buildout/pack4'
  1649. ...Installing pack1.
  1650. Installing 'pack0'.
  1651. We have a develop egg: pack0 0.0.0
  1652. Getting required 'pack4'
  1653. required by pack0 0.0.0.
  1654. We have a develop egg: pack4 0.0.0
  1655. Getting required 'pack3'
  1656. required by pack0 0.0.0.
  1657. required by pack4 0.0.0.
  1658. We have a develop egg: pack3 0.0.0
  1659. Getting required 'pack2'
  1660. required by pack0 0.0.0.
  1661. required by pack3 0.0.0.
  1662. required by pack4 0.0.0.
  1663. We have a develop egg: pack2 0.0.0
  1664. Getting required 'pack1'
  1665. required by pack0 0.0.0.
  1666. required by pack2 0.0.0.
  1667. required by pack3 0.0.0.
  1668. required by pack4 0.0.0.
  1669. We have a develop egg: pack1 0.0.0
  1670. Getting required 'pack5'
  1671. required by pack4 0.0.0.
  1672. We have no distributions for pack5 that satisfies 'pack5'.
  1673. ...
  1674. While:
  1675. Installing pack1.
  1676. Getting distribution for 'pack5'.
  1677. Error: Couldn't find a distribution for 'pack5'.
  1678. """
  1679. def read_find_links_to_load_extensions():
  1680. r"""
  1681. We'll create a wacky buildout extension that just announces itself when used:
  1682. >>> src = tmpdir('src')
  1683. >>> write(src, 'wacky_handler.py',
  1684. ... '''
  1685. ... import sys
  1686. ... def install(buildout=None):
  1687. ... sys.stdout.write("I am a wacky extension\\n")
  1688. ... ''')
  1689. >>> write(src, 'setup.py',
  1690. ... '''
  1691. ... from setuptools import setup
  1692. ... setup(name='wackyextension', version='1',
  1693. ... py_modules=['wacky_handler'],
  1694. ... entry_points = {'zc.buildout.extension':
  1695. ... ['default = wacky_handler:install']
  1696. ... },
  1697. ... )
  1698. ... ''')
  1699. >>> print_(system(buildout+' setup '+src+' bdist_egg'), end='')
  1700. ... # doctest: +ELLIPSIS
  1701. Running setup ...
  1702. creating 'dist/wackyextension-1-...
  1703. Now we'll create a buildout that uses this extension to load other packages:
  1704. >>> wacky_server = link_server.replace('http', 'wacky')
  1705. >>> dist = 'file://' + join(src, 'dist').replace(os.path.sep, '/')
  1706. >>> write('buildout.cfg',
  1707. ... '''
  1708. ... [buildout]
  1709. ... parts =
  1710. ... extensions = wackyextension
  1711. ... find-links = %(dist)s
  1712. ... ''' % globals())
  1713. When we run the buildout. it will load the extension from the dist
  1714. directory and then use the wacky extension to load the demo package
  1715. >>> print_(system(buildout), end='')
  1716. Getting distribution for 'wackyextension'.
  1717. Got wackyextension 1.
  1718. I am a wacky extension
  1719. """
  1720. def distributions_from_local_find_links_make_it_to_download_cache():
  1721. """
  1722. If we specify a local directory in find links, distors found there
  1723. need to make it to the download cache.
  1724. >>> mkdir('test')
  1725. >>> write('test', 'setup.py',
  1726. ... '''
  1727. ... from setuptools import setup
  1728. ... setup(name='foo')
  1729. ... ''')
  1730. >>> print_(system(buildout+' setup test bdist_egg')) # doctest: +ELLIPSIS
  1731. Running setup script 'test/setup.py'.
  1732. ...
  1733. >>> mkdir('cache')
  1734. >>> old_cache = zc.buildout.easy_install.download_cache('cache')
  1735. >>> list(zc.buildout.easy_install.install(['foo'], 'eggs',
  1736. ... links=[join('test', 'dist')])) # doctest: +ELLIPSIS
  1737. [foo 0.0.0 ...
  1738. >>> ls('cache')
  1739. - foo-0.0.0-py2.4.egg
  1740. >>> _ = zc.buildout.easy_install.download_cache(old_cache)
  1741. """
  1742. def create_egg(name, version, dest, install_requires=None,
  1743. dependency_links=None):
  1744. d = tempfile.mkdtemp()
  1745. if dest=='available':
  1746. extras = dict(x=['x'])
  1747. else:
  1748. extras = {}
  1749. if dependency_links:
  1750. links = 'dependency_links = %s, ' % dependency_links
  1751. else:
  1752. links = ''
  1753. if install_requires:
  1754. requires = 'install_requires = %s, ' % install_requires
  1755. else:
  1756. requires = ''
  1757. try:
  1758. open(os.path.join(d, 'setup.py'), 'w').write(
  1759. 'from setuptools import setup\n'
  1760. 'setup(name=%r, version=%r, extras_require=%r, zip_safe=True,\n'
  1761. ' %s %s py_modules=["setup"]\n)'
  1762. % (name, str(version), extras, requires, links)
  1763. )
  1764. zc.buildout.testing.bdist_egg(d, sys.executable, os.path.abspath(dest))
  1765. finally:
  1766. shutil.rmtree(d)
  1767. def prefer_final_permutation(existing, available):
  1768. for d in ('existing', 'available'):
  1769. if os.path.exists(d):
  1770. shutil.rmtree(d)
  1771. os.mkdir(d)
  1772. for version in existing:
  1773. create_egg('spam', version, 'existing')
  1774. for version in available:
  1775. create_egg('spam', version, 'available')
  1776. zc.buildout.easy_install.clear_index_cache()
  1777. [dist] = list(
  1778. zc.buildout.easy_install.install(['spam'], 'existing', ['available'])
  1779. )
  1780. if dist.extras:
  1781. print_('downloaded', dist.version)
  1782. else:
  1783. print_('had', dist.version)
  1784. sys.path_importer_cache.clear()
  1785. def prefer_final():
  1786. """
  1787. This test tests several permutations:
  1788. Using different version numbers to work around zip importer cache problems. :(
  1789. - With prefer final:
  1790. - no existing and newer dev available
  1791. >>> prefer_final_permutation((), [1, '2a1'])
  1792. downloaded 1
  1793. - no existing and only dev available
  1794. >>> prefer_final_permutation((), ['3a1'])
  1795. downloaded 3a1
  1796. - final existing and only dev acailable
  1797. >>> prefer_final_permutation([4], ['5a1'])
  1798. had 4
  1799. - final existing and newer final available
  1800. >>> prefer_final_permutation([6], [7])
  1801. downloaded 7
  1802. - final existing and same final available
  1803. >>> prefer_final_permutation([8], [8])
  1804. had 8
  1805. - final existing and older final available
  1806. >>> prefer_final_permutation([10], [9])
  1807. had 10
  1808. - only dev existing and final available
  1809. >>> prefer_final_permutation(['12a1'], [11])
  1810. downloaded 11
  1811. - only dev existing and no final available newer dev available
  1812. >>> prefer_final_permutation(['13a1'], ['13a2'])
  1813. downloaded 13a2
  1814. - only dev existing and no final available older dev available
  1815. >>> prefer_final_permutation(['15a1'], ['14a1'])
  1816. had 15a1
  1817. - only dev existing and no final available same dev available
  1818. >>> prefer_final_permutation(['16a1'], ['16a1'])
  1819. had 16a1
  1820. - Without prefer final:
  1821. >>> _ = zc.buildout.easy_install.prefer_final(False)
  1822. - no existing and newer dev available
  1823. >>> prefer_final_permutation((), [18, '19a1'])
  1824. downloaded 19a1
  1825. - no existing and only dev available
  1826. >>> prefer_final_permutation((), ['20a1'])
  1827. downloaded 20a1
  1828. - final existing and only dev acailable
  1829. >>> prefer_final_permutation([21], ['22a1'])
  1830. downloaded 22a1
  1831. - final existing and newer final available
  1832. >>> prefer_final_permutation([23], [24])
  1833. downloaded 24
  1834. - final existing and same final available
  1835. >>> prefer_final_permutation([25], [25])
  1836. had 25
  1837. - final existing and older final available
  1838. >>> prefer_final_permutation([27], [26])
  1839. had 27
  1840. - only dev existing and final available
  1841. >>> prefer_final_permutation(['29a1'], [28])
  1842. had 29a1
  1843. - only dev existing and no final available newer dev available
  1844. >>> prefer_final_permutation(['30a1'], ['30a2'])
  1845. downloaded 30a2
  1846. - only dev existing and no final available older dev available
  1847. >>> prefer_final_permutation(['32a1'], ['31a1'])
  1848. had 32a1
  1849. - only dev existing and no final available same dev available
  1850. >>> prefer_final_permutation(['33a1'], ['33a1'])
  1851. had 33a1
  1852. >>> _ = zc.buildout.easy_install.prefer_final(True)
  1853. """
  1854. def buildout_prefer_final_option():
  1855. """
  1856. The prefer-final buildout option can be used for override the default
  1857. preference for newer distributions.
  1858. The default is prefer-final = true:
  1859. >>> write('buildout.cfg',
  1860. ... '''
  1861. ... [buildout]
  1862. ... parts = eggs
  1863. ... find-links = %(link_server)s
  1864. ...
  1865. ... [eggs]
  1866. ... recipe = zc.recipe.egg:eggs
  1867. ... eggs = demo
  1868. ... ''' % globals())
  1869. >>> print_(system(buildout+' -v'), end='') # doctest: +ELLIPSIS
  1870. Installing 'zc.buildout >=1.99', 'distribute'.
  1871. ...
  1872. Picked: demo = 0.3
  1873. ...
  1874. Picked: demoneeded = 1.1
  1875. Here we see that the final versions of demo and demoneeded are used.
  1876. We get the same behavior if we add prefer-final = true
  1877. >>> write('buildout.cfg',
  1878. ... '''
  1879. ... [buildout]
  1880. ... parts = eggs
  1881. ... find-links = %(link_server)s
  1882. ... prefer-final = true
  1883. ...
  1884. ... [eggs]
  1885. ... recipe = zc.recipe.egg:eggs
  1886. ... eggs = demo
  1887. ... ''' % globals())
  1888. >>> print_(system(buildout+' -v'), end='') # doctest: +ELLIPSIS
  1889. Installing 'zc.buildout >=1.99', 'distribute'.
  1890. ...
  1891. Picked: demo = 0.3
  1892. ...
  1893. Picked: demoneeded = 1.1
  1894. If we specify prefer-final = false, we'll get the newest
  1895. distributions:
  1896. >>> write('buildout.cfg',
  1897. ... '''
  1898. ... [buildout]
  1899. ... parts = eggs
  1900. ... find-links = %(link_server)s
  1901. ... prefer-final = false
  1902. ...
  1903. ... [eggs]
  1904. ... recipe = zc.recipe.egg:eggs
  1905. ... eggs = demo
  1906. ... ''' % globals())
  1907. >>> print_(system(buildout+' -v'), end='') # doctest: +ELLIPSIS
  1908. Installing 'zc.buildout >=1.99', 'distribute'.
  1909. ...
  1910. Picked: demo = 0.4c1
  1911. ...
  1912. Picked: demoneeded = 1.2c1
  1913. We get an error if we specify anything but true or false:
  1914. >>> write('buildout.cfg',
  1915. ... '''
  1916. ... [buildout]
  1917. ... parts = eggs
  1918. ... find-links = %(link_server)s
  1919. ... prefer-final = no
  1920. ...
  1921. ... [eggs]
  1922. ... recipe = zc.recipe.egg:eggs
  1923. ... eggs = demo
  1924. ... ''' % globals())
  1925. >>> print_(system(buildout+' -v'), end='') # doctest: +ELLIPSIS
  1926. While:
  1927. Initializing.
  1928. Error: Invalid value for prefer-final option: no
  1929. """
  1930. def wont_downgrade_due_to_prefer_final():
  1931. r"""
  1932. If we install a non-final buildout version, we don't want to
  1933. downgrade just bcause we prefer-final. If a buildout version
  1934. isn't specified, either through buildout-version or a versions
  1935. entry, then buildout-version gets set to >=CURRENT_VERSION.
  1936. >>> write('buildout.cfg',
  1937. ... '''
  1938. ... [buildout]
  1939. ... parts =
  1940. ... ''')
  1941. >>> [v] = [l.split('=', 1)[1].strip()
  1942. ... for l in system(buildout+' -vv').split('\n')
  1943. ... if l.startswith('zc.buildout-version = ')]
  1944. >>> v == '>=' + pkg_resources.working_set.find(
  1945. ... pkg_resources.Requirement.parse('zc.buildout')
  1946. ... ).version
  1947. True
  1948. >>> write('buildout.cfg',
  1949. ... '''
  1950. ... [buildout]
  1951. ... parts =
  1952. ... zc.buildout-version = >.1
  1953. ... ''')
  1954. >>> [str(l.split('=', 1)[1].strip())
  1955. ... for l in system(buildout+' -vv').split('\n')
  1956. ... if l.startswith('zc.buildout-version =')]
  1957. ['>.1']
  1958. >>> write('buildout.cfg',
  1959. ... '''
  1960. ... [buildout]
  1961. ... parts =
  1962. ... versions = versions
  1963. ... [versions]
  1964. ... zc.buildout = 43
  1965. ... ''')
  1966. >>> print_(system(buildout+' -v'), end='') # doctest: +ELLIPSIS
  1967. Installing...
  1968. Error: Couldn't find a distribution for 'zc.buildout==43'.
  1969. """
  1970. def develop_with_modules():
  1971. """
  1972. Distribution setup scripts can import modules in the distribution directory:
  1973. >>> mkdir('foo')
  1974. >>> write('foo', 'bar.py',
  1975. ... '''# empty
  1976. ... ''')
  1977. >>> write('foo', 'setup.py',
  1978. ... '''
  1979. ... import bar
  1980. ... from setuptools import setup
  1981. ... setup(name="foo")
  1982. ... ''')
  1983. >>> write('buildout.cfg',
  1984. ... '''
  1985. ... [buildout]
  1986. ... develop = foo
  1987. ... parts =
  1988. ... ''')
  1989. >>> print_(system(join('bin', 'buildout')), end='')
  1990. Develop: '/sample-buildout/foo'
  1991. >>> ls('develop-eggs')
  1992. - foo.egg-link
  1993. - zc.recipe.egg.egg-link
  1994. """
  1995. def dont_pick_distribute_if_version_is_specified_when_required_by_src_dist():
  1996. """
  1997. When installing a source distribution, we got distribute without
  1998. honoring our version specification.
  1999. >>> mkdir('dist')
  2000. >>> write('setup.py',
  2001. ... '''
  2002. ... from setuptools import setup
  2003. ... setup(name='foo', version='1', py_modules=['foo'], zip_safe=True)
  2004. ... ''')
  2005. >>> write('foo.py', '')
  2006. >>> _ = system(buildout+' setup . sdist')
  2007. >>> write('buildout.cfg',
  2008. ... '''
  2009. ... [buildout]
  2010. ... parts = foo
  2011. ... find-links = dist
  2012. ... versions = versions
  2013. ... allow-picked-versions = false
  2014. ...
  2015. ... [versions]
  2016. ... distribute = %s
  2017. ... foo = 1
  2018. ...
  2019. ... [foo]
  2020. ... recipe = zc.recipe.egg
  2021. ... eggs = foo
  2022. ... ''' % pkg_resources.working_set.find(
  2023. ... pkg_resources.Requirement.parse('distribute')).version)
  2024. >>> print_(system(buildout), end='')
  2025. Installing foo.
  2026. Getting distribution for 'foo==1'.
  2027. Got foo 1.
  2028. """
  2029. def pyc_and_pyo_files_have_correct_paths():
  2030. r"""
  2031. >>> write('buildout.cfg',
  2032. ... '''
  2033. ... [buildout]
  2034. ... parts = eggs
  2035. ... find-links = %(link_server)s
  2036. ...
  2037. ... [eggs]
  2038. ... recipe = zc.recipe.egg
  2039. ... eggs = demo
  2040. ... interpreter = py
  2041. ... ''' % globals())
  2042. >>> _ = system(buildout)
  2043. >>> write('t.py',
  2044. ... r'''
  2045. ... import eggrecipedemo, eggrecipedemoneeded, sys
  2046. ... if sys.version_info > (3,):
  2047. ... code = lambda f: f.__code__
  2048. ... else:
  2049. ... code = lambda f: f.func_code
  2050. ... sys.stdout.write(code(eggrecipedemo.main).co_filename+'\n')
  2051. ... sys.stdout.write(code(eggrecipedemoneeded.f).co_filename+'\n')
  2052. ... ''')
  2053. >>> print_(system(join('bin', 'py')+ ' t.py'), end='')
  2054. /sample-buildout/eggs/demo-0.3-py2.4.egg/eggrecipedemo.py
  2055. /sample-buildout/eggs/demoneeded-1.1-py2.4.egg/eggrecipedemoneeded.py
  2056. """
  2057. def dont_mess_with_standard_dirs_with_variable_refs():
  2058. """
  2059. >>> write('buildout.cfg',
  2060. ... '''
  2061. ... [buildout]
  2062. ... eggs-directory = ${buildout:directory}/develop-eggs
  2063. ... parts =
  2064. ... ''' % globals())
  2065. >>> print_(system(buildout), end='')
  2066. """
  2067. def expand_shell_patterns_in_develop_paths():
  2068. """
  2069. Sometimes we want to include a number of eggs in some directory as
  2070. develop eggs, without explicitly listing all of them in our
  2071. buildout.cfg
  2072. >>> make_dist_that_requires(sample_buildout, 'sampley')
  2073. >>> make_dist_that_requires(sample_buildout, 'samplez')
  2074. Now, let's create a buildout that has a shell pattern that matches
  2075. both:
  2076. >>> write('buildout.cfg',
  2077. ... '''
  2078. ... [buildout]
  2079. ... parts = eggs
  2080. ... develop = sample*
  2081. ... find-links = %(link_server)s
  2082. ...
  2083. ... [eggs]
  2084. ... recipe = zc.recipe.egg
  2085. ... eggs = sampley
  2086. ... samplez
  2087. ... ''' % globals())
  2088. We can see that both eggs were found:
  2089. >>> print_(system(buildout), end='')
  2090. Develop: '/sample-buildout/sampley'
  2091. Develop: '/sample-buildout/samplez'
  2092. Installing eggs.
  2093. """
  2094. def warn_users_when_expanding_shell_patterns_yields_no_results():
  2095. """
  2096. Sometimes shell patterns do not match anything, so we want to warn
  2097. our users about it...
  2098. >>> make_dist_that_requires(sample_buildout, 'samplea')
  2099. So if we have 2 patterns, one that has a matching directory, and
  2100. another one that does not
  2101. >>> write('buildout.cfg',
  2102. ... '''
  2103. ... [buildout]
  2104. ... parts = eggs
  2105. ... develop = samplea grumble*
  2106. ... find-links = %(link_server)s
  2107. ...
  2108. ... [eggs]
  2109. ... recipe = zc.recipe.egg
  2110. ... eggs = samplea
  2111. ... ''' % globals())
  2112. We should get one of the eggs, and a warning for the pattern that
  2113. did not match anything.
  2114. >>> print_(system(buildout), end='')
  2115. Develop: '/sample-buildout/samplea'
  2116. Couldn't develop '/sample-buildout/grumble*' (not found)
  2117. Installing eggs.
  2118. """
  2119. def make_sure_versions_dont_cancel_extras():
  2120. """
  2121. There was a bug that caused extras in requirements to be lost.
  2122. >>> _ = open('setup.py', 'w').write('''
  2123. ... from setuptools import setup
  2124. ... setup(name='extraversiondemo', version='1.0',
  2125. ... url='x', author='x', author_email='x',
  2126. ... extras_require=dict(foo=['demo']), py_modules=['t'])
  2127. ... ''')
  2128. >>> open('README', 'w').close()
  2129. >>> open('t.py', 'w').close()
  2130. >>> sdist('.', sample_eggs)
  2131. >>> mkdir('dest')
  2132. >>> ws = zc.buildout.easy_install.install(
  2133. ... ['extraversiondemo[foo]'], 'dest', links=[sample_eggs],
  2134. ... versions = dict(extraversiondemo='1.0')
  2135. ... )
  2136. >>> sorted(dist.key for dist in ws)
  2137. ['demo', 'demoneeded', 'extraversiondemo']
  2138. """
  2139. def increment_buildout_options():
  2140. r"""
  2141. >>> write('b1.cfg', '''
  2142. ... [buildout]
  2143. ... parts = p1
  2144. ... x = 1
  2145. ... y = a
  2146. ... b
  2147. ...
  2148. ... [p1]
  2149. ... recipe = zc.buildout:debug
  2150. ... foo = ${buildout:x} ${buildout:y}
  2151. ... ''')
  2152. >>> write('buildout.cfg', '''
  2153. ... [buildout]
  2154. ... extends = b1.cfg
  2155. ... parts += p2
  2156. ... x += 2
  2157. ... y -= a
  2158. ...
  2159. ... [p2]
  2160. ... <= p1
  2161. ... ''')
  2162. >>> print_(system(buildout), end='')
  2163. Installing p1.
  2164. foo='1\n2 b'
  2165. recipe='zc.buildout:debug'
  2166. Installing p2.
  2167. foo='1\n2 b'
  2168. recipe='zc.buildout:debug'
  2169. """
  2170. def increment_buildout_with_multiple_extended_files_421022():
  2171. r"""
  2172. >>> write('foo.cfg', '''
  2173. ... [buildout]
  2174. ... foo-option = foo
  2175. ... [other]
  2176. ... foo-option = foo
  2177. ... ''')
  2178. >>> write('bar.cfg', '''
  2179. ... [buildout]
  2180. ... bar-option = bar
  2181. ... [other]
  2182. ... bar-option = bar
  2183. ... ''')
  2184. >>> write('buildout.cfg', '''
  2185. ... [buildout]
  2186. ... parts = p other
  2187. ... extends = bar.cfg foo.cfg
  2188. ... bar-option += baz
  2189. ... foo-option += ham
  2190. ...
  2191. ... [other]
  2192. ... recipe = zc.buildout:debug
  2193. ... bar-option += baz
  2194. ... foo-option += ham
  2195. ...
  2196. ... [p]
  2197. ... recipe = zc.buildout:debug
  2198. ... x = ${buildout:bar-option} ${buildout:foo-option}
  2199. ... ''')
  2200. >>> print_(system(buildout), end='')
  2201. Installing p.
  2202. recipe='zc.buildout:debug'
  2203. x='bar\nbaz foo\nham'
  2204. Installing other.
  2205. bar-option='bar\nbaz'
  2206. foo-option='foo\nham'
  2207. recipe='zc.buildout:debug'
  2208. """
  2209. def increment_on_command_line():
  2210. r"""
  2211. >>> write('buildout.cfg', '''
  2212. ... [buildout]
  2213. ... parts = p1
  2214. ... x = 1
  2215. ... y = a
  2216. ... b
  2217. ...
  2218. ... [p1]
  2219. ... recipe = zc.buildout:debug
  2220. ... foo = ${buildout:x} ${buildout:y}
  2221. ...
  2222. ... [p2]
  2223. ... <= p1
  2224. ... ''')
  2225. >>> print_(system(buildout+' buildout:parts+=p2 p1:foo+=bar'), end='')
  2226. Installing p1.
  2227. foo='1 a\nb\nbar'
  2228. recipe='zc.buildout:debug'
  2229. Installing p2.
  2230. foo='1 a\nb\nbar'
  2231. recipe='zc.buildout:debug'
  2232. """
  2233. def test_constrained_requirement():
  2234. """
  2235. zc.buildout.easy_install._constrained_requirement(constraint, requitement)
  2236. Transforms an environment by applying a constraint.
  2237. Here's a table of examples:
  2238. >>> from zc.buildout.easy_install import IncompatibleConstraintError
  2239. >>> examples = [
  2240. ... # original, constraint, transformed
  2241. ... ('x', '1', 'x==1'),
  2242. ... ('x>1', '2', 'x==2'),
  2243. ... ('x>3', '2', IncompatibleConstraintError),
  2244. ... ('x>1', '>2', 'x>2'),
  2245. ... ('x>1', '>=2', 'x>=2'),
  2246. ... ('x<1', '>2', IncompatibleConstraintError),
  2247. ... ('x<=1', '>=1', 'x>=1,<1,==1'),
  2248. ... ('x<3', '>1', 'x>1,<3'),
  2249. ... ('x==2', '>1', 'x==2'),
  2250. ... ('x==2', '>=2', 'x==2'),
  2251. ... ('x[y]', '1', 'x[y]==1'),
  2252. ... ('x[y]>1', '2', 'x[y]==2'),
  2253. ... ('x<3', '2', 'x==2'),
  2254. ... ('x<1', '2', IncompatibleConstraintError),
  2255. ... ('x<3', '<2', 'x<2'),
  2256. ... ('x<3', '<=2', 'x<=2'),
  2257. ... ('x>3', '<2', IncompatibleConstraintError),
  2258. ... ('x>=1', '<=1', 'x<=1,>1,==1'),
  2259. ... ('x<3', '>1', 'x>1,<3'),
  2260. ... ('x==2', '<3', 'x==2'),
  2261. ... ('x==2', '<=2', 'x==2'),
  2262. ... ('x[y]<3', '2', 'x[y]==2'),
  2263. ... ]
  2264. >>> from zc.buildout.easy_install import _constrained_requirement
  2265. >>> for o, c, e in examples:
  2266. ... try:
  2267. ... o = pkg_resources.Requirement.parse(o)
  2268. ... if isinstance(e, str):
  2269. ... e = pkg_resources.Requirement.parse(e)
  2270. ... g = _constrained_requirement(c, o)
  2271. ... except IncompatibleConstraintError:
  2272. ... g = IncompatibleConstraintError
  2273. ... if str(g) != str(e):
  2274. ... print_('failed', o, c, g, '!=', e)
  2275. """
  2276. def want_new_zcrecipeegg():
  2277. """
  2278. >>> write('buildout.cfg',
  2279. ... '''
  2280. ... [buildout]
  2281. ... parts = egg
  2282. ... [egg]
  2283. ... recipe = zc.recipe.egg <2dev
  2284. ... eggs = demo
  2285. ... ''')
  2286. >>> print_(system(join('bin', 'buildout')), end='') # doctest: +ELLIPSIS
  2287. The constraint, >=2.0.0a3,...
  2288. While:
  2289. Installing.
  2290. Getting section egg.
  2291. Initializing section egg.
  2292. Installing recipe zc.recipe.egg <2dev.
  2293. Error: Bad constraint >=2.0.0a3 zc.recipe.egg<2dev
  2294. """
  2295. def macro_inheritance_bug():
  2296. """
  2297. There was a bug preventing a section from using another section as a macro
  2298. if that section was extended with macros, and both sections were listed as
  2299. parts (phew!). The following contrived example demonstrates that this
  2300. now works.
  2301. >>> write('buildout.cfg',
  2302. ... '''
  2303. ... [buildout]
  2304. ... parts = foo bar
  2305. ... [base]
  2306. ... recipe = zc.recipe.egg
  2307. ... [foo]
  2308. ... <=base
  2309. ... eggs = zc.buildout
  2310. ... interpreter = python
  2311. ... [bar]
  2312. ... <=foo
  2313. ... interpreter = py
  2314. ... ''')
  2315. >>> print_(system(join('bin', 'buildout')), end='') # doctest: +ELLIPSIS
  2316. Installing foo.
  2317. ...
  2318. Installing bar.
  2319. ...
  2320. >>> ls("./bin")
  2321. - buildout
  2322. - py
  2323. - python
  2324. """
  2325. ######################################################################
  2326. def create_sample_eggs(test, executable=sys.executable):
  2327. assert executable == sys.executable, (executable, sys.executable)
  2328. write = test.globs['write']
  2329. dest = test.globs['sample_eggs']
  2330. tmp = tempfile.mkdtemp()
  2331. try:
  2332. write(tmp, 'README.txt', '')
  2333. for i in (0, 1, 2):
  2334. write(tmp, 'eggrecipedemoneeded.py', 'y=%s\ndef f():\n pass' % i)
  2335. c1 = i==2 and 'c1' or ''
  2336. write(
  2337. tmp, 'setup.py',
  2338. "from setuptools import setup\n"
  2339. "setup(name='demoneeded', py_modules=['eggrecipedemoneeded'],"
  2340. " zip_safe=True, version='1.%s%s', author='bob', url='bob', "
  2341. "author_email='bob')\n"
  2342. % (i, c1)
  2343. )
  2344. zc.buildout.testing.sdist(tmp, dest)
  2345. write(
  2346. tmp, 'distutilsscript',
  2347. '#!/usr/bin/python\n'
  2348. 'import sys; sys.stdout.write("distutils!\\n")\n'
  2349. )
  2350. write(
  2351. tmp, 'setup.py',
  2352. "from setuptools import setup\n"
  2353. "setup(name='other', zip_safe=False, version='1.0', "
  2354. "scripts=['distutilsscript'],"
  2355. "py_modules=['eggrecipedemoneeded'])\n"
  2356. )
  2357. zc.buildout.testing.bdist_egg(tmp, sys.executable, dest)
  2358. write(
  2359. tmp, 'setup.py',
  2360. "from setuptools import setup\n"
  2361. "setup(name='du_zipped', zip_safe=True, version='1.0', "
  2362. "scripts=['distutilsscript'],"
  2363. "py_modules=['eggrecipedemoneeded'])\n"
  2364. )
  2365. zc.buildout.testing.bdist_egg(tmp, executable, dest)
  2366. os.remove(os.path.join(tmp, 'distutilsscript'))
  2367. os.remove(os.path.join(tmp, 'eggrecipedemoneeded.py'))
  2368. for i in (1, 2, 3, 4):
  2369. write(
  2370. tmp, 'eggrecipedemo.py',
  2371. 'import eggrecipedemoneeded, sys\n'
  2372. 'def print_(*a):\n'
  2373. ' sys.stdout.write(" ".join(map(str, a))+"\\n")\n'
  2374. 'x=%s\n'
  2375. 'def main():\n'
  2376. ' print_(x, eggrecipedemoneeded.y)\n'
  2377. % i)
  2378. c1 = i==4 and 'c1' or ''
  2379. write(
  2380. tmp, 'setup.py',
  2381. "from setuptools import setup\n"
  2382. "setup(name='demo', py_modules=['eggrecipedemo'],"
  2383. " install_requires = 'demoneeded',"
  2384. " entry_points={'console_scripts': "
  2385. "['demo = eggrecipedemo:main']},"
  2386. " zip_safe=True, version='0.%s%s')\n" % (i, c1)
  2387. )
  2388. zc.buildout.testing.bdist_egg(tmp, dest)
  2389. write(tmp, 'eggrecipebigdemo.py', 'import eggrecipedemo')
  2390. write(
  2391. tmp, 'setup.py',
  2392. "from setuptools import setup\n"
  2393. "setup(name='bigdemo', "
  2394. " install_requires = 'demo',"
  2395. " py_modules=['eggrecipebigdemo'], "
  2396. " zip_safe=True, version='0.1')\n"
  2397. )
  2398. zc.buildout.testing.bdist_egg(tmp, sys.executable, dest)
  2399. finally:
  2400. shutil.rmtree(tmp)
  2401. extdemo_c2 = """
  2402. #include <Python.h>
  2403. #include <extdemo.h>
  2404. static PyMethodDef methods[] = {{NULL}};
  2405. PyMODINIT_FUNC
  2406. initextdemo(void)
  2407. {
  2408. PyObject *m;
  2409. m = Py_InitModule3("extdemo", methods, "");
  2410. #ifdef TWO
  2411. PyModule_AddObject(m, "val", PyInt_FromLong(2));
  2412. #else
  2413. PyModule_AddObject(m, "val", PyInt_FromLong(EXTDEMO));
  2414. #endif
  2415. }
  2416. """
  2417. extdemo_c3 = """
  2418. #include <Python.h>
  2419. #include <extdemo.h>
  2420. static PyMethodDef methods[] = {{NULL}};
  2421. #define MOD_DEF(ob, name, doc, methods) \
  2422. static struct PyModuleDef moduledef = { \
  2423. PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \
  2424. ob = PyModule_Create(&moduledef);
  2425. #define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void)
  2426. MOD_INIT(extdemo)
  2427. {
  2428. PyObject *m;
  2429. MOD_DEF(m, "extdemo", "", methods);
  2430. #ifdef TWO
  2431. PyModule_AddObject(m, "val", PyLong_FromLong(2));
  2432. #else
  2433. PyModule_AddObject(m, "val", PyLong_FromLong(EXTDEMO));
  2434. #endif
  2435. return m;
  2436. }
  2437. """
  2438. extdemo_c = sys.version_info[0] < 3 and extdemo_c2 or extdemo_c3
  2439. extdemo_setup_py = r"""
  2440. import os, sys
  2441. from distutils.core import setup, Extension
  2442. if os.environ.get('test-variable'):
  2443. print("Have environment test-variable: %%s" %% os.environ['test-variable'])
  2444. setup(name = "extdemo", version = "%s", url="http://www.zope.org",
  2445. author="Demo", author_email="demo@demo.com",
  2446. ext_modules = [Extension('extdemo', ['extdemo.c'])],
  2447. )
  2448. """
  2449. def add_source_dist(test, version=1.4):
  2450. if 'extdemo' not in test.globs:
  2451. test.globs['extdemo'] = test.globs['tmpdir']('extdemo')
  2452. tmp = test.globs['extdemo']
  2453. write = test.globs['write']
  2454. try:
  2455. write(tmp, 'extdemo.c', extdemo_c);
  2456. write(tmp, 'setup.py', extdemo_setup_py % version);
  2457. write(tmp, 'README', "");
  2458. write(tmp, 'MANIFEST.in', "include *.c\n");
  2459. test.globs['sdist'](tmp, test.globs['sample_eggs'])
  2460. except:
  2461. shutil.rmtree(tmp)
  2462. def easy_install_SetUp(test):
  2463. zc.buildout.testing.buildoutSetUp(test)
  2464. sample_eggs = test.globs['tmpdir']('sample_eggs')
  2465. test.globs['sample_eggs'] = sample_eggs
  2466. os.mkdir(os.path.join(sample_eggs, 'index'))
  2467. create_sample_eggs(test)
  2468. add_source_dist(test)
  2469. test.globs['link_server'] = test.globs['start_server'](
  2470. test.globs['sample_eggs'])
  2471. test.globs['update_extdemo'] = lambda : add_source_dist(test, 1.5)
  2472. zc.buildout.testing.install_develop('zc.recipe.egg', test)
  2473. def buildout_txt_setup(test):
  2474. zc.buildout.testing.buildoutSetUp(test)
  2475. mkdir = test.globs['mkdir']
  2476. eggs = os.environ['buildout-testing-index-url'][7:]
  2477. test.globs['sample_eggs'] = eggs
  2478. create_sample_eggs(test)
  2479. for name in os.listdir(eggs):
  2480. if '-' in name:
  2481. pname = name.split('-')[0]
  2482. if not os.path.exists(os.path.join(eggs, pname)):
  2483. mkdir(eggs, pname)
  2484. shutil.move(os.path.join(eggs, name),
  2485. os.path.join(eggs, pname, name))
  2486. dist = pkg_resources.working_set.find(
  2487. pkg_resources.Requirement.parse('zc.recipe.egg'))
  2488. mkdir(eggs, 'zc.recipe.egg')
  2489. zc.buildout.testing.sdist(
  2490. os.path.dirname(dist.location),
  2491. os.path.join(eggs, 'zc.recipe.egg'),
  2492. )
  2493. egg_parse = re.compile('([0-9a-zA-Z_.]+)-([0-9a-zA-Z_.]+)-py(\d[.]\d).egg$'
  2494. ).match
  2495. def makeNewRelease(project, ws, dest, version='99.99'):
  2496. dist = ws.find(pkg_resources.Requirement.parse(project))
  2497. eggname, oldver, pyver = egg_parse(
  2498. os.path.basename(dist.location)
  2499. ).groups()
  2500. dest = os.path.join(dest, "%s-%s-py%s.egg" % (eggname, version, pyver))
  2501. if os.path.isfile(dist.location):
  2502. shutil.copy(dist.location, dest)
  2503. zip = zipfile.ZipFile(dest, 'a')
  2504. zip.writestr(
  2505. 'EGG-INFO/PKG-INFO',
  2506. ((zip.read('EGG-INFO/PKG-INFO').decode()
  2507. ).replace("Version: %s" % oldver,
  2508. "Version: %s" % version)
  2509. ).encode()
  2510. )
  2511. zip.close()
  2512. else:
  2513. shutil.copytree(dist.location, dest)
  2514. info_path = os.path.join(dest, 'EGG-INFO', 'PKG-INFO')
  2515. info = open(info_path).read().replace("Version: %s" % oldver,
  2516. "Version: %s" % version)
  2517. open(info_path, 'w').write(info)
  2518. def getWorkingSetWithBuildoutEgg(test):
  2519. sample_buildout = test.globs['sample_buildout']
  2520. eggs = os.path.join(sample_buildout, 'eggs')
  2521. # If the zc.buildout dist is a develop dist, convert it to a
  2522. # regular egg in the sample buildout
  2523. req = pkg_resources.Requirement.parse('zc.buildout')
  2524. dist = pkg_resources.working_set.find(req)
  2525. if dist.precedence == pkg_resources.DEVELOP_DIST:
  2526. # We have a develop egg, create a real egg for it:
  2527. here = os.getcwd()
  2528. os.chdir(os.path.dirname(dist.location))
  2529. zc.buildout.easy_install.call_subprocess(
  2530. [sys.executable,
  2531. os.path.join(os.path.dirname(dist.location), 'setup.py'),
  2532. '-q', 'bdist_egg', '-d', eggs],
  2533. env=dict(os.environ,
  2534. PYTHONPATH=pkg_resources.working_set.find(
  2535. pkg_resources.Requirement.parse('distribute')
  2536. ).location,
  2537. ),
  2538. )
  2539. os.chdir(here)
  2540. os.remove(os.path.join(eggs, 'zc.buildout.egg-link'))
  2541. # Rebuild the buildout script
  2542. ws = pkg_resources.WorkingSet([eggs])
  2543. ws.require('zc.buildout')
  2544. zc.buildout.easy_install.scripts(
  2545. ['zc.buildout'], ws, sys.executable,
  2546. os.path.join(sample_buildout, 'bin'))
  2547. else:
  2548. ws = pkg_resources.working_set
  2549. return ws
  2550. def updateSetup(test):
  2551. zc.buildout.testing.buildoutSetUp(test)
  2552. new_releases = test.globs['tmpdir']('new_releases')
  2553. test.globs['new_releases'] = new_releases
  2554. ws = getWorkingSetWithBuildoutEgg(test)
  2555. # now let's make the new releases
  2556. makeNewRelease('zc.buildout', ws, new_releases)
  2557. os.mkdir(os.path.join(new_releases, 'zc.buildout'))
  2558. makeNewRelease('distribute', ws, new_releases)
  2559. os.mkdir(os.path.join(new_releases, 'distribute'))
  2560. bootstrap_py = os.path.join(
  2561. os.path.dirname(os.path.dirname(os.path.dirname(
  2562. os.path.dirname(__file__)))),
  2563. 'bootstrap', 'bootstrap.py')
  2564. def bootstrapSetup(test):
  2565. buildout_txt_setup(test)
  2566. test.globs['link_server'] = test.globs['start_server'](
  2567. test.globs['sample_eggs'])
  2568. sample_eggs = test.globs['sample_eggs']
  2569. ws = getWorkingSetWithBuildoutEgg(test)
  2570. makeNewRelease('zc.buildout', ws, sample_eggs, '2.0.0')
  2571. makeNewRelease('zc.buildout', ws, sample_eggs, '22.0.0')
  2572. os.environ['bootstrap-testing-find-links'] = test.globs['link_server']
  2573. test.globs['bootstrap_py'] = bootstrap_py
  2574. normalize_bang = (
  2575. re.compile(re.escape('#!'+
  2576. zc.buildout.easy_install._safe_arg(sys.executable))),
  2577. '#!/usr/local/bin/python2.7',
  2578. )
  2579. normalize_S = (
  2580. re.compile(r'#!/usr/local/bin/python2.7 -S'),
  2581. '#!/usr/local/bin/python2.7',
  2582. )
  2583. def test_suite():
  2584. test_suite = [
  2585. manuel.testing.TestSuite(
  2586. manuel.doctest.Manuel() + manuel.capture.Manuel(),
  2587. 'configparser.test'),
  2588. manuel.testing.TestSuite(
  2589. manuel.doctest.Manuel(
  2590. checker=renormalizing.RENormalizing([
  2591. zc.buildout.testing.normalize_path,
  2592. zc.buildout.testing.normalize_endings,
  2593. zc.buildout.testing.normalize_script,
  2594. zc.buildout.testing.normalize_egg_py,
  2595. zc.buildout.testing.not_found,
  2596. (re.compile(r'zc.buildout-version = >=\S+'), ''),
  2597. (re.compile(r"Installing 'zc.buildout >=\S+"), ''),
  2598. (re.compile('__buildout_signature__ = recipes-\S+'),
  2599. '__buildout_signature__ = recipes-SSSSSSSSSSS'),
  2600. (re.compile('executable = [\S ]+python\S*', re.I),
  2601. 'executable = python'),
  2602. (re.compile('[-d] (setuptools|distribute)-\S+[.]egg'),
  2603. 'setuptools.egg'),
  2604. (re.compile('zc.buildout(-\S+)?[.]egg(-link)?'),
  2605. 'zc.buildout.egg'),
  2606. (re.compile('creating \S*setup.cfg'), 'creating setup.cfg'),
  2607. (re.compile('hello\%ssetup' % os.path.sep), 'hello/setup'),
  2608. (re.compile('Picked: (\S+) = \S+'),
  2609. 'Picked: \\1 = V.V'),
  2610. (re.compile(r'We have a develop egg: zc.buildout (\S+)'),
  2611. 'We have a develop egg: zc.buildout X.X.'),
  2612. (re.compile(r'\\[\\]?'), '/'),
  2613. (re.compile('WindowsError'), 'OSError'),
  2614. (re.compile(r'\[Error \d+\] Cannot create a file '
  2615. r'when that file already exists: '),
  2616. '[Errno 17] File exists: '
  2617. ),
  2618. (re.compile('distribute'), 'setuptools'),
  2619. (re.compile('Got zc.recipe.egg \S+'), 'Got zc.recipe.egg'),
  2620. ])
  2621. ) + manuel.capture.Manuel(),
  2622. 'buildout.txt',
  2623. setUp=buildout_txt_setup,
  2624. tearDown=zc.buildout.testing.buildoutTearDown,
  2625. ),
  2626. doctest.DocFileSuite(
  2627. 'runsetup.txt', 'repeatable.txt', 'setup.txt',
  2628. setUp=zc.buildout.testing.buildoutSetUp,
  2629. tearDown=zc.buildout.testing.buildoutTearDown,
  2630. checker=renormalizing.RENormalizing([
  2631. zc.buildout.testing.normalize_path,
  2632. zc.buildout.testing.normalize_endings,
  2633. zc.buildout.testing.normalize_script,
  2634. zc.buildout.testing.normalize_egg_py,
  2635. zc.buildout.testing.not_found,
  2636. (re.compile(r"Installing 'zc.buildout >=\S+"), ''),
  2637. (re.compile(r"Getting distribution for 'zc.buildout >=\S+"),
  2638. ''),
  2639. (re.compile('__buildout_signature__ = recipes-\S+'),
  2640. '__buildout_signature__ = recipes-SSSSSSSSSSS'),
  2641. (re.compile('[-d] distribute-\S+[.]egg'), 'distribute.egg'),
  2642. (re.compile('zc.buildout(-\S+)?[.]egg(-link)?'),
  2643. 'zc.buildout.egg'),
  2644. (re.compile('creating \S*setup.cfg'), 'creating setup.cfg'),
  2645. (re.compile('hello\%ssetup' % os.path.sep), 'hello/setup'),
  2646. (re.compile('Picked: (\S+) = \S+'),
  2647. 'Picked: \\1 = V.V'),
  2648. (re.compile(r'We have a develop egg: zc.buildout (\S+)'),
  2649. 'We have a develop egg: zc.buildout X.X.'),
  2650. (re.compile(r'\\[\\]?'), '/'),
  2651. (re.compile('WindowsError'), 'OSError'),
  2652. (re.compile(r'\[Error 17\] Cannot create a file '
  2653. r'when that file already exists: '),
  2654. '[Errno 17] File exists: '
  2655. ),
  2656. (re.compile('executable = %s' % re.escape(sys.executable)),
  2657. 'executable = python'),
  2658. ])
  2659. ),
  2660. doctest.DocFileSuite(
  2661. 'debugging.txt',
  2662. setUp=zc.buildout.testing.buildoutSetUp,
  2663. tearDown=zc.buildout.testing.buildoutTearDown,
  2664. checker=renormalizing.RENormalizing([
  2665. zc.buildout.testing.normalize_path,
  2666. zc.buildout.testing.normalize_endings,
  2667. zc.buildout.testing.normalize_exception_type_for_python_2_and_3,
  2668. zc.buildout.testing.not_found,
  2669. (re.compile('zc.buildout.buildout.MissingOption'),
  2670. 'MissingOption'),
  2671. (re.compile(r'\S+buildout.py'), 'buildout.py'),
  2672. (re.compile(r'line \d+'), 'line NNN'),
  2673. (re.compile(r'py\(\d+\)'), 'py(NNN)'),
  2674. ])
  2675. ),
  2676. doctest.DocFileSuite(
  2677. 'update.txt',
  2678. setUp=updateSetup,
  2679. tearDown=zc.buildout.testing.buildoutTearDown,
  2680. checker=renormalizing.RENormalizing([
  2681. (re.compile(r'(zc.buildout|distribute)-\d+[.]\d+\S*'
  2682. '-py\d.\d.egg'),
  2683. '\\1.egg'),
  2684. zc.buildout.testing.normalize_path,
  2685. zc.buildout.testing.normalize_endings,
  2686. zc.buildout.testing.normalize_script,
  2687. zc.buildout.testing.normalize_egg_py,
  2688. zc.buildout.testing.not_found,
  2689. normalize_bang,
  2690. normalize_S,
  2691. (re.compile(r"Installing 'zc.buildout >=\S+"), ''),
  2692. (re.compile(r"Getting distribution for 'zc.buildout>=\S+"),
  2693. ''),
  2694. (re.compile('99[.]99'), 'NINETYNINE.NINETYNINE'),
  2695. (re.compile(
  2696. r'(zc.buildout|distribute)( version)? \d+[.]\d+\S*'),
  2697. '\\1 V.V'),
  2698. (re.compile('[-d] distribute'), '- distribute'),
  2699. ])
  2700. ),
  2701. doctest.DocFileSuite(
  2702. 'easy_install.txt', 'downloadcache.txt', 'dependencylinks.txt',
  2703. 'allowhosts.txt',
  2704. setUp=easy_install_SetUp,
  2705. tearDown=zc.buildout.testing.buildoutTearDown,
  2706. checker=renormalizing.RENormalizing([
  2707. zc.buildout.testing.normalize_script,
  2708. zc.buildout.testing.normalize_path,
  2709. zc.buildout.testing.normalize_endings,
  2710. zc.buildout.testing.normalize_egg_py,
  2711. zc.buildout.testing.normalize_exception_type_for_python_2_and_3,
  2712. zc.buildout.testing.not_found,
  2713. normalize_bang,
  2714. normalize_S,
  2715. (re.compile('[-d] distribute-\S+[.]egg'), 'distribute.egg'),
  2716. (re.compile(r'\\[\\]?'), '/'),
  2717. (re.compile('(\n?)- ([a-zA-Z_.-]+)\n- \\2.exe\n'),
  2718. '\\1- \\2\n'),
  2719. ]+(sys.version_info < (2, 5) and [
  2720. (re.compile('.*No module named runpy.*', re.S), ''),
  2721. (re.compile('.*usage: pdb.py scriptfile .*', re.S), ''),
  2722. (re.compile('.*Error: what does not exist.*', re.S), ''),
  2723. ] or [])),
  2724. ),
  2725. doctest.DocFileSuite(
  2726. 'download.txt', 'extends-cache.txt',
  2727. setUp=easy_install_SetUp,
  2728. tearDown=zc.buildout.testing.buildoutTearDown,
  2729. optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS,
  2730. checker=renormalizing.RENormalizing([
  2731. zc.buildout.testing.normalize_exception_type_for_python_2_and_3,
  2732. zc.buildout.testing.not_found,
  2733. (re.compile(' at -?0x[^>]+'), '<MEM ADDRESS>'),
  2734. (re.compile('http://localhost:[0-9]{4,5}/'),
  2735. 'http://localhost/'),
  2736. (re.compile('[0-9a-f]{32}'), '<MD5 CHECKSUM>'),
  2737. zc.buildout.testing.normalize_path,
  2738. zc.buildout.testing.ignore_not_upgrading,
  2739. ]),
  2740. ),
  2741. doctest.DocTestSuite(
  2742. setUp=easy_install_SetUp,
  2743. tearDown=zc.buildout.testing.buildoutTearDown,
  2744. checker=renormalizing.RENormalizing([
  2745. zc.buildout.testing.normalize_path,
  2746. zc.buildout.testing.normalize_endings,
  2747. zc.buildout.testing.normalize_script,
  2748. zc.buildout.testing.normalize_egg_py,
  2749. zc.buildout.testing.normalize___pycache__,
  2750. zc.buildout.testing.not_found,
  2751. (re.compile(r"Installing 'zc.buildout >=\S+"), 'Installing '),
  2752. (re.compile(r'^(\w+\.)*(Missing\w+: )'), '\2'),
  2753. (re.compile("buildout: Running \S*setup.py"),
  2754. 'buildout: Running setup.py'),
  2755. (re.compile('distribute-\S+-'),
  2756. 'distribute.egg'),
  2757. (re.compile('zc.buildout-\S+-'),
  2758. 'zc.buildout.egg'),
  2759. (re.compile('File "\S+one.py"'),
  2760. 'File "one.py"'),
  2761. (re.compile(r'We have a develop egg: (\S+) (\S+)'),
  2762. r'We have a develop egg: \1 V'),
  2763. (re.compile('Picked: distribute = \S+'),
  2764. 'Picked: distribute = V'),
  2765. (re.compile(r'\\[\\]?'), '/'),
  2766. (re.compile(
  2767. '-q develop -mxN -d "/sample-buildout/develop-eggs'),
  2768. '-q develop -mxN -d /sample-buildout/develop-eggs'
  2769. ),
  2770. (re.compile(r'^[*]...'), '...'),
  2771. # for
  2772. # bug_92891
  2773. # bootstrap_crashes_with_egg_recipe_in_buildout_section
  2774. (re.compile(r"Unused options for buildout: 'eggs' 'scripts'\."),
  2775. "Unused options for buildout: 'scripts' 'eggs'."),
  2776. ]),
  2777. ),
  2778. zc.buildout.rmtree.test_suite(),
  2779. doctest.DocFileSuite(
  2780. 'windows.txt',
  2781. setUp=zc.buildout.testing.buildoutSetUp,
  2782. tearDown=zc.buildout.testing.buildoutTearDown,
  2783. checker=renormalizing.RENormalizing([
  2784. zc.buildout.testing.normalize_path,
  2785. zc.buildout.testing.normalize_endings,
  2786. zc.buildout.testing.normalize_script,
  2787. zc.buildout.testing.normalize_egg_py,
  2788. zc.buildout.testing.not_found,
  2789. (re.compile('__buildout_signature__ = recipes-\S+'),
  2790. '__buildout_signature__ = recipes-SSSSSSSSSSS'),
  2791. (re.compile('[-d] distribute-\S+[.]egg'), 'distribute.egg'),
  2792. (re.compile('zc.buildout(-\S+)?[.]egg(-link)?'),
  2793. 'zc.buildout.egg'),
  2794. (re.compile('creating \S*setup.cfg'), 'creating setup.cfg'),
  2795. (re.compile('hello\%ssetup' % os.path.sep), 'hello/setup'),
  2796. (re.compile('Picked: (\S+) = \S+'),
  2797. 'Picked: \\1 = V.V'),
  2798. (re.compile(r'We have a develop egg: zc.buildout (\S+)'),
  2799. 'We have a develop egg: zc.buildout X.X.'),
  2800. (re.compile(r'\\[\\]?'), '/'),
  2801. (re.compile('WindowsError'), 'OSError'),
  2802. (re.compile(r'\[Error 17\] Cannot create a file '
  2803. r'when that file already exists: '),
  2804. '[Errno 17] File exists: '
  2805. ),
  2806. ])
  2807. ),
  2808. doctest.DocFileSuite(
  2809. 'testing_bugfix.txt'),
  2810. ]
  2811. # adding bootstrap.txt doctest to the suite
  2812. # only if bootstrap.py is present
  2813. if os.path.exists(bootstrap_py):
  2814. test_suite.append(doctest.DocFileSuite(
  2815. 'bootstrap.txt', 'bootstrap_cl_settings.test',
  2816. setUp=bootstrapSetup,
  2817. tearDown=zc.buildout.testing.buildoutTearDown,
  2818. checker=renormalizing.RENormalizing([
  2819. zc.buildout.testing.normalize_path,
  2820. zc.buildout.testing.normalize_endings,
  2821. zc.buildout.testing.normalize_script,
  2822. zc.buildout.testing.not_found,
  2823. normalize_bang,
  2824. (re.compile('Downloading.*distribute.*egg\n'), ''),
  2825. ]),
  2826. ))
  2827. return unittest.TestSuite(test_suite)