Skip to content
Browse files

[svn r20974] Renaming pyinstall to pip

  • Loading branch information...
0 parents commit c2000d7de68ef955a85cf8f5f6e78d4f25c10103 @ianb ianb committed
Showing with 3,384 additions and 0 deletions.
  1. +133 −0 docs/conf.py
  2. +192 −0 docs/index.txt
  3. +67 −0 docs/news.txt
  4. +51 −0 docs/requirement-format.txt
  5. +2,538 −0 pyinstall.py
  6. +9 −0 regen-docs
  7. +3 −0 setup.cfg
  8. +41 −0 setup.py
  9. +90 −0 tests/test_all_pyinstall.py
  10. +41 −0 tests/test_basic.txt
  11. +62 −0 tests/test_freeze.txt
  12. +43 −0 tests/test_proxy.txt
  13. +76 −0 tests/test_pyinstall.py
  14. +38 −0 tests/test_requirements.txt
133 docs/conf.py
@@ -0,0 +1,133 @@
+# -*- coding: utf-8 -*-
+#
+# Paste documentation build configuration file, created by
+# sphinx-quickstart on Tue Apr 22 22:08:49 2008.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# The contents of this file are pickled, so don't put values in the namespace
+# that aren't pickleable (module imports are okay, they're removed automatically).
+#
+# All configuration values have a default value; values that are commented out
+# serve to show the default value.
+
+import sys
+
+# If your extensions are in another directory, add it here.
+#sys.path.append('some/directory')
+
+# General configuration
+# ---------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+#extensions = ['sphinx.ext.autodoc']
+extensions = []
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.txt'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General substitutions.
+project = 'pyinstall'
+copyright = '2008, The Open Planning Project'
+
+# The default replacements for |version| and |release|, also used in various
+# other places throughout the built documents.
+#
+# The short X.Y version.
+version = '0.1.3'
+# The full version, including alpha/beta/rc tags.
+release = '0.1.3'
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+unused_docs = []
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+
+# Options for HTML output
+# -----------------------
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+html_style = 'default.css'
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Content template for the index page.
+#html_index = ''
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_use_modindex = True
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+#html_copy_source = True
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'pyinstalldocs'
+
+
+# Options for LaTeX output
+# ------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, document class [howto/manual]).
+#latex_documents = []
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
192 docs/index.txt
@@ -0,0 +1,192 @@
+pyinstall
+=========
+
+.. toctree::
+
+ news
+ requirement-format
+
+.. comment: split here
+
+.. contents::
+
+Introduction
+------------
+
+pyinstall is a replacement for `easy_install
+<http://peak.telecommunity.com/DevCenter/EasyInstall>`_. It uses mostly the
+same techniques for finding packages, so packages that were made
+easy_installable should be pyinstallable as well.
+
+pyinstall is meant to improve on easy_install. Some of the improvements:
+
+* All packages are downloaded before installation. Partially-completed
+ installation doesn't occur as a result.
+
+* Care is taken to present useful output on the console.
+
+* The reasons for actions are kept track of. For instance, if a package is
+ being installed, pyinstall keeps track of why that package was required.
+
+* Error messages should be useful.
+
+* The code is relatively concise and cohesive, making it easier to use
+ programmatically.
+
+* Packages don't have to be installed as egg archives, they can be installed
+ flat (while keeping the egg metadata).
+
+* Maybe features like native support for other version control systems, or
+ uninstallation, will get added. (They might get added to easy_install, but I
+ think the chance for pyinstall is higher.)
+
+Also, pyinstall will eventually be merged directly with poacheggs, making it
+simple to define fixed sets of requirements and reliably reproduce a set of
+packages.
+
+pyinstall is complementary with `virtualenv
+<http://pypi.python.org/pypi/virtualenv>`_, and it is encouraged that you use
+virtualenv to isolate your installation.
+
+Community
+---------
+
+The homepage for pyinstall is temporarily located `on PyPI
+<http://pypi.python.org/pypi/pyinstall>`_ -- a more proper homepage
+will follow. Bugs can go on the `poacheggs Trac instance
+<http://trac.openplans.org/poacheggs/>`_ (probably that will change
+too). Discussion should happen on the `virtualenv email group
+<http://groups.google.com/group/python-virtualenv?hl=en>`_.
+
+Differences From easy_install
+-----------------------------
+
+pyinstall cannot install some packages. Specifically:
+
+* It cannot install from eggs. It only installs from source. (Maybe this will
+ be changed sometime, but it's low priority.)
+
+* It doesn't understand Setuptools extras (like ``package[test]``). This should
+ be added eventually.
+
+* It is incompatible with some packages that customize distutils or setuptools
+ in their ``setup.py`` files.
+
+* Maybe it doesn't work on Windows. At least, the author doesn't test on
+ Windows often.
+
+* It also has some extra features. Extra features the author thinks are great.
+
+.. _`requirements file`:
+
+Requirements Files
+------------------
+
+When installing software, and Python packages in particular, it's common that
+you get a lot of libraries installed. You just did ``easy_install MyPackage``
+and you get a dozen packages. Each of these packages has its own version.
+
+Maybe you ran that installation and it works. Great! Will it keep working?
+Did you have to provide special options to get it to find everything? Did you
+have to install a bunch of other optional pieces? Most of all, will you be able
+to do it again?
+
+If you've ever tried to setup an application on a new system, or with slightly
+updated pieces, and had it fail, pyinstall requirements are for you. If you
+haven't had this problem then you will eventually, so pyinstall requirements are
+for you too -- requirements make explicit, repeatable installation of packages.
+
+So what are requirements files? They are very simple: lists of packages to
+install. Instead of running something like ``pyinstall MyApp`` and getting
+whatever libraries come along, you can create a requirements file something like::
+
+ MyApp
+ Framework==0.9.4
+ Library>=0.2
+
+Then, regardless of what MyApp lists in ``setup.py``, you'll get a specific
+version of Framework and at least the 0.2 version of Library. (You might think
+you could list these specific versions in ``setup.py`` -- try it and you'll
+quickly see why that doesn't work.) You can add optional libraries and support
+tools that MyApp doesn't strictly require.
+
+You can also include "editable" packages -- packages that are checked out from
+subversion (in the future other VCS will be supported). These are just like
+using the ``-e`` option to pyinstall. They look like::
+
+ -e svn+http://myrepo/svn/MyApp#egg=MyApp
+
+You have to start the URL with ``svn+`` (eventually you'll be able to use
+``hg+`` etc), and you have to include ``#egg=Package`` so pyinstall knows what
+to expect at that URL. You can also include ``@rev`` in the URL, e.g., ``@275``
+to check out revision 275.
+
+Freezing Requirements
+---------------------
+
+So you have a working set of packages, and you want to be able to install them
+elsewhere. `Requirements files`_ let you install exact versions, but it won't
+tell you what all the exact versions are.
+
+To create a new requirements file from a known working environment, use::
+
+ $ pyinstall.py --freeze=stable-req.txt
+
+This will write a listing of *all* installed libraries to ``stable-req.txt``
+with exact versions for every library. You may want to edit the file down after
+generating (e.g., to eliminate unnecessary libraries), but it'll give you a
+stable starting point for constructing your requirements file.
+
+You can also give it an existing requirements file, and it will use that as a
+sort of template for the new file. So if you do::
+
+ $ pyinstall.py --freeze=stable-req.txt -r devel-req.txt
+
+it will keep the packages listed in ``devel-req.txt`` in order and preserve
+comments.
+
+Bundles
+-------
+
+Another way to distribute a set of libraries is a bundle format (specific to
+pyinstall). This format is not stable at this time (there simply hasn't been
+any feedback, nor a great deal of thought). A bundle file contains all the
+source for your package, and you can have pyinstall install then all together.
+Once you have the bundle file further network access won't be necessary. To
+build a bundle file, do::
+
+ $ pyinstall.py --bundle=MyApp.pybundle MyApp
+
+(Using a `requirements file`_ would be wise.) Then someone else can get the
+file ``MyApp.pybundle`` and run::
+
+ $ pyinstall.py MyApp.pybundle
+
+This is *not* a binary format. This only packages source. If you have binary
+packages, then the person who installs the files will have to have a compiler,
+any necessary headers installed, etc. Binary packages are hard, this is
+relatively easy.
+
+Using pyinstall With virtualenv
+-------------------------------
+
+pyinstall is most nutritious when used with `virtualenv
+<http://pypi.python.org/pypi/virtualenv>`_. One of the reasons pyinstall
+doesn't install "multi-version" eggs is that virtualenv removes much of the need
+for it.
+
+pyinstall does not have to be installed to use it, you can run ``python
+pyinstall.py`` and it will work. This is intended to avoid the bootstrapping
+problem of installation. You can also run pyinstall inside any virtualenv
+environment, like::
+
+ $ virtualenv new-env/
+ ... creates new-env/ ...
+ $ pyinstall.py -E new-env/ MyPackage
+
+This is exactly equivalent to::
+
+ $ ./new-env/bin/python pyinstall.py MyPackage
+
+Except, if you have ``virtualenv`` installed and the path ``new-env/``
+doesn't exist, then a new virtualenv will be created.
67 docs/news.txt
@@ -0,0 +1,67 @@
+News for pyinstall
+==================
+
+0.1.4
+-----
+
+* Added an option ``--install-option`` to pass options to pass
+ arguments to ``setup.py install``
+
+* ``.svn/`` directories are no longer included in bundles, as these
+ directories are specific to a version of svn -- if you build a
+ bundle on a system with svn 1.5, you can't use the checkout on a
+ system with svn 1.4. Instead a file ``svn-checkout.txt`` is
+ included that notes the original location and revision, and the
+ command you can use to turn it back into an svn checkout. (Probably
+ unpacking the bundle should, maybe optionally, recreate this
+ information -- but that is not currently implemented, and it would
+ require network access.)
+
+* Avoid ambiguities over project name case, where for instance
+ MyPackage and mypackage would be considered different packages.
+ This in particular caused problems on Macs, where ``MyPackage/`` and
+ ``mypackage/`` are the same directory.
+
+* Added support for an environmental variable
+ ``$PYINSTALL_DOWNLOAD_CACHE`` which will cache package downloads, so
+ future installations won't require large downloads. Network access
+ is still required, but just some downloads will be avoided when
+ using this.
+
+0.1.3
+-----
+
+* Always use ``svn checkout`` (not ``export``) so that
+ ``tag_svn_revision`` settings give the revision of the package.
+
+* Don't update checkouts that came from ``.pybundle`` files.
+
+0.1.2
+-----
+
+* Improve error text when there are errors fetching HTML pages when
+ seeking packages.
+
+* Improve bundles: include empty directories, make them work with
+ editable packages.
+
+* If you use ``-E env`` and the environment ``env/`` doesn't exist, a
+ new virtual environment will be created.
+
+* Fix ``dependency_links`` for finding packages.
+
+0.1.1
+-----
+
+* Fixed a NameError exception when running pyinstall outside of a
+ virtualenv environment.
+
+* Added HTTP proxy support (from Prabhu Ramachandran)
+
+* Fixed use of ``hashlib.md5`` on python2.5+ (also from Prabhu
+ Ramachandran)
+
+0.1
+---
+
+* Initial release
51 docs/requirement-format.txt
@@ -0,0 +1,51 @@
+The requirements file format
+============================
+
+The requirements file is what poacheggs uses to install packages.
+This document describes that format.
+
+Each line of the requirements file indicates something to be
+installed. For example::
+
+ MyPackage==3.0
+
+tells poacheggs to install the 3.0 version of MyPackage.
+
+You can also install a package in an "editable" form. This puts the
+source code into ``src/distname`` (making the name lower case) and
+runs ``python setup.py develop`` on the package. To indicate
+editable, use ``-e``, like::
+
+ -e svn+http://svn.myproject.org/svn/MyProject/trunk#egg=MyProject
+
+The ``#egg=MyProject`` part is important, because while you can
+install simply given the svn location, the project name is useful in
+other places.
+
+If you need to give poacheggs (and by association easy_install) hints
+about where to find a package, you can use the ``-f``
+(``--find-links``) option, like::
+
+ -f http://someserver.org/MyPackage-3.0.tar.gz
+
+If the package is named like ``PackageName-Version.tar.gz`` (or a zip)
+then you don't need ``#egg=...``. Note that you cannot provide
+multiple ``-f`` arguments to easy_install, but you can in a
+requirements file (they all get concatenated into a single ``-f`` for
+easy_install).
+
+Version Control
+---------------
+
+Right now poacheggs only knows Subversion. I hope to add Mercurial in
+the not-too-distant future, as that system in particular is used by
+quite a few open source Python projects (once that's added, support
+for Bazaar, git, etc. will probably be easy).
+
+You can also give specific revisions to an SVN URL, like::
+
+ -e svn+http://svn.myproject.org/svn/MyProject/trunk@2019
+
+which will check out revision 2019. ``@{20080101}`` would also check
+out the revision from 2008-01-01. You can only check out specific
+revisions using ``-e svn+...``.
2,538 pyinstall.py
2,538 additions, 0 deletions not shown because the diff is too large. Please use a local Git client to view these changes.
9 regen-docs
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+mkdir -p docs/_static docs/_build
+sphinx-build -E -b html docs/ docs/_build || exit 1
+if [ "$1" = "publish" ] ; then
+ cd docs/_build
+ echo "Uploading files..."
+ tar czvf - . | ssh flow.openplans.org 'ssh acura.openplans.org "cd /www/pyinstall.openplans.org/; tar xzvf -"'
+fi
3 setup.cfg
@@ -0,0 +1,3 @@
+[egg_info]
+tag_build = dev
+tag_svn_revision = true
41 setup.py
@@ -0,0 +1,41 @@
+try:
+ from setuptools import setup
+except ImportError:
+ from distutils.core import setup
+import os
+
+version = '0.1.5'
+
+doc_dir = os.path.join(os.path.dirname(__file__), 'docs')
+index_filename = os.path.join(doc_dir, 'index.txt')
+long_description = """\
+The main website for pyinstall is `pyinstall.openplans.org
+<http://pyinstall.openplans.org>`_
+
+"""
+long_description = long_description + open(index_filename).read().split('split here', 1)[1]
+
+
+
+setup(name='pyinstall',
+ version=version,
+ description="Installer for Python packages",
+ long_description=long_description,
+ classifiers=[
+ 'Development Status :: 4 - Beta',
+ #'Development Status :: 5 - Production/Stable',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: MIT License',
+ 'Topic :: Software Development :: Build Tools',
+ ],
+ keywords='easy_install distutils setuptools egg virtualenv',
+ author='The Open Planning Project',
+ author_email='python-virtualenv@groups.google.com',
+ url='http://pyinstall.openplans.org',
+ license='MIT',
+ py_modules=['pyinstall'],
+ ## FIXME: is this the best way? (Works with distutils, but
+ ## don't we really require setuptools anyway?)
+ scripts=['pyinstall.py'],
+ )
+
90 tests/test_all_pyinstall.py
@@ -0,0 +1,90 @@
+import urllib2
+import re
+import sys
+import os
+import subprocess
+import shutil
+
+pyinstall_fn = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'pyinstall.py')
+
+def all_projects():
+ data = urllib2.urlopen('http://pypi.python.org/pypi/').read()
+ projects = [m.group(1) for m in re.finditer(r'href="/pypi/([^/"]*)', data)]
+ return projects
+
+def main(args=None):
+ if args is None:
+ args = sys.argv[1:]
+ if not args:
+ print 'Usage: test_all_pyinstall.py <output-dir>'
+ sys.exit(1)
+ output = args[0]
+ if not os.path.exists(output):
+ print 'Creating %s' % output
+ os.makedirs(output)
+ pending_fn = os.path.join(output, 'pending.txt')
+ if not os.path.exists(pending_fn):
+ print 'Downloading pending list'
+ projects = all_projects()
+ print 'Found %s projects' % len(projects)
+ f = open(pending_fn, 'w')
+ for name in projects:
+ f.write(name + '\n')
+ f.close()
+ print 'Starting testing...'
+ while os.stat(pending_fn).st_size:
+ test_packages(output, pending_fn)
+ print 'Finished all pending!'
+
+def test_packages(output, pending_fn):
+ package = get_last_item(pending_fn)
+ print 'Testing package %s' % package
+ dest_dir = os.path.join(output, package)
+ print 'Creating virtualenv in %s' % dest_dir
+ code = subprocess.call(['virtualenv', dest_dir])
+ assert not code, "virtualenv failed"
+ print 'Trying installation of %s' % dest_dir
+ code = subprocess.call([os.path.join(dest_dir, 'bin', 'python'),
+ pyinstall_fn, package])
+ if code:
+ print 'Installation of %s failed' % package
+ print 'Now checking easy_install...'
+ code = subprocess.call([os.path.join(dest_dir, 'bin', 'easy_install'),
+ package])
+ if code:
+ print 'easy_install also failed'
+ add_package(os.path.join(output, 'easy-failure.txt'), package)
+ else:
+ print 'easy_install succeeded'
+ add_package(os.path.join(output, 'failure.txt'), package)
+ pop_last_item(pending_fn, package)
+ else:
+ print 'Installation of %s succeeded' % package
+ add_package(os.path.join(output, 'success.txt'), package)
+ pop_last_item(pending_fn, package)
+ shutil.rmtree(dest_dir)
+
+def get_last_item(fn):
+ f = open(fn, 'r')
+ lines = f.readlines()
+ f.close()
+ return lines[-1].strip()
+
+def pop_last_item(fn, line=None):
+ f = open(fn, 'r')
+ lines = f.readlines()
+ f.close()
+ if line:
+ assert lines[-1].strip() == line.strip()
+ lines.pop()
+ f = open(fn, 'w')
+ f.writelines(lines)
+ f.close()
+
+def add_package(filename, package):
+ f = open(filename, 'a')
+ f.write(package + '\n')
+ f.close()
+
+if __name__ == '__main__':
+ main()
41 tests/test_basic.txt
@@ -0,0 +1,41 @@
+Basic setup::
+
+ >>> from __main__ import here, reset_env, run_pyinstall, pyversion, lib_py
+ >>> reset_env()
+
+First a test of the distutils-configuration-setting command (which is distinct from other commands)::
+
+ #>>> print run_pyinstall('-vv', '--distutils-cfg=easy_install:index_url:http://download.zope.org/ppix/', expect_error=True)
+ #Script result: python ../../poacheggs.py -E .../poacheggs-tests/test-scratch -vv --distutils-cfg=easy_install:index_url:http://download.zope.org/ppix/
+ #-- stdout: --------------------
+ #Distutils config .../poacheggs-tests/test-scratch/lib/python.../distutils/distutils.cfg is writable
+ #Replaced setting index_url
+ #Updated .../poacheggs-tests/test-scratch/lib/python.../distutils/distutils.cfg
+ #<BLANKLINE>
+ #-- updated: -------------------
+ # lib/python2.4/distutils/distutils.cfg (346 bytes)
+
+Next, a simple test::
+
+ >>> result = run_pyinstall('-vvv', 'INITools==0.2', expect_error=True)
+ >>> assert (lib_py + 'site-packages/INITools-0.2-py%s.egg-info' % pyversion) in result.files_created
+ >>> assert (lib_py + 'site-packages/initools') in result.files_created
+
+Let's try that again, editable::
+
+ >>> reset_env()
+ >>> result = run_pyinstall('-e', 'INITools==0.2', expect_error=True)
+ >>> assert "--editable=INITools==0.2 is not the right format" in result.stdout
+ >>> assert len(result.files_created) == 1 and not result.files_updated
+
+Now, checking out from svn::
+
+ >>> reset_env()
+ >>> result = run_pyinstall('-e', 'svn+http://svn.colorstudy.com/INITools/trunk#egg=initools-dev', expect_error=True)
+ >>> egg_link = result.files_created[lib_py + 'site-packages/INITools.egg-link']
+ >>> # FIXME: I don't understand why there's a trailing . here:
+ >>> egg_link.bytes
+ '.../test-scratch/src/initools\n.'
+ >>> assert (lib_py + 'site-packages/easy-install.pth') in result.files_updated
+ >>> assert 'src/initools' in result.files_created
+ >>> assert 'src/initools/.svn' in result.files_created
62 tests/test_freeze.txt
@@ -0,0 +1,62 @@
+Basic setup::
+
+ >>> import os
+ >>> from __main__ import base_path, reset_env, run_pyinstall, pyversion, lib_py, write_file, get_env
+
+Some tests of freeze, first we have to install some stuff::
+
+ >>> reset_env()
+ >>> write_file('initools-req.txt', '''\
+ ... INITools==0.2
+ ... # and something else to test out:
+ ... simplejson<=1.7.4
+ ... ''')
+ >>> result = run_pyinstall('-r', 'initools-req.txt')
+ >>> result = run_pyinstall('--freeze=-', expect_stderr=True)
+ >>> print result
+ Script result: python ../../pyinstall.py -E .../test-scratch --freeze=-
+ -- stdout: --------------------
+ INITools==0.2
+ simplejson==1.7.4
+ <BLANKLINE>
+
+Now lets try it with an svn checkout::
+
+ >>> env = get_env()
+ >>> result = env.run('svn', 'co', '-r3472', 'http://svn.colorstudy.com/INITools/trunk', 'initools-trunk')
+ >>> result = env.run(os.path.join(env.base_path, 'bin/python'), 'setup.py', 'develop',
+ ... cwd=os.path.join(env.base_path, 'initools-trunk'))
+ >>> result = run_pyinstall('--freeze=-', expect_stderr=True)
+ >>> print result
+ Script result: python ../../pyinstall.py -E .../test-scratch --freeze=-
+ -- stdout: --------------------
+ -e svn+http://svn.colorstudy.com/INITools/trunk@3472#egg=INITools-0.2.1dev_r3472-py2.4-dev
+ simplejson==1.7.4
+ <BLANKLINE>
+
+Now, straight from trunk (but not editable/setup.py develop)::
+
+ >>> result = env.run(os.path.join(env.base_path, 'bin/easy_install'), 'http://svn.colorstudy.com/INITools/trunk')
+ >>> result = run_pyinstall('--freeze=-', expect_stderr=True)
+ >>> print result
+ Script result: python ../../pyinstall.py -E .../test-scratch --freeze=-
+ -- stderr: --------------------
+ Warning: cannot find svn location for INITools==...dev-r...
+ <BLANKLINE>
+ -- stdout: --------------------
+ ## FIXME: could not find svn URL in dependency_links for this package:
+ INITools==...dev-r...
+ simplejson==1.7.4
+ <BLANKLINE>
+
+Bah, that's no good! Let's give it a hint::
+
+ >>> result = run_pyinstall('--freeze=-', '-f', 'http://svn.colorstudy.com/INITools/trunk#egg=INITools-dev', expect_stderr=True)
+ >>> print result
+ Script result: python ../../pyinstall.py -E .../test-scratch --freeze=- -f http://svn.colorstudy.com/INITools/trunk#egg=INITools-dev
+ -- stdout: --------------------
+ -f http://svn.colorstudy.com/INITools/trunk#egg=INITools-dev
+ # Installing as editable to satisfy requirement INITools==...dev-r...:
+ -e svn+http://svn.colorstudy.com/INITools/trunk@...#egg=INITools-...dev_r...
+ simplejson==1.7.4
+ <BLANKLINE>
43 tests/test_proxy.txt
@@ -0,0 +1,43 @@
+Tests for the proxy support in pyinstall::
+
+ >>> import os
+ >>> import pyinstall
+
+Remove proxy from environ:
+
+ >>> if 'HTTP_PROXY' in os.environ:
+ ... del os.environ['HTTP_PROXY']
+
+ >>> print pyinstall.get_proxy()
+ None
+ >>> os.environ['HTTP_PROXY'] = 'user:pwd@server.com:port'
+ >>> pyinstall.get_proxy()
+ 'user:pwd@server.com:port'
+ >>> del os.environ['HTTP_PROXY']
+ >>> pyinstall.get_proxy('server.com')
+ 'server.com'
+ >>> pyinstall.get_proxy('server.com:80')
+ 'server.com:80'
+ >>> pyinstall.get_proxy('user:passwd@server.com:3128')
+ 'user:passwd@server.com:3128'
+
+Now, a quick monkeypatch for getpass.getpass, to avoid asking for a password::
+
+ >>> import getpass
+ >>> old_getpass = getpass.getpass
+ >>> def new_getpass(prompt, answer='passwd'):
+ ... print '%s%s' % (prompt, answer)
+ ... return answer
+ >>> getpass.getpass = new_getpass
+
+Test it:
+
+ >>> pyinstall.get_proxy('user:@server.com:3128')
+ 'user:@server.com:3128'
+ >>> pyinstall.get_proxy('user@server.com:3128')
+ Password for user@server.com:3128: passwd
+ 'user:passwd@server.com:3128'
+
+Undo monkeypatch:
+
+ >>> getpass.getpass = old_getpass
76 tests/test_pyinstall.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+import os, sys
+sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
+import doctest
+
+pyversion = sys.version[:3]
+lib_py = 'lib/python%s/' % pyversion
+here = os.path.dirname(os.path.abspath(__file__))
+base_path = os.path.join(here, 'test-scratch')
+
+from scripttest import TestFileEnvironment
+
+if 'PYTHONPATH' in os.environ:
+ del os.environ['PYTHONPATH']
+
+def reset_env():
+ global env
+ env = TestFileEnvironment(base_path, ignore_hidden=False)
+ env.run('virtualenv', '--no-site-packages', env.base_path)
+ # To avoid the 0.9c8 svn 1.5 incompatibility:
+ env.run('%s/bin/easy_install' % env.base_path, 'http://peak.telecommunity.com/snapshots/setuptools-0.7a1dev-r66388.tar.gz')
+ env.run('mkdir', 'src')
+
+def run_pyinstall(*args, **kw):
+ import sys
+ args = ('python', '../../pyinstall.py', '-E', env.base_path) + args
+ #print >> sys.__stdout__, 'running', ' '.join(args)
+ if options.show_error:
+ kw['expect_error'] = True
+ result = env.run(*args, **kw)
+ if options.show_error and result.returncode:
+ print result
+ return result
+
+def write_file(filename, text):
+ f = open(os.path.join(base_path, filename), 'w')
+ f.write(text)
+ f.close()
+
+def get_env():
+ return env
+
+import optparse
+parser = optparse.OptionParser(usage='%prog [OPTIONS] [TEST_FILE...]')
+parser.add_option('--first', action='store_true',
+ help='Show only first failure')
+parser.add_option('--diff', action='store_true',
+ help='Show diffs in doctest failures')
+parser.add_option('--show-error', action='store_true',
+ help='Show the errors (use expect_error=True in run_pyinstall)')
+parser.add_option('-v', action='store_true',
+ help='Be verbose')
+
+def main():
+ global options
+ options, args = parser.parse_args()
+ reset_env()
+ if not args:
+ args = ['test_basic.txt', 'test_requirements.txt', 'test_freeze.txt', 'test_proxy.txt']
+ optionflags = doctest.ELLIPSIS
+ if options.first:
+ optionflags |= doctest.REPORT_ONLY_FIRST_FAILURE
+ if options.diff:
+ optionflags |= doctest.REPORT_UDIFF
+ for filename in args:
+ if not filename.endswith('.txt'):
+ filename += '.txt'
+ if not filename.startswith('test_'):
+ filename = 'test_' + filename
+ ## FIXME: test for filename existance
+ failures, successes = doctest.testfile(filename, optionflags=optionflags)
+ if options.first and failures:
+ break
+
+if __name__ == '__main__':
+ main()
38 tests/test_requirements.txt
@@ -0,0 +1,38 @@
+Basic setup::
+
+ >>> import os
+ >>> from __main__ import base_path, reset_env, run_pyinstall, pyversion, lib_py, write_file
+
+Some tests of requirement files::
+
+ >>> reset_env()
+ >>> write_file('initools-req.txt', '''\
+ ... INITools==0.2
+ ... # and something else to test out:
+ ... simplejson<=1.7.4
+ ... ''')
+ >>> result = run_pyinstall('-r', 'initools-req.txt')
+ >>> len(result.wildcard_matches('lib/python*/site-packages/INITools-0.2-py*.egg-info'))
+ 1
+ >>> len(result.wildcard_matches('lib/python*/site-packages/initools'))
+ 1
+ >>> dirs = result.wildcard_matches('lib/python*/site-packages/simplejson*')
+ >>> len(dirs)
+ 2
+ >>> dirs[0].dir, dirs[1].dir
+ (True, True)
+
+Now with more than one file::
+
+ >>> reset_env()
+ >>> write_file('initools-req.txt', '''\
+ ... -e svn+http://svn.colorstudy.com/INITools/trunk@3139#egg=INITools-dev
+ ... -r simplejson-req.txt''')
+ >>> write_file('simplejson-req.txt', '''\
+ ... simplejson<=1.7.4
+ ... ''')
+ >>> result = run_pyinstall('-r', 'initools-req.txt')
+ >>> len(result.wildcard_matches('lib/python*/site-packages/simplejson*'))
+ 2
+ >>> assert 'src/initools' in result.files_created
+

0 comments on commit c2000d7

Please sign in to comment.
Something went wrong with that request. Please try again.