diff -r 2e49722c7263 -r 6944bdf1289a .hgeol --- a/.hgeol Thu Jun 09 15:52:31 2011 -0400 +++ b/.hgeol Sat May 14 18:40:38 2011 +0200 @@ -27,10 +27,9 @@ **.zip = BIN Lib/email/test/data/msg_26.txt = BIN -Lib/test/cjkencodings/* = BIN +Lib/test/test_email/data/msg_26.txt = BIN +Lib/test/sndhdrdata/sndhdr.* = BIN Lib/test/decimaltestdata/*.decTest = BIN -Lib/test/sndhdrdata/sndhdr.* = BIN -Lib/test/test_email/data/msg_26.txt = BIN # All other files (which presumably are human-editable) are "native". # This must be the last rule! diff -r 2e49722c7263 -r 6944bdf1289a .hgtags --- a/.hgtags Thu Jun 09 15:52:31 2011 -0400 +++ b/.hgtags Sat May 14 18:40:38 2011 +0200 @@ -75,7 +75,6 @@ 960efa327c5d9c18df995437b0ac550cb89c9f85 v3.1.2 d18e9d71f369d8211f6ac87252c6d3211f9bd09f v3.1.3rc1 a4f75773c0060cee38b0bb651a7aba6f56b0e996 v3.1.3 -32fcb9e94985cb19ce37ba9543f091c0dbe9d7dd v3.1.4rc1 b37b7834757492d009b99cf0ca4d42d2153d7fac v3.2a1 56d4373cecb73c8b45126ba7b045b3c7b3f94b0b v3.2a2 da012d9a2c23d144e399d2e01a55b8a83ad94573 v3.2a3 @@ -87,4 +86,3 @@ 18c1f52896501c7ee13b038454a39acb45a87979 v3.2rc3 a222a015e28d8ae9af3899258dc6c15c3d40add0 v3.2 8ffac2337a3323323d02153ac919fd1483176652 v3.2.1b1 -cfa9364997c7f2e67b9cbb45c3a5fa3bba4e4999 v3.2.1rc1 diff -r 2e49722c7263 -r 6944bdf1289a Doc/c-api/buffer.rst --- a/Doc/c-api/buffer.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/c-api/buffer.rst Sat May 14 18:40:38 2011 +0200 @@ -314,7 +314,7 @@ .. c:function:: void PyBuffer_FillContiguousStrides(int ndim, Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t itemsize, char fortran) Fill the *strides* array with byte-strides of a contiguous (C-style if - *fortran* is ``'C'`` or Fortran-style if *fortran* is ``'F'``) array of the + *fortran* is ``'C'`` or Fortran-style if *fortran* is ``'F'`` array of the given shape with the given number of bytes per element. diff -r 2e49722c7263 -r 6944bdf1289a Doc/c-api/intro.rst --- a/Doc/c-api/intro.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/c-api/intro.rst Sat May 14 18:40:38 2011 +0200 @@ -588,8 +588,8 @@ Compiling the interpreter with the :c:macro:`Py_DEBUG` macro defined produces what is generally meant by "a debug build" of Python. :c:macro:`Py_DEBUG` is -enabled in the Unix build by adding ``--with-pydebug`` to the -:file:`./configure` command. It is also implied by the presence of the +enabled in the Unix build by adding :option:`--with-pydebug` to the +:file:`configure` command. It is also implied by the presence of the not-Python-specific :c:macro:`_DEBUG` macro. When :c:macro:`Py_DEBUG` is enabled in the Unix build, compiler optimization is disabled. diff -r 2e49722c7263 -r 6944bdf1289a Doc/c-api/veryhigh.rst --- a/Doc/c-api/veryhigh.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/c-api/veryhigh.rst Sat May 14 18:40:38 2011 +0200 @@ -27,17 +27,18 @@ .. c:function:: int Py_Main(int argc, wchar_t **argv) - The main program for the standard interpreter. This is made available for - programs which embed Python. The *argc* and *argv* parameters should be - prepared exactly as those which are passed to a C program's :c:func:`main` - function (converted to wchar_t according to the user's locale). It is - important to note that the argument list may be modified (but the contents of - the strings pointed to by the argument list are not). The return value will - be ``0`` if the interpreter exits normally (i.e., without an exception), - ``1`` if the interpreter exits due to an exception, or ``2`` if the parameter + The main program for the standard interpreter. This is made + available for programs which embed Python. The *argc* and *argv* + parameters should be prepared exactly as those which are passed to + a C program's :c:func:`main` function (converted to wchar_t + according to the user's locale). It is important to note that the + argument list may be modified (but the contents of the strings + pointed to by the argument list are not). The return value will be + the integer passed to the :func:`sys.exit` function, ``1`` if the + interpreter exits due to an exception, or ``2`` if the parameter list does not represent a valid Python command line. - Note that if an otherwise unhandled :exc:`SystemExit` is raised, this + Note that if an otherwise unhandled :exc:`SystemError` is raised, this function will not return ``1``, but exit the process, as long as ``Py_InspectFlag`` is not set. @@ -84,7 +85,7 @@ there was an error, there is no way to get the exception information. For the meaning of *flags*, see below. - Note that if an otherwise unhandled :exc:`SystemExit` is raised, this + Note that if an otherwise unhandled :exc:`SystemError` is raised, this function will not return ``-1``, but exit the process, as long as ``Py_InspectFlag`` is not set. diff -r 2e49722c7263 -r 6944bdf1289a Doc/c-api/weakref.rst --- a/Doc/c-api/weakref.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/c-api/weakref.rst Sat May 14 18:40:38 2011 +0200 @@ -55,7 +55,7 @@ Return the referenced object from a weak reference, *ref*. If the referent is no longer live, returns :const:`Py_None`. - .. note:: + .. warning:: This function returns a **borrowed reference** to the referenced object. This means that you should always call :c:func:`Py_INCREF` on the object diff -r 2e49722c7263 -r 6944bdf1289a Doc/contents.rst --- a/Doc/contents.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/contents.rst Sat May 14 18:40:38 2011 +0200 @@ -11,7 +11,7 @@ library/index.rst extending/index.rst c-api/index.rst - packaging/index.rst + distutils/index.rst install/index.rst documenting/index.rst howto/index.rst diff -r 2e49722c7263 -r 6944bdf1289a Doc/distutils/apiref.rst --- a/Doc/distutils/apiref.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/distutils/apiref.rst Sat May 14 18:40:38 2011 +0200 @@ -21,7 +21,7 @@ .. function:: setup(arguments) The basic do-everything function that does most everything you could ever ask - for from a Distutils method. + for from a Distutils method. See XXXXX The setup function takes a large number of arguments. These are laid out in the following table. @@ -147,11 +147,11 @@ In addition, the :mod:`distutils.core` module exposed a number of classes that live elsewhere. -* :class:`~distutils.extension.Extension` from :mod:`distutils.extension` - -* :class:`~distutils.cmd.Command` from :mod:`distutils.cmd` - -* :class:`~distutils.dist.Distribution` from :mod:`distutils.dist` +* :class:`Extension` from :mod:`distutils.extension` + +* :class:`Command` from :mod:`distutils.cmd` + +* :class:`Distribution` from :mod:`distutils.dist` A short description of each of these follows, but see the relevant module for the full reference. @@ -1678,8 +1678,8 @@ =================================================================== .. module:: distutils.cmd - :synopsis: This module provides the abstract base class Command. This class - is subclassed by the modules in the distutils.command subpackage. + :synopsis: This module provides the abstract base class Command. This class is subclassed + by the modules in the distutils.command subpackage. This module supplies the abstract base class :class:`Command`. @@ -1689,38 +1689,291 @@ Abstract base class for defining command classes, the "worker bees" of the Distutils. A useful analogy for command classes is to think of them as - subroutines with local variables called *options*. The options are declared - in :meth:`initialize_options` and defined (given their final values) in - :meth:`finalize_options`, both of which must be defined by every command - class. The distinction between the two is necessary because option values - might come from the outside world (command line, config file, ...), and any - options dependent on other options must be computed after these outside - influences have been processed --- hence :meth:`finalize_options`. The body - of the subroutine, where it does all its work based on the values of its - options, is the :meth:`run` method, which must also be implemented by every - command class. - - The class constructor takes a single argument *dist*, a :class:`Distribution` + subroutines with local variables called *options*. The options are declared in + :meth:`initialize_options` and defined (given their final values) in + :meth:`finalize_options`, both of which must be defined by every command class. + The distinction between the two is necessary because option values might come + from the outside world (command line, config file, ...), and any options + dependent on other options must be computed after these outside influences have + been processed --- hence :meth:`finalize_options`. The body of the subroutine, + where it does all its work based on the values of its options, is the + :meth:`run` method, which must also be implemented by every command class. + + The class constructor takes a single argument *dist*, a :class:`Distribution` instance. +:mod:`distutils.command` --- Individual Distutils commands +========================================================== + +.. module:: distutils.command + :synopsis: This subpackage contains one module for each standard Distutils command. + + +.. % \subsubsection{Individual Distutils commands} +.. % todo + + +:mod:`distutils.command.bdist` --- Build a binary installer +=========================================================== + +.. module:: distutils.command.bdist + :synopsis: Build a binary installer for a package + + +.. % todo + + +:mod:`distutils.command.bdist_packager` --- Abstract base class for packagers +============================================================================= + +.. module:: distutils.command.bdist_packager + :synopsis: Abstract base class for packagers + + +.. % todo + + +:mod:`distutils.command.bdist_dumb` --- Build a "dumb" installer +================================================================ + +.. module:: distutils.command.bdist_dumb + :synopsis: Build a "dumb" installer - a simple archive of files + + +.. % todo + + +:mod:`distutils.command.bdist_msi` --- Build a Microsoft Installer binary package +================================================================================= + +.. module:: distutils.command.bdist_msi + :synopsis: Build a binary distribution as a Windows MSI file + +.. class:: bdist_msi(Command) + + Builds a `Windows Installer`_ (.msi) binary package. + + .. _Windows Installer: http://msdn.microsoft.com/en-us/library/cc185688(VS.85).aspx + + In most cases, the ``bdist_msi`` installer is a better choice than the + ``bdist_wininst`` installer, because it provides better support for + Win64 platforms, allows administrators to perform non-interactive + installations, and allows installation through group policies. + + +:mod:`distutils.command.bdist_rpm` --- Build a binary distribution as a Redhat RPM and SRPM +=========================================================================================== + +.. module:: distutils.command.bdist_rpm + :synopsis: Build a binary distribution as a Redhat RPM and SRPM + + +.. % todo + + +:mod:`distutils.command.bdist_wininst` --- Build a Windows installer +==================================================================== + +.. module:: distutils.command.bdist_wininst + :synopsis: Build a Windows installer + + +.. % todo + + +:mod:`distutils.command.sdist` --- Build a source distribution +============================================================== + +.. module:: distutils.command.sdist + :synopsis: Build a source distribution + + +.. % todo + + +:mod:`distutils.command.build` --- Build all files of a package +=============================================================== + +.. module:: distutils.command.build + :synopsis: Build all files of a package + + +.. % todo + + +:mod:`distutils.command.build_clib` --- Build any C libraries in a package +========================================================================== + +.. module:: distutils.command.build_clib + :synopsis: Build any C libraries in a package + + +.. % todo + + +:mod:`distutils.command.build_ext` --- Build any extensions in a package +======================================================================== + +.. module:: distutils.command.build_ext + :synopsis: Build any extensions in a package + + +.. % todo + + +:mod:`distutils.command.build_py` --- Build the .py/.pyc files of a package +=========================================================================== + +.. module:: distutils.command.build_py + :synopsis: Build the .py/.pyc files of a package + + +.. class:: build_py(Command) + +.. class:: build_py_2to3(build_py) + + Alternative implementation of build_py which also runs the + 2to3 conversion library on each .py file that is going to be + installed. To use this in a setup.py file for a distribution + that is designed to run with both Python 2.x and 3.x, add:: + + try: + from distutils.command.build_py import build_py_2to3 as build_py + except ImportError: + from distutils.command.build_py import build_py + + to your setup.py, and later:: + + cmdclass = {'build_py': build_py} + + to the invocation of setup(). + + +:mod:`distutils.command.build_scripts` --- Build the scripts of a package +========================================================================= + +.. module:: distutils.command.build_scripts + :synopsis: Build the scripts of a package + + +.. % todo + + +:mod:`distutils.command.clean` --- Clean a package build area +============================================================= + +.. module:: distutils.command.clean + :synopsis: Clean a package build area + + +.. % todo + + +:mod:`distutils.command.config` --- Perform package configuration +================================================================= + +.. module:: distutils.command.config + :synopsis: Perform package configuration + + +.. % todo + + +:mod:`distutils.command.install` --- Install a package +====================================================== + +.. module:: distutils.command.install + :synopsis: Install a package + + +.. % todo + + +:mod:`distutils.command.install_data` --- Install data files from a package +=========================================================================== + +.. module:: distutils.command.install_data + :synopsis: Install data files from a package + + +.. % todo + + +:mod:`distutils.command.install_headers` --- Install C/C++ header files from a package +====================================================================================== + +.. module:: distutils.command.install_headers + :synopsis: Install C/C++ header files from a package + + +.. % todo + + +:mod:`distutils.command.install_lib` --- Install library files from a package +============================================================================= + +.. module:: distutils.command.install_lib + :synopsis: Install library files from a package + + +.. % todo + + +:mod:`distutils.command.install_scripts` --- Install script files from a package +================================================================================ + +.. module:: distutils.command.install_scripts + :synopsis: Install script files from a package + + +.. % todo + + +:mod:`distutils.command.register` --- Register a module with the Python Package Index +===================================================================================== + +.. module:: distutils.command.register + :synopsis: Register a module with the Python Package Index + + +The ``register`` command registers the package with the Python Package Index. +This is described in more detail in :pep:`301`. + +.. % todo + +:mod:`distutils.command.check` --- Check the meta-data of a package +=================================================================== + +.. module:: distutils.command.check + :synopsis: Check the metadata of a package + + +The ``check`` command performs some tests on the meta-data of a package. +For example, it verifies that all required meta-data are provided as +the arguments passed to the :func:`setup` function. + +.. % todo + + Creating a new Distutils command ================================ This section outlines the steps to create a new Distutils command. A new command lives in a module in the :mod:`distutils.command` package. There -is a sample template in that directory called :file:`command_template`. Copy +is a sample template in that directory called :file:`command_template`. Copy this file to a new module with the same name as the new command you're -implementing. This module should implement a class with the same name as the -module (and the command). So, for instance, to create the command +implementing. This module should implement a class with the same name as the +module (and the command). So, for instance, to create the command ``peel_banana`` (so that users can run ``setup.py peel_banana``), you'd copy -:file:`command_template` to :file:`distutils/command/peel_banana.py`, then edit +:file:`command_template` to :file:`distutils/command/peel_banana.py`, then edit it so that it's implementing the class :class:`peel_banana`, a subclass of :class:`distutils.cmd.Command`. Subclasses of :class:`Command` must define the following methods. + .. method:: Command.initialize_options() Set default values for all the options that this command supports. Note that @@ -1748,274 +2001,16 @@ :meth:`finalize_options`. All terminal output and filesystem interaction should be done by :meth:`run`. - -.. attribute:: Command.sub_commands - - *sub_commands* formalizes the notion of a "family" of commands, - e.g. ``install`` as the parent with sub-commands ``install_lib``, - ``install_headers``, etc. The parent of a family of commands defines - *sub_commands* as a class attribute; it's a list of 2-tuples ``(command_name, - predicate)``, with *command_name* a string and *predicate* a function, a - string or ``None``. *predicate* is a method of the parent command that - determines whether the corresponding command is applicable in the current - situation. (E.g. ``install_headers`` is only applicable if we have any C - header files to install.) If *predicate* is ``None``, that command is always - applicable. - - *sub_commands* is usually defined at the *end* of a class, because - predicates can be methods of the class, so they must already have been - defined. The canonical example is the :command:`install` command. - - -:mod:`distutils.command` --- Individual Distutils commands -========================================================== - -.. module:: distutils.command - :synopsis: This subpackage contains one module for each standard Distutils command. - - -.. % \subsubsection{Individual Distutils commands} -.. % todo - - -:mod:`distutils.command.bdist` --- Build a binary installer -=========================================================== - -.. module:: distutils.command.bdist - :synopsis: Build a binary installer for a package - - -.. % todo - - -:mod:`distutils.command.bdist_packager` --- Abstract base class for packagers -============================================================================= - -.. module:: distutils.command.bdist_packager - :synopsis: Abstract base class for packagers - - -.. % todo - - -:mod:`distutils.command.bdist_dumb` --- Build a "dumb" installer -================================================================ - -.. module:: distutils.command.bdist_dumb - :synopsis: Build a "dumb" installer - a simple archive of files - - -.. % todo - - -:mod:`distutils.command.bdist_msi` --- Build a Microsoft Installer binary package -================================================================================= - -.. module:: distutils.command.bdist_msi - :synopsis: Build a binary distribution as a Windows MSI file - -.. class:: bdist_msi - - Builds a `Windows Installer`_ (.msi) binary package. - - .. _Windows Installer: http://msdn.microsoft.com/en-us/library/cc185688(VS.85).aspx - - In most cases, the ``bdist_msi`` installer is a better choice than the - ``bdist_wininst`` installer, because it provides better support for - Win64 platforms, allows administrators to perform non-interactive - installations, and allows installation through group policies. - - -:mod:`distutils.command.bdist_rpm` --- Build a binary distribution as a Redhat RPM and SRPM -=========================================================================================== - -.. module:: distutils.command.bdist_rpm - :synopsis: Build a binary distribution as a Redhat RPM and SRPM - - -.. % todo - - -:mod:`distutils.command.bdist_wininst` --- Build a Windows installer -==================================================================== - -.. module:: distutils.command.bdist_wininst - :synopsis: Build a Windows installer - - -.. % todo - - -:mod:`distutils.command.sdist` --- Build a source distribution -============================================================== - -.. module:: distutils.command.sdist - :synopsis: Build a source distribution - - -.. % todo - - -:mod:`distutils.command.build` --- Build all files of a package -=============================================================== - -.. module:: distutils.command.build - :synopsis: Build all files of a package - - -.. % todo - - -:mod:`distutils.command.build_clib` --- Build any C libraries in a package -========================================================================== - -.. module:: distutils.command.build_clib - :synopsis: Build any C libraries in a package - - -.. % todo - - -:mod:`distutils.command.build_ext` --- Build any extensions in a package -======================================================================== - -.. module:: distutils.command.build_ext - :synopsis: Build any extensions in a package - - -.. % todo - - -:mod:`distutils.command.build_py` --- Build the .py/.pyc files of a package -=========================================================================== - -.. module:: distutils.command.build_py - :synopsis: Build the .py/.pyc files of a package - - -.. class:: build_py - -.. class:: build_py_2to3 - - Alternative implementation of build_py which also runs the - 2to3 conversion library on each .py file that is going to be - installed. To use this in a setup.py file for a distribution - that is designed to run with both Python 2.x and 3.x, add:: - - try: - from distutils.command.build_py import build_py_2to3 as build_py - except ImportError: - from distutils.command.build_py import build_py - - to your setup.py, and later:: - - cmdclass = {'build_py': build_py} - - to the invocation of setup(). - - -:mod:`distutils.command.build_scripts` --- Build the scripts of a package -========================================================================= - -.. module:: distutils.command.build_scripts - :synopsis: Build the scripts of a package - - -.. % todo - - -:mod:`distutils.command.clean` --- Clean a package build area -============================================================= - -.. module:: distutils.command.clean - :synopsis: Clean a package build area - - -.. % todo - - -:mod:`distutils.command.config` --- Perform package configuration -================================================================= - -.. module:: distutils.command.config - :synopsis: Perform package configuration - - -.. % todo - - -:mod:`distutils.command.install` --- Install a package -====================================================== - -.. module:: distutils.command.install - :synopsis: Install a package - - -.. % todo - - -:mod:`distutils.command.install_data` --- Install data files from a package -=========================================================================== - -.. module:: distutils.command.install_data - :synopsis: Install data files from a package - - -.. % todo - - -:mod:`distutils.command.install_headers` --- Install C/C++ header files from a package -====================================================================================== - -.. module:: distutils.command.install_headers - :synopsis: Install C/C++ header files from a package - - -.. % todo - - -:mod:`distutils.command.install_lib` --- Install library files from a package -============================================================================= - -.. module:: distutils.command.install_lib - :synopsis: Install library files from a package - - -.. % todo - - -:mod:`distutils.command.install_scripts` --- Install script files from a package -================================================================================ - -.. module:: distutils.command.install_scripts - :synopsis: Install script files from a package - - -.. % todo - - -:mod:`distutils.command.register` --- Register a module with the Python Package Index -===================================================================================== - -.. module:: distutils.command.register - :synopsis: Register a module with the Python Package Index - - -The ``register`` command registers the package with the Python Package Index. -This is described in more detail in :pep:`301`. - -.. % todo - - -:mod:`distutils.command.check` --- Check the meta-data of a package -=================================================================== - -.. module:: distutils.command.check - :synopsis: Check the metadata of a package - - -The ``check`` command performs some tests on the meta-data of a package. -For example, it verifies that all required meta-data are provided as -the arguments passed to the :func:`setup` function. - -.. % todo +*sub_commands* formalizes the notion of a "family" of commands, eg. ``install`` +as the parent with sub-commands ``install_lib``, ``install_headers``, etc. The +parent of a family of commands defines *sub_commands* as a class attribute; it's +a list of 2-tuples ``(command_name, predicate)``, with *command_name* a string +and *predicate* a function, a string or None. *predicate* is a method of +the parent command that determines whether the corresponding command is +applicable in the current situation. (Eg. we ``install_headers`` is only +applicable if we have any C header files to install.) If *predicate* is None, +that command is always applicable. + +*sub_commands* is usually defined at the \*end\* of a class, because predicates +can be methods of the class, so they must already have been defined. The +canonical example is the :command:`install` command. diff -r 2e49722c7263 -r 6944bdf1289a Doc/distutils/extending.rst --- a/Doc/distutils/extending.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/distutils/extending.rst Sat May 14 18:40:38 2011 +0200 @@ -15,8 +15,8 @@ should be copied into packages in addition to :file:`.py` files as a convenience. -Most distutils command implementations are subclasses of the -:class:`distutils.cmd.Command` class. New commands may directly inherit from +Most distutils command implementations are subclasses of the :class:`Command` +class from :mod:`distutils.cmd`. New commands may directly inherit from :class:`Command`, while replacements often derive from :class:`Command` indirectly, directly subclassing the command they are replacing. Commands are required to derive from :class:`Command`. diff -r 2e49722c7263 -r 6944bdf1289a Doc/distutils/index.rst --- a/Doc/distutils/index.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/distutils/index.rst Sat May 14 18:40:38 2011 +0200 @@ -14,10 +14,6 @@ make Python modules and extensions easily available to a wider audience with very little overhead for build/release/install mechanics. -.. deprecated:: 3.3 - :mod:`packaging` replaces Distutils. See :ref:`packaging-index` and - :ref:`packaging-install-index`. - .. toctree:: :maxdepth: 2 :numbered: @@ -33,10 +29,3 @@ extending.rst commandref.rst apiref.rst - -Another document describes how to install modules and extensions packaged -following the above guidelines: - -.. toctree:: - - install.rst diff -r 2e49722c7263 -r 6944bdf1289a Doc/distutils/install.rst --- a/Doc/distutils/install.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1008 +0,0 @@ -.. highlightlang:: none - -.. _install-index: - -***************************** - Installing Python Modules -***************************** - -:Author: Greg Ward -:Release: |version| -:Date: |today| - -.. TODO: Fill in XXX comments - -.. The audience for this document includes people who don't know anything - about Python and aren't about to learn the language just in order to - install and maintain it for their users, i.e. system administrators. - Thus, I have to be sure to explain the basics at some point: - sys.path and PYTHONPATH at least. Should probably give pointers to - other docs on "import site", PYTHONSTARTUP, PYTHONHOME, etc. - - Finally, it might be useful to include all the material from my "Care - and Feeding of a Python Installation" talk in here somewhere. Yow! - -.. topic:: Abstract - - This document describes the Python Distribution Utilities ("Distutils") from the - end-user's point-of-view, describing how to extend the capabilities of a - standard Python installation by building and installing third-party Python - modules and extensions. - - -.. _inst-intro: - -Introduction -============ - -Although Python's extensive standard library covers many programming needs, -there often comes a time when you need to add some new functionality to your -Python installation in the form of third-party modules. This might be necessary -to support your own programming, or to support an application that you want to -use and that happens to be written in Python. - -In the past, there has been little support for adding third-party modules to an -existing Python installation. With the introduction of the Python Distribution -Utilities (Distutils for short) in Python 2.0, this changed. - -This document is aimed primarily at the people who need to install third-party -Python modules: end-users and system administrators who just need to get some -Python application running, and existing Python programmers who want to add some -new goodies to their toolbox. You don't need to know Python to read this -document; there will be some brief forays into using Python's interactive mode -to explore your installation, but that's it. If you're looking for information -on how to distribute your own Python modules so that others may use them, see -the :ref:`distutils-index` manual. - - -.. _inst-trivial-install: - -Best case: trivial installation -------------------------------- - -In the best case, someone will have prepared a special version of the module -distribution you want to install that is targeted specifically at your platform -and is installed just like any other software on your platform. For example, -the module developer might make an executable installer available for Windows -users, an RPM package for users of RPM-based Linux systems (Red Hat, SuSE, -Mandrake, and many others), a Debian package for users of Debian-based Linux -systems, and so forth. - -In that case, you would download the installer appropriate to your platform and -do the obvious thing with it: run it if it's an executable installer, ``rpm ---install`` it if it's an RPM, etc. You don't need to run Python or a setup -script, you don't need to compile anything---you might not even need to read any -instructions (although it's always a good idea to do so anyways). - -Of course, things will not always be that easy. You might be interested in a -module distribution that doesn't have an easy-to-use installer for your -platform. In that case, you'll have to start with the source distribution -released by the module's author/maintainer. Installing from a source -distribution is not too hard, as long as the modules are packaged in the -standard way. The bulk of this document is about building and installing -modules from standard source distributions. - - -.. _inst-new-standard: - -The new standard: Distutils ---------------------------- - -If you download a module source distribution, you can tell pretty quickly if it -was packaged and distributed in the standard way, i.e. using the Distutils. -First, the distribution's name and version number will be featured prominently -in the name of the downloaded archive, e.g. :file:`foo-1.0.tar.gz` or -:file:`widget-0.9.7.zip`. Next, the archive will unpack into a similarly-named -directory: :file:`foo-1.0` or :file:`widget-0.9.7`. Additionally, the -distribution will contain a setup script :file:`setup.py`, and a file named -:file:`README.txt` or possibly just :file:`README`, which should explain that -building and installing the module distribution is a simple matter of running -one command from a terminal:: - - python setup.py install - -For Windows, this command should be run from a command prompt windows ("DOS -box"):: - - setup.py install - -If all these things are true, then you already know how to build and install the -modules you've just downloaded: Run the command above. Unless you need to -install things in a non-standard way or customize the build process, you don't -really need this manual. Or rather, the above command is everything you need to -get out of this manual. - - -.. _inst-standard-install: - -Standard Build and Install -========================== - -As described in section :ref:`inst-new-standard`, building and installing a module -distribution using the Distutils is usually one simple command to run from a -terminal:: - - python setup.py install - - -.. _inst-platform-variations: - -Platform variations -------------------- - -You should always run the setup command from the distribution root directory, -i.e. the top-level subdirectory that the module source distribution unpacks -into. For example, if you've just downloaded a module source distribution -:file:`foo-1.0.tar.gz` onto a Unix system, the normal thing to do is:: - - gunzip -c foo-1.0.tar.gz | tar xf - # unpacks into directory foo-1.0 - cd foo-1.0 - python setup.py install - -On Windows, you'd probably download :file:`foo-1.0.zip`. If you downloaded the -archive file to :file:`C:\\Temp`, then it would unpack into -:file:`C:\\Temp\\foo-1.0`; you can use either a archive manipulator with a -graphical user interface (such as WinZip) or a command-line tool (such as -:program:`unzip` or :program:`pkunzip`) to unpack the archive. Then, open a -command prompt window ("DOS box"), and run:: - - cd c:\Temp\foo-1.0 - python setup.py install - - -.. _inst-splitting-up: - -Splitting the job up --------------------- - -Running ``setup.py install`` builds and installs all modules in one run. If you -prefer to work incrementally---especially useful if you want to customize the -build process, or if things are going wrong---you can use the setup script to do -one thing at a time. This is particularly helpful when the build and install -will be done by different users---for example, you might want to build a module -distribution and hand it off to a system administrator for installation (or do -it yourself, with super-user privileges). - -For example, you can build everything in one step, and then install everything -in a second step, by invoking the setup script twice:: - - python setup.py build - python setup.py install - -If you do this, you will notice that running the :command:`install` command -first runs the :command:`build` command, which---in this case---quickly notices -that it has nothing to do, since everything in the :file:`build` directory is -up-to-date. - -You may not need this ability to break things down often if all you do is -install modules downloaded off the 'net, but it's very handy for more advanced -tasks. If you get into distributing your own Python modules and extensions, -you'll run lots of individual Distutils commands on their own. - - -.. _inst-how-build-works: - -How building works ------------------- - -As implied above, the :command:`build` command is responsible for putting the -files to install into a *build directory*. By default, this is :file:`build` -under the distribution root; if you're excessively concerned with speed, or want -to keep the source tree pristine, you can change the build directory with the -:option:`--build-base` option. For example:: - - python setup.py build --build-base=/tmp/pybuild/foo-1.0 - -(Or you could do this permanently with a directive in your system or personal -Distutils configuration file; see section :ref:`inst-config-files`.) Normally, this -isn't necessary. - -The default layout for the build tree is as follows:: - - --- build/ --- lib/ - or - --- build/ --- lib./ - temp./ - -where ```` expands to a brief description of the current OS/hardware -platform and Python version. The first form, with just a :file:`lib` directory, -is used for "pure module distributions"---that is, module distributions that -include only pure Python modules. If a module distribution contains any -extensions (modules written in C/C++), then the second form, with two ```` -directories, is used. In that case, the :file:`temp.{plat}` directory holds -temporary files generated by the compile/link process that don't actually get -installed. In either case, the :file:`lib` (or :file:`lib.{plat}`) directory -contains all Python modules (pure Python and extensions) that will be installed. - -In the future, more directories will be added to handle Python scripts, -documentation, binary executables, and whatever else is needed to handle the job -of installing Python modules and applications. - - -.. _inst-how-install-works: - -How installation works ----------------------- - -After the :command:`build` command runs (whether you run it explicitly, or the -:command:`install` command does it for you), the work of the :command:`install` -command is relatively simple: all it has to do is copy everything under -:file:`build/lib` (or :file:`build/lib.{plat}`) to your chosen installation -directory. - -If you don't choose an installation directory---i.e., if you just run ``setup.py -install``\ ---then the :command:`install` command installs to the standard -location for third-party Python modules. This location varies by platform and -by how you built/installed Python itself. On Unix (and Mac OS X, which is also -Unix-based), it also depends on whether the module distribution being installed -is pure Python or contains extensions ("non-pure"): - -+-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ -| Platform | Standard installation location | Default value | Notes | -+=================+=====================================================+==================================================+=======+ -| Unix (pure) | :file:`{prefix}/lib/python{X.Y}/site-packages` | :file:`/usr/local/lib/python{X.Y}/site-packages` | \(1) | -+-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ -| Unix (non-pure) | :file:`{exec-prefix}/lib/python{X.Y}/site-packages` | :file:`/usr/local/lib/python{X.Y}/site-packages` | \(1) | -+-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ -| Windows | :file:`{prefix}\\Lib\\site-packages` | :file:`C:\\Python{XY}\\Lib\\site-packages` | \(2) | -+-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ - -Notes: - -(1) - Most Linux distributions include Python as a standard part of the system, so - :file:`{prefix}` and :file:`{exec-prefix}` are usually both :file:`/usr` on - Linux. If you build Python yourself on Linux (or any Unix-like system), the - default :file:`{prefix}` and :file:`{exec-prefix}` are :file:`/usr/local`. - -(2) - The default installation directory on Windows was :file:`C:\\Program - Files\\Python` under Python 1.6a1, 1.5.2, and earlier. - -:file:`{prefix}` and :file:`{exec-prefix}` stand for the directories that Python -is installed to, and where it finds its libraries at run-time. They are always -the same under Windows, and very often the same under Unix and Mac OS X. You -can find out what your Python installation uses for :file:`{prefix}` and -:file:`{exec-prefix}` by running Python in interactive mode and typing a few -simple commands. Under Unix, just type ``python`` at the shell prompt. Under -Windows, choose :menuselection:`Start --> Programs --> Python X.Y --> -Python (command line)`. Once the interpreter is started, you type Python code -at the prompt. For example, on my Linux system, I type the three Python -statements shown below, and get the output as shown, to find out my -:file:`{prefix}` and :file:`{exec-prefix}`:: - - Python 2.4 (#26, Aug 7 2004, 17:19:02) - Type "help", "copyright", "credits" or "license" for more information. - >>> import sys - >>> sys.prefix - '/usr' - >>> sys.exec_prefix - '/usr' - -If you don't want to install modules to the standard location, or if you don't -have permission to write there, then you need to read about alternate -installations in section :ref:`inst-alt-install`. If you want to customize your -installation directories more heavily, see section :ref:`inst-custom-install` on -custom installations. - - -.. _inst-alt-install: - -Alternate Installation -====================== - -Often, it is necessary or desirable to install modules to a location other than -the standard location for third-party Python modules. For example, on a Unix -system you might not have permission to write to the standard third-party module -directory. Or you might wish to try out a module before making it a standard -part of your local Python installation. This is especially true when upgrading -a distribution already present: you want to make sure your existing base of -scripts still works with the new version before actually upgrading. - -The Distutils :command:`install` command is designed to make installing module -distributions to an alternate location simple and painless. The basic idea is -that you supply a base directory for the installation, and the -:command:`install` command picks a set of directories (called an *installation -scheme*) under this base directory in which to install files. The details -differ across platforms, so read whichever of the following sections applies to -you. - - -.. _inst-alt-install-prefix: - -Alternate installation: the home scheme ---------------------------------------- - -The idea behind the "home scheme" is that you build and maintain a personal -stash of Python modules. This scheme's name is derived from the idea of a -"home" directory on Unix, since it's not unusual for a Unix user to make their -home directory have a layout similar to :file:`/usr/` or :file:`/usr/local/`. -This scheme can be used by anyone, regardless of the operating system they -are installing for. - -Installing a new module distribution is as simple as :: - - python setup.py install --home= - -where you can supply any directory you like for the :option:`--home` option. On -Unix, lazy typists can just type a tilde (``~``); the :command:`install` command -will expand this to your home directory:: - - python setup.py install --home=~ - -The :option:`--home` option defines the installation base directory. Files are -installed to the following directories under the installation base as follows: - -+------------------------------+---------------------------+-----------------------------+ -| Type of file | Installation Directory | Override option | -+==============================+===========================+=============================+ -| pure module distribution | :file:`{home}/lib/python` | :option:`--install-purelib` | -+------------------------------+---------------------------+-----------------------------+ -| non-pure module distribution | :file:`{home}/lib/python` | :option:`--install-platlib` | -+------------------------------+---------------------------+-----------------------------+ -| scripts | :file:`{home}/bin` | :option:`--install-scripts` | -+------------------------------+---------------------------+-----------------------------+ -| data | :file:`{home}/share` | :option:`--install-data` | -+------------------------------+---------------------------+-----------------------------+ - - -.. _inst-alt-install-home: - -Alternate installation: Unix (the prefix scheme) ------------------------------------------------- - -The "prefix scheme" is useful when you wish to use one Python installation to -perform the build/install (i.e., to run the setup script), but install modules -into the third-party module directory of a different Python installation (or -something that looks like a different Python installation). If this sounds a -trifle unusual, it is---that's why the "home scheme" comes first. However, -there are at least two known cases where the prefix scheme will be useful. - -First, consider that many Linux distributions put Python in :file:`/usr`, rather -than the more traditional :file:`/usr/local`. This is entirely appropriate, -since in those cases Python is part of "the system" rather than a local add-on. -However, if you are installing Python modules from source, you probably want -them to go in :file:`/usr/local/lib/python2.{X}` rather than -:file:`/usr/lib/python2.{X}`. This can be done with :: - - /usr/bin/python setup.py install --prefix=/usr/local - -Another possibility is a network filesystem where the name used to write to a -remote directory is different from the name used to read it: for example, the -Python interpreter accessed as :file:`/usr/local/bin/python` might search for -modules in :file:`/usr/local/lib/python2.{X}`, but those modules would have to -be installed to, say, :file:`/mnt/{@server}/export/lib/python2.{X}`. This could -be done with :: - - /usr/local/bin/python setup.py install --prefix=/mnt/@server/export - -In either case, the :option:`--prefix` option defines the installation base, and -the :option:`--exec-prefix` option defines the platform-specific installation -base, which is used for platform-specific files. (Currently, this just means -non-pure module distributions, but could be expanded to C libraries, binary -executables, etc.) If :option:`--exec-prefix` is not supplied, it defaults to -:option:`--prefix`. Files are installed as follows: - -+------------------------------+-----------------------------------------------------+-----------------------------+ -| Type of file | Installation Directory | Override option | -+==============================+=====================================================+=============================+ -| pure module distribution | :file:`{prefix}/lib/python{X.Y}/site-packages` | :option:`--install-purelib` | -+------------------------------+-----------------------------------------------------+-----------------------------+ -| non-pure module distribution | :file:`{exec-prefix}/lib/python{X.Y}/site-packages` | :option:`--install-platlib` | -+------------------------------+-----------------------------------------------------+-----------------------------+ -| scripts | :file:`{prefix}/bin` | :option:`--install-scripts` | -+------------------------------+-----------------------------------------------------+-----------------------------+ -| data | :file:`{prefix}/share` | :option:`--install-data` | -+------------------------------+-----------------------------------------------------+-----------------------------+ - -There is no requirement that :option:`--prefix` or :option:`--exec-prefix` -actually point to an alternate Python installation; if the directories listed -above do not already exist, they are created at installation time. - -Incidentally, the real reason the prefix scheme is important is simply that a -standard Unix installation uses the prefix scheme, but with :option:`--prefix` -and :option:`--exec-prefix` supplied by Python itself as ``sys.prefix`` and -``sys.exec_prefix``. Thus, you might think you'll never use the prefix scheme, -but every time you run ``python setup.py install`` without any other options, -you're using it. - -Note that installing extensions to an alternate Python installation has no -effect on how those extensions are built: in particular, the Python header files -(:file:`Python.h` and friends) installed with the Python interpreter used to run -the setup script will be used in compiling extensions. It is your -responsibility to ensure that the interpreter used to run extensions installed -in this way is compatible with the interpreter used to build them. The best way -to do this is to ensure that the two interpreters are the same version of Python -(possibly different builds, or possibly copies of the same build). (Of course, -if your :option:`--prefix` and :option:`--exec-prefix` don't even point to an -alternate Python installation, this is immaterial.) - - -.. _inst-alt-install-windows: - -Alternate installation: Windows (the prefix scheme) ---------------------------------------------------- - -Windows has no concept of a user's home directory, and since the standard Python -installation under Windows is simpler than under Unix, the :option:`--prefix` -option has traditionally been used to install additional packages in separate -locations on Windows. :: - - python setup.py install --prefix="\Temp\Python" - -to install modules to the :file:`\\Temp\\Python` directory on the current drive. - -The installation base is defined by the :option:`--prefix` option; the -:option:`--exec-prefix` option is not supported under Windows. Files are -installed as follows: - -+------------------------------+---------------------------+-----------------------------+ -| Type of file | Installation Directory | Override option | -+==============================+===========================+=============================+ -| pure module distribution | :file:`{prefix}` | :option:`--install-purelib` | -+------------------------------+---------------------------+-----------------------------+ -| non-pure module distribution | :file:`{prefix}` | :option:`--install-platlib` | -+------------------------------+---------------------------+-----------------------------+ -| scripts | :file:`{prefix}\\Scripts` | :option:`--install-scripts` | -+------------------------------+---------------------------+-----------------------------+ -| data | :file:`{prefix}\\Data` | :option:`--install-data` | -+------------------------------+---------------------------+-----------------------------+ - - -.. _inst-custom-install: - -Custom Installation -=================== - -Sometimes, the alternate installation schemes described in section -:ref:`inst-alt-install` just don't do what you want. You might want to tweak just -one or two directories while keeping everything under the same base directory, -or you might want to completely redefine the installation scheme. In either -case, you're creating a *custom installation scheme*. - -You probably noticed the column of "override options" in the tables describing -the alternate installation schemes above. Those options are how you define a -custom installation scheme. These override options can be relative, absolute, -or explicitly defined in terms of one of the installation base directories. -(There are two installation base directories, and they are normally the same--- -they only differ when you use the Unix "prefix scheme" and supply different -:option:`--prefix` and :option:`--exec-prefix` options.) - -For example, say you're installing a module distribution to your home directory -under Unix---but you want scripts to go in :file:`~/scripts` rather than -:file:`~/bin`. As you might expect, you can override this directory with the -:option:`--install-scripts` option; in this case, it makes most sense to supply -a relative path, which will be interpreted relative to the installation base -directory (your home directory, in this case):: - - python setup.py install --home=~ --install-scripts=scripts - -Another Unix example: suppose your Python installation was built and installed -with a prefix of :file:`/usr/local/python`, so under a standard installation -scripts will wind up in :file:`/usr/local/python/bin`. If you want them in -:file:`/usr/local/bin` instead, you would supply this absolute directory for the -:option:`--install-scripts` option:: - - python setup.py install --install-scripts=/usr/local/bin - -(This performs an installation using the "prefix scheme," where the prefix is -whatever your Python interpreter was installed with--- :file:`/usr/local/python` -in this case.) - -If you maintain Python on Windows, you might want third-party modules to live in -a subdirectory of :file:`{prefix}`, rather than right in :file:`{prefix}` -itself. This is almost as easy as customizing the script installation directory ----you just have to remember that there are two types of modules to worry about, -pure modules and non-pure modules (i.e., modules from a non-pure distribution). -For example:: - - python setup.py install --install-purelib=Site --install-platlib=Site - -The specified installation directories are relative to :file:`{prefix}`. Of -course, you also have to ensure that these directories are in Python's module -search path, such as by putting a :file:`.pth` file in :file:`{prefix}`. See -section :ref:`inst-search-path` to find out how to modify Python's search path. - -If you want to define an entire installation scheme, you just have to supply all -of the installation directory options. The recommended way to do this is to -supply relative paths; for example, if you want to maintain all Python -module-related files under :file:`python` in your home directory, and you want a -separate directory for each platform that you use your home directory from, you -might define the following installation scheme:: - - python setup.py install --home=~ \ - --install-purelib=python/lib \ - --install-platlib=python/lib.$PLAT \ - --install-scripts=python/scripts - --install-data=python/data - -or, equivalently, :: - - python setup.py install --home=~/python \ - --install-purelib=lib \ - --install-platlib='lib.$PLAT' \ - --install-scripts=scripts - --install-data=data - -``$PLAT`` is not (necessarily) an environment variable---it will be expanded by -the Distutils as it parses your command line options, just as it does when -parsing your configuration file(s). - -Obviously, specifying the entire installation scheme every time you install a -new module distribution would be very tedious. Thus, you can put these options -into your Distutils config file (see section :ref:`inst-config-files`):: - - [install] - install-base=$HOME - install-purelib=python/lib - install-platlib=python/lib.$PLAT - install-scripts=python/scripts - install-data=python/data - -or, equivalently, :: - - [install] - install-base=$HOME/python - install-purelib=lib - install-platlib=lib.$PLAT - install-scripts=scripts - install-data=data - -Note that these two are *not* equivalent if you supply a different installation -base directory when you run the setup script. For example, :: - - python setup.py install --install-base=/tmp - -would install pure modules to :file:`{/tmp/python/lib}` in the first case, and -to :file:`{/tmp/lib}` in the second case. (For the second case, you probably -want to supply an installation base of :file:`/tmp/python`.) - -You probably noticed the use of ``$HOME`` and ``$PLAT`` in the sample -configuration file input. These are Distutils configuration variables, which -bear a strong resemblance to environment variables. In fact, you can use -environment variables in config files on platforms that have such a notion but -the Distutils additionally define a few extra variables that may not be in your -environment, such as ``$PLAT``. (And of course, on systems that don't have -environment variables, such as Mac OS 9, the configuration variables supplied by -the Distutils are the only ones you can use.) See section :ref:`inst-config-files` -for details. - -.. XXX need some Windows examples---when would custom installation schemes be - needed on those platforms? - - -.. XXX I'm not sure where this section should go. - -.. _inst-search-path: - -Modifying Python's Search Path ------------------------------- - -When the Python interpreter executes an :keyword:`import` statement, it searches -for both Python code and extension modules along a search path. A default value -for the path is configured into the Python binary when the interpreter is built. -You can determine the path by importing the :mod:`sys` module and printing the -value of ``sys.path``. :: - - $ python - Python 2.2 (#11, Oct 3 2002, 13:31:27) - [GCC 2.96 20000731 (Red Hat Linux 7.3 2.96-112)] on linux2 - Type "help", "copyright", "credits" or "license" for more information. - >>> import sys - >>> sys.path - ['', '/usr/local/lib/python2.3', '/usr/local/lib/python2.3/plat-linux2', - '/usr/local/lib/python2.3/lib-tk', '/usr/local/lib/python2.3/lib-dynload', - '/usr/local/lib/python2.3/site-packages'] - >>> - -The null string in ``sys.path`` represents the current working directory. - -The expected convention for locally installed packages is to put them in the -:file:`{...}/site-packages/` directory, but you may want to install Python -modules into some arbitrary directory. For example, your site may have a -convention of keeping all software related to the web server under :file:`/www`. -Add-on Python modules might then belong in :file:`/www/python`, and in order to -import them, this directory must be added to ``sys.path``. There are several -different ways to add the directory. - -The most convenient way is to add a path configuration file to a directory -that's already on Python's path, usually to the :file:`.../site-packages/` -directory. Path configuration files have an extension of :file:`.pth`, and each -line must contain a single path that will be appended to ``sys.path``. (Because -the new paths are appended to ``sys.path``, modules in the added directories -will not override standard modules. This means you can't use this mechanism for -installing fixed versions of standard modules.) - -Paths can be absolute or relative, in which case they're relative to the -directory containing the :file:`.pth` file. See the documentation of -the :mod:`site` module for more information. - -A slightly less convenient way is to edit the :file:`site.py` file in Python's -standard library, and modify ``sys.path``. :file:`site.py` is automatically -imported when the Python interpreter is executed, unless the :option:`-S` switch -is supplied to suppress this behaviour. So you could simply edit -:file:`site.py` and add two lines to it:: - - import sys - sys.path.append('/www/python/') - -However, if you reinstall the same major version of Python (perhaps when -upgrading from 2.2 to 2.2.2, for example) :file:`site.py` will be overwritten by -the stock version. You'd have to remember that it was modified and save a copy -before doing the installation. - -There are two environment variables that can modify ``sys.path``. -:envvar:`PYTHONHOME` sets an alternate value for the prefix of the Python -installation. For example, if :envvar:`PYTHONHOME` is set to ``/www/python``, -the search path will be set to ``['', '/www/python/lib/pythonX.Y/', -'/www/python/lib/pythonX.Y/plat-linux2', ...]``. - -The :envvar:`PYTHONPATH` variable can be set to a list of paths that will be -added to the beginning of ``sys.path``. For example, if :envvar:`PYTHONPATH` is -set to ``/www/python:/opt/py``, the search path will begin with -``['/www/python', '/opt/py']``. (Note that directories must exist in order to -be added to ``sys.path``; the :mod:`site` module removes paths that don't -exist.) - -Finally, ``sys.path`` is just a regular Python list, so any Python application -can modify it by adding or removing entries. - - -.. _inst-config-files: - -Distutils Configuration Files -============================= - -As mentioned above, you can use Distutils configuration files to record personal -or site preferences for any Distutils options. That is, any option to any -command can be stored in one of two or three (depending on your platform) -configuration files, which will be consulted before the command-line is parsed. -This means that configuration files will override default values, and the -command-line will in turn override configuration files. Furthermore, if -multiple configuration files apply, values from "earlier" files are overridden -by "later" files. - - -.. _inst-config-filenames: - -Location and names of config files ----------------------------------- - -The names and locations of the configuration files vary slightly across -platforms. On Unix and Mac OS X, the three configuration files (in the order -they are processed) are: - -+--------------+----------------------------------------------------------+-------+ -| Type of file | Location and filename | Notes | -+==============+==========================================================+=======+ -| system | :file:`{prefix}/lib/python{ver}/distutils/distutils.cfg` | \(1) | -+--------------+----------------------------------------------------------+-------+ -| personal | :file:`$HOME/.pydistutils.cfg` | \(2) | -+--------------+----------------------------------------------------------+-------+ -| local | :file:`setup.cfg` | \(3) | -+--------------+----------------------------------------------------------+-------+ - -And on Windows, the configuration files are: - -+--------------+-------------------------------------------------+-------+ -| Type of file | Location and filename | Notes | -+==============+=================================================+=======+ -| system | :file:`{prefix}\\Lib\\distutils\\distutils.cfg` | \(4) | -+--------------+-------------------------------------------------+-------+ -| personal | :file:`%HOME%\\pydistutils.cfg` | \(5) | -+--------------+-------------------------------------------------+-------+ -| local | :file:`setup.cfg` | \(3) | -+--------------+-------------------------------------------------+-------+ - -On all platforms, the "personal" file can be temporarily disabled by -passing the `--no-user-cfg` option. - -Notes: - -(1) - Strictly speaking, the system-wide configuration file lives in the directory - where the Distutils are installed; under Python 1.6 and later on Unix, this is - as shown. For Python 1.5.2, the Distutils will normally be installed to - :file:`{prefix}/lib/python1.5/site-packages/distutils`, so the system - configuration file should be put there under Python 1.5.2. - -(2) - On Unix, if the :envvar:`HOME` environment variable is not defined, the user's - home directory will be determined with the :func:`getpwuid` function from the - standard :mod:`pwd` module. This is done by the :func:`os.path.expanduser` - function used by Distutils. - -(3) - I.e., in the current directory (usually the location of the setup script). - -(4) - (See also note (1).) Under Python 1.6 and later, Python's default "installation - prefix" is :file:`C:\\Python`, so the system configuration file is normally - :file:`C:\\Python\\Lib\\distutils\\distutils.cfg`. Under Python 1.5.2, the - default prefix was :file:`C:\\Program Files\\Python`, and the Distutils were not - part of the standard library---so the system configuration file would be - :file:`C:\\Program Files\\Python\\distutils\\distutils.cfg` in a standard Python - 1.5.2 installation under Windows. - -(5) - On Windows, if the :envvar:`HOME` environment variable is not defined, - :envvar:`USERPROFILE` then :envvar:`HOMEDRIVE` and :envvar:`HOMEPATH` will - be tried. This is done by the :func:`os.path.expanduser` function used - by Distutils. - - -.. _inst-config-syntax: - -Syntax of config files ----------------------- - -The Distutils configuration files all have the same syntax. The config files -are grouped into sections. There is one section for each Distutils command, -plus a ``global`` section for global options that affect every command. Each -section consists of one option per line, specified as ``option=value``. - -For example, the following is a complete config file that just forces all -commands to run quietly by default:: - - [global] - verbose=0 - -If this is installed as the system config file, it will affect all processing of -any Python module distribution by any user on the current system. If it is -installed as your personal config file (on systems that support them), it will -affect only module distributions processed by you. And if it is used as the -:file:`setup.cfg` for a particular module distribution, it affects only that -distribution. - -You could override the default "build base" directory and make the -:command:`build\*` commands always forcibly rebuild all files with the -following:: - - [build] - build-base=blib - force=1 - -which corresponds to the command-line arguments :: - - python setup.py build --build-base=blib --force - -except that including the :command:`build` command on the command-line means -that command will be run. Including a particular command in config files has no -such implication; it only means that if the command is run, the options in the -config file will apply. (Or if other commands that derive values from it are -run, they will use the values in the config file.) - -You can find out the complete list of options for any command using the -:option:`--help` option, e.g.:: - - python setup.py build --help - -and you can find out the complete list of global options by using -:option:`--help` without a command:: - - python setup.py --help - -See also the "Reference" section of the "Distributing Python Modules" manual. - - -.. _inst-building-ext: - -Building Extensions: Tips and Tricks -==================================== - -Whenever possible, the Distutils try to use the configuration information made -available by the Python interpreter used to run the :file:`setup.py` script. -For example, the same compiler and linker flags used to compile Python will also -be used for compiling extensions. Usually this will work well, but in -complicated situations this might be inappropriate. This section discusses how -to override the usual Distutils behaviour. - - -.. _inst-tweak-flags: - -Tweaking compiler/linker flags ------------------------------- - -Compiling a Python extension written in C or C++ will sometimes require -specifying custom flags for the compiler and linker in order to use a particular -library or produce a special kind of object code. This is especially true if the -extension hasn't been tested on your platform, or if you're trying to -cross-compile Python. - -In the most general case, the extension author might have foreseen that -compiling the extensions would be complicated, and provided a :file:`Setup` file -for you to edit. This will likely only be done if the module distribution -contains many separate extension modules, or if they often require elaborate -sets of compiler flags in order to work. - -A :file:`Setup` file, if present, is parsed in order to get a list of extensions -to build. Each line in a :file:`Setup` describes a single module. Lines have -the following structure:: - - module ... [sourcefile ...] [cpparg ...] [library ...] - - -Let's examine each of the fields in turn. - -* *module* is the name of the extension module to be built, and should be a - valid Python identifier. You can't just change this in order to rename a module - (edits to the source code would also be needed), so this should be left alone. - -* *sourcefile* is anything that's likely to be a source code file, at least - judging by the filename. Filenames ending in :file:`.c` are assumed to be - written in C, filenames ending in :file:`.C`, :file:`.cc`, and :file:`.c++` are - assumed to be C++, and filenames ending in :file:`.m` or :file:`.mm` are assumed - to be in Objective C. - -* *cpparg* is an argument for the C preprocessor, and is anything starting with - :option:`-I`, :option:`-D`, :option:`-U` or :option:`-C`. - -* *library* is anything ending in :file:`.a` or beginning with :option:`-l` or - :option:`-L`. - -If a particular platform requires a special library on your platform, you can -add it by editing the :file:`Setup` file and running ``python setup.py build``. -For example, if the module defined by the line :: - - foo foomodule.c - -must be linked with the math library :file:`libm.a` on your platform, simply add -:option:`-lm` to the line:: - - foo foomodule.c -lm - -Arbitrary switches intended for the compiler or the linker can be supplied with -the :option:`-Xcompiler` *arg* and :option:`-Xlinker` *arg* options:: - - foo foomodule.c -Xcompiler -o32 -Xlinker -shared -lm - -The next option after :option:`-Xcompiler` and :option:`-Xlinker` will be -appended to the proper command line, so in the above example the compiler will -be passed the :option:`-o32` option, and the linker will be passed -:option:`-shared`. If a compiler option requires an argument, you'll have to -supply multiple :option:`-Xcompiler` options; for example, to pass ``-x c++`` -the :file:`Setup` file would have to contain ``-Xcompiler -x -Xcompiler c++``. - -Compiler flags can also be supplied through setting the :envvar:`CFLAGS` -environment variable. If set, the contents of :envvar:`CFLAGS` will be added to -the compiler flags specified in the :file:`Setup` file. - - -.. _inst-non-ms-compilers: - -Using non-Microsoft compilers on Windows ----------------------------------------- - -.. sectionauthor:: Rene Liebscher - - - -Borland/CodeGear C++ -^^^^^^^^^^^^^^^^^^^^ - -This subsection describes the necessary steps to use Distutils with the Borland -C++ compiler version 5.5. First you have to know that Borland's object file -format (OMF) is different from the format used by the Python version you can -download from the Python or ActiveState Web site. (Python is built with -Microsoft Visual C++, which uses COFF as the object file format.) For this -reason you have to convert Python's library :file:`python25.lib` into the -Borland format. You can do this as follows: - -.. Should we mention that users have to create cfg-files for the compiler? -.. see also http://community.borland.com/article/0,1410,21205,00.html - -:: - - coff2omf python25.lib python25_bcpp.lib - -The :file:`coff2omf` program comes with the Borland compiler. The file -:file:`python25.lib` is in the :file:`Libs` directory of your Python -installation. If your extension uses other libraries (zlib, ...) you have to -convert them too. - -The converted files have to reside in the same directories as the normal -libraries. - -How does Distutils manage to use these libraries with their changed names? If -the extension needs a library (eg. :file:`foo`) Distutils checks first if it -finds a library with suffix :file:`_bcpp` (eg. :file:`foo_bcpp.lib`) and then -uses this library. In the case it doesn't find such a special library it uses -the default name (:file:`foo.lib`.) [#]_ - -To let Distutils compile your extension with Borland C++ you now have to type:: - - python setup.py build --compiler=bcpp - -If you want to use the Borland C++ compiler as the default, you could specify -this in your personal or system-wide configuration file for Distutils (see -section :ref:`inst-config-files`.) - - -.. seealso:: - - `C++Builder Compiler `_ - Information about the free C++ compiler from Borland, including links to the - download pages. - - `Creating Python Extensions Using Borland's Free Compiler `_ - Document describing how to use Borland's free command-line C++ compiler to build - Python. - - -GNU C / Cygwin / MinGW -^^^^^^^^^^^^^^^^^^^^^^ - -This section describes the necessary steps to use Distutils with the GNU C/C++ -compilers in their Cygwin and MinGW distributions. [#]_ For a Python interpreter -that was built with Cygwin, everything should work without any of these -following steps. - -Not all extensions can be built with MinGW or Cygwin, but many can. Extensions -most likely to not work are those that use C++ or depend on Microsoft Visual C -extensions. - -To let Distutils compile your extension with Cygwin you have to type:: - - python setup.py build --compiler=cygwin - -and for Cygwin in no-cygwin mode [#]_ or for MinGW type:: - - python setup.py build --compiler=mingw32 - -If you want to use any of these options/compilers as default, you should -consider writing it in your personal or system-wide configuration file for -Distutils (see section :ref:`inst-config-files`.) - -Older Versions of Python and MinGW -"""""""""""""""""""""""""""""""""" -The following instructions only apply if you're using a version of Python -inferior to 2.4.1 with a MinGW inferior to 3.0.0 (with -binutils-2.13.90-20030111-1). - -These compilers require some special libraries. This task is more complex than -for Borland's C++, because there is no program to convert the library. First -you have to create a list of symbols which the Python DLL exports. (You can find -a good program for this task at -http://www.emmestech.com/software/pexports-0.43/download_pexports.html). - -.. I don't understand what the next line means. --amk -.. (inclusive the references on data structures.) - -:: - - pexports python25.dll >python25.def - -The location of an installed :file:`python25.dll` will depend on the -installation options and the version and language of Windows. In a "just for -me" installation, it will appear in the root of the installation directory. In -a shared installation, it will be located in the system directory. - -Then you can create from these information an import library for gcc. :: - - /cygwin/bin/dlltool --dllname python25.dll --def python25.def --output-lib libpython25.a - -The resulting library has to be placed in the same directory as -:file:`python25.lib`. (Should be the :file:`libs` directory under your Python -installation directory.) - -If your extension uses other libraries (zlib,...) you might have to convert -them too. The converted files have to reside in the same directories as the -normal libraries do. - - -.. seealso:: - - `Building Python modules on MS Windows platform with MinGW `_ - Information about building the required libraries for the MinGW environment. - - -.. rubric:: Footnotes - -.. [#] This also means you could replace all existing COFF-libraries with OMF-libraries - of the same name. - -.. [#] Check http://sources.redhat.com/cygwin/ and http://www.mingw.org/ for more - information - -.. [#] Then you have no POSIX emulation available, but you also don't need - :file:`cygwin1.dll`. diff -r 2e49722c7263 -r 6944bdf1289a Doc/distutils/introduction.rst --- a/Doc/distutils/introduction.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/distutils/introduction.rst Sat May 14 18:40:38 2011 +0200 @@ -79,17 +79,11 @@ for an example) To create a source distribution for this module, you would create a setup -script, :file:`setup.py`, containing the above code, and run this command from a -terminal:: +script, :file:`setup.py`, containing the above code, and run:: python setup.py sdist -For Windows, open a command prompt windows ("DOS box") and change the command -to:: - - setup.py sdist - -:command:`sdist` will create an archive file (e.g., tarball on Unix, ZIP file on Windows) +which will create an archive file (e.g., tarball on Unix, ZIP file on Windows) containing your setup script :file:`setup.py`, and your module :file:`foo.py`. The archive file will be named :file:`foo-1.0.tar.gz` (or :file:`.zip`), and will unpack into a directory :file:`foo-1.0`. diff -r 2e49722c7263 -r 6944bdf1289a Doc/documenting/building.rst --- a/Doc/documenting/building.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/documenting/building.rst Sat May 14 18:40:38 2011 +0200 @@ -14,7 +14,6 @@ Luckily, a Makefile has been prepared so that on Unix, provided you have installed Python and Subversion, you can just run :: - cd Doc make html to check out the necessary toolset in the :file:`tools/` subdirectory and build diff -r 2e49722c7263 -r 6944bdf1289a Doc/documenting/markup.rst --- a/Doc/documenting/markup.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/documenting/markup.rst Sat May 14 18:40:38 2011 +0200 @@ -98,12 +98,11 @@ Spam or ham the foo. -The signatures of object methods or data attributes should not include the -class name, but be nested in a class directive. The generated files will -reflect this nesting, and the target identifiers (for HTML output) will use -both the class and method name, to enable consistent cross-references. If you -describe methods belonging to an abstract protocol such as context managers, -use a class directive with a (pseudo-)type name too to make the +The signatures of object methods or data attributes should always include the +type name (``.. method:: FileInput.input(...)``), even if it is obvious from the +context which type they belong to; this is to enable consistent +cross-references. If you describe methods belonging to an abstract protocol, +such as "context managers", include a (pseudo-)type name too to make the index entries more informative. The directives are: diff -r 2e49722c7263 -r 6944bdf1289a Doc/documenting/style.rst --- a/Doc/documenting/style.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/documenting/style.rst Sat May 14 18:40:38 2011 +0200 @@ -136,7 +136,7 @@ Economy of Expression --------------------- -More documentation is not necessarily better documentation. Err on the side +More documentation is not necessarily better documentation. Error on the side of being succinct. It is an unfortunate fact that making documentation longer can be an impediment @@ -198,7 +198,7 @@ The tone of the tutorial (and all the docs) needs to be respectful of the reader's intelligence. Don't presume that the readers are stupid. Lay out the relevant information, show motivating use cases, provide glossary links, and do -your best to connect-the-dots, but don't talk down to them or waste their time. +our best to connect-the-dots, but don't talk down to them or waste their time. The tutorial is meant for newcomers, many of whom will be using the tutorial to evaluate the language as a whole. The experience needs to be positive and not diff -r 2e49722c7263 -r 6944bdf1289a Doc/glossary.rst --- a/Doc/glossary.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/glossary.rst Sat May 14 18:40:38 2011 +0200 @@ -27,14 +27,12 @@ :ref:`2to3-reference`. abstract base class - Abstract base classes complement :term:`duck-typing` by + :ref:`abstract-base-classes` complement :term:`duck-typing` by providing a way to define interfaces when other techniques like - :func:`hasattr` would be clumsy or subtly wrong (for example with - :ref:`magic methods `). Python comes with many built-in ABCs for - data structures (in the :mod:`collections.abc` module), numbers (in the - :mod:`numbers` module), streams (in the :mod:`io` module), import finders - and loaders (in the :mod:`importlib.abc` module). You can create your own - ABCs with the :mod:`abc` module. + :func:`hasattr` would be clumsy. Python comes with many built-in ABCs for + data structures (in the :mod:`collections` module), numbers (in the + :mod:`numbers` module), and streams (in the :mod:`io` module). You can + create your own ABC with the :mod:`abc` module. argument A value passed to a function or method, assigned to a named local @@ -249,7 +247,7 @@ processing, remembering the location execution state (including local variables and pending try-statements). When the generator resumes, it picks-up where it left-off (in contrast to functions which start fresh on - every invocation). + every invocation. .. index:: single: generator expression @@ -432,8 +430,8 @@ mapping A container object that supports arbitrary key lookups and implements the methods specified in the :class:`Mapping` or :class:`MutableMapping` - :ref:`abstract base classes `. Examples - include :class:`dict`, :class:`collections.defaultdict`, + :ref:`abstract base classes `. Examples include + :class:`dict`, :class:`collections.defaultdict`, :class:`collections.OrderedDict` and :class:`collections.Counter`. metaclass diff -r 2e49722c7263 -r 6944bdf1289a Doc/howto/sockets.rst --- a/Doc/howto/sockets.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/howto/sockets.rst Sat May 14 18:40:38 2011 +0200 @@ -23,8 +23,8 @@ working. It doesn't cover the fine points (and there are a lot of them), but I hope it will give you enough background to begin using them decently. -I'm only going to talk about INET (i.e. IPv4) sockets, but they account for at least 99% of -the sockets in use. And I'll only talk about STREAM (i.e. TCP) sockets - unless you really +I'm only going to talk about INET sockets, but they account for at least 99% of +the sockets in use. And I'll only talk about STREAM sockets - unless you really know what you're doing (in which case this HOWTO isn't for you!), you'll get better behavior and performance from a STREAM socket than anything else. I will try to clear up the mystery of what a socket is, as well as some hints on how to @@ -208,10 +208,10 @@ totalsent = totalsent + sent def myreceive(self): - msg = b'' + msg = '' while len(msg) < MSGLEN: chunk = self.sock.recv(MSGLEN-len(msg)) - if chunk == b'': + if chunk == '': raise RuntimeError("socket connection broken") msg = msg + chunk return msg @@ -356,7 +356,8 @@ In return, you will get three lists. They contain the sockets that are actually readable, writable and in error. Each of these lists is a subset (possibly -empty) of the corresponding list you passed in. +empty) of the corresponding list you passed in. If you put a socket in more +than one input list, it will only be (at most) in one output list. If a socket is in the output readable list, you can be as-close-to-certain-as-we-ever-get-in-this-business that a ``recv`` on that @@ -371,6 +372,12 @@ potential_writers list. If it shows up in the writable list, you have a decent chance that it has connected. +One very nasty problem with ``select``: if somewhere in those input lists of +sockets is one which has died a nasty death, the ``select`` will fail. You then +need to loop through every single damn socket in all those lists and do a +``select([sock],[],[],0)`` until you find the bad one. That timeout of 0 means +it won't take long, but it's ugly. + Actually, ``select`` can be handy even with blocking sockets. It's one way of determining whether you will block - the socket returns as readable when there's something in the buffers. However, this still doesn't help with the problem of @@ -380,6 +387,32 @@ files. Don't try this on Windows. On Windows, ``select`` works with sockets only. Also note that in C, many of the more advanced socket options are done differently on Windows. In fact, on Windows I usually use threads (which work -very, very well) with my sockets. +very, very well) with my sockets. Face it, if you want any kind of performance, +your code will look very different on Windows than on Unix. +Performance +----------- + +There's no question that the fastest sockets code uses non-blocking sockets and +select to multiplex them. You can put together something that will saturate a +LAN connection without putting any strain on the CPU. The trouble is that an app +written this way can't do much of anything else - it needs to be ready to +shuffle bytes around at all times. + +Assuming that your app is actually supposed to do something more than that, +threading is the optimal solution, (and using non-blocking sockets will be +faster than using blocking sockets). Unfortunately, threading support in Unixes +varies both in API and quality. So the normal Unix solution is to fork a +subprocess to deal with each connection. The overhead for this is significant +(and don't do this on Windows - the overhead of process creation is enormous +there). It also means that unless each subprocess is completely independent, +you'll need to use another form of IPC, say a pipe, or shared memory and +semaphores, to communicate between the parent and child processes. + +Finally, remember that even though blocking sockets are somewhat slower than +non-blocking, in many cases they are the "right" solution. After all, if your +app is driven by the data it receives over a socket, there's not much sense in +complicating the logic just so your app can wait on ``select`` instead of +``recv``. + diff -r 2e49722c7263 -r 6944bdf1289a Doc/install/index.rst --- a/Doc/install/index.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/install/index.rst Sat May 14 18:40:38 2011 +0200 @@ -1,10 +1,12 @@ -.. _packaging-install-index: +.. highlightlang:: none -****************************** - Installing Python Projects -****************************** +.. _install-index: -:Author: The Fellowship of the Packaging +***************************** + Installing Python Modules +***************************** + +:Author: Greg Ward :Release: |version| :Date: |today| @@ -14,43 +16,990 @@ about Python and aren't about to learn the language just in order to install and maintain it for their users, i.e. system administrators. Thus, I have to be sure to explain the basics at some point: - sys.path and PYTHONPATH at least. Should probably give pointers to + sys.path and PYTHONPATH at least. Should probably give pointers to other docs on "import site", PYTHONSTARTUP, PYTHONHOME, etc. Finally, it might be useful to include all the material from my "Care - and Feeding of a Python Installation" talk in here somewhere. Yow! + and Feeding of a Python Installation" talk in here somewhere. Yow! .. topic:: Abstract - This document describes Packaging from the end-user's point of view: it - explains how to extend the functionality of a standard Python installation by - building and installing third-party Python modules and applications. + This document describes the Python Distribution Utilities ("Distutils") from the + end-user's point-of-view, describing how to extend the capabilities of a + standard Python installation by building and installing third-party Python + modules and extensions. -This guide is split into a simple overview followed by a longer presentation of -the :program:`pysetup` script, the Python package management tool used to -build, distribute, search for, install, remove and list Python distributions. +.. _inst-intro: -.. TODO integrate install and pysetup instead of duplicating +Introduction +============ -.. toctree:: - :maxdepth: 2 - :numbered: +Although Python's extensive standard library covers many programming needs, +there often comes a time when you need to add some new functionality to your +Python installation in the form of third-party modules. This might be necessary +to support your own programming, or to support an application that you want to +use and that happens to be written in Python. - install - pysetup - pysetup-config - pysetup-servers +In the past, there has been little support for adding third-party modules to an +existing Python installation. With the introduction of the Python Distribution +Utilities (Distutils for short) in Python 2.0, this changed. + +This document is aimed primarily at the people who need to install third-party +Python modules: end-users and system administrators who just need to get some +Python application running, and existing Python programmers who want to add some +new goodies to their toolbox. You don't need to know Python to read this +document; there will be some brief forays into using Python's interactive mode +to explore your installation, but that's it. If you're looking for information +on how to distribute your own Python modules so that others may use them, see +the :ref:`distutils-index` manual. + + +.. _inst-trivial-install: + +Best case: trivial installation +------------------------------- + +In the best case, someone will have prepared a special version of the module +distribution you want to install that is targeted specifically at your platform +and is installed just like any other software on your platform. For example, +the module developer might make an executable installer available for Windows +users, an RPM package for users of RPM-based Linux systems (Red Hat, SuSE, +Mandrake, and many others), a Debian package for users of Debian-based Linux +systems, and so forth. + +In that case, you would download the installer appropriate to your platform and +do the obvious thing with it: run it if it's an executable installer, ``rpm +--install`` it if it's an RPM, etc. You don't need to run Python or a setup +script, you don't need to compile anything---you might not even need to read any +instructions (although it's always a good idea to do so anyways). + +Of course, things will not always be that easy. You might be interested in a +module distribution that doesn't have an easy-to-use installer for your +platform. In that case, you'll have to start with the source distribution +released by the module's author/maintainer. Installing from a source +distribution is not too hard, as long as the modules are packaged in the +standard way. The bulk of this document is about building and installing +modules from standard source distributions. + + +.. _inst-new-standard: + +The new standard: Distutils +--------------------------- + +If you download a module source distribution, you can tell pretty quickly if it +was packaged and distributed in the standard way, i.e. using the Distutils. +First, the distribution's name and version number will be featured prominently +in the name of the downloaded archive, e.g. :file:`foo-1.0.tar.gz` or +:file:`widget-0.9.7.zip`. Next, the archive will unpack into a similarly-named +directory: :file:`foo-1.0` or :file:`widget-0.9.7`. Additionally, the +distribution will contain a setup script :file:`setup.py`, and a file named +:file:`README.txt` or possibly just :file:`README`, which should explain that +building and installing the module distribution is a simple matter of running :: + + python setup.py install + +If all these things are true, then you already know how to build and install the +modules you've just downloaded: Run the command above. Unless you need to +install things in a non-standard way or customize the build process, you don't +really need this manual. Or rather, the above command is everything you need to +get out of this manual. + + +.. _inst-standard-install: + +Standard Build and Install +========================== + +As described in section :ref:`inst-new-standard`, building and installing a module +distribution using the Distutils is usually one simple command:: + + python setup.py install + +On Unix, you'd run this command from a shell prompt; on Windows, you have to +open a command prompt window ("DOS box") and do it there; on Mac OS X, you open +a :command:`Terminal` window to get a shell prompt. + + +.. _inst-platform-variations: + +Platform variations +------------------- + +You should always run the setup command from the distribution root directory, +i.e. the top-level subdirectory that the module source distribution unpacks +into. For example, if you've just downloaded a module source distribution +:file:`foo-1.0.tar.gz` onto a Unix system, the normal thing to do is:: + + gunzip -c foo-1.0.tar.gz | tar xf - # unpacks into directory foo-1.0 + cd foo-1.0 + python setup.py install + +On Windows, you'd probably download :file:`foo-1.0.zip`. If you downloaded the +archive file to :file:`C:\\Temp`, then it would unpack into +:file:`C:\\Temp\\foo-1.0`; you can use either a archive manipulator with a +graphical user interface (such as WinZip) or a command-line tool (such as +:program:`unzip` or :program:`pkunzip`) to unpack the archive. Then, open a +command prompt window ("DOS box"), and run:: + + cd c:\Temp\foo-1.0 + python setup.py install + + +.. _inst-splitting-up: + +Splitting the job up +-------------------- + +Running ``setup.py install`` builds and installs all modules in one run. If you +prefer to work incrementally---especially useful if you want to customize the +build process, or if things are going wrong---you can use the setup script to do +one thing at a time. This is particularly helpful when the build and install +will be done by different users---for example, you might want to build a module +distribution and hand it off to a system administrator for installation (or do +it yourself, with super-user privileges). + +For example, you can build everything in one step, and then install everything +in a second step, by invoking the setup script twice:: + + python setup.py build + python setup.py install + +If you do this, you will notice that running the :command:`install` command +first runs the :command:`build` command, which---in this case---quickly notices +that it has nothing to do, since everything in the :file:`build` directory is +up-to-date. + +You may not need this ability to break things down often if all you do is +install modules downloaded off the 'net, but it's very handy for more advanced +tasks. If you get into distributing your own Python modules and extensions, +you'll run lots of individual Distutils commands on their own. + + +.. _inst-how-build-works: + +How building works +------------------ + +As implied above, the :command:`build` command is responsible for putting the +files to install into a *build directory*. By default, this is :file:`build` +under the distribution root; if you're excessively concerned with speed, or want +to keep the source tree pristine, you can change the build directory with the +:option:`--build-base` option. For example:: + + python setup.py build --build-base=/tmp/pybuild/foo-1.0 + +(Or you could do this permanently with a directive in your system or personal +Distutils configuration file; see section :ref:`inst-config-files`.) Normally, this +isn't necessary. + +The default layout for the build tree is as follows:: + + --- build/ --- lib/ + or + --- build/ --- lib./ + temp./ + +where ```` expands to a brief description of the current OS/hardware +platform and Python version. The first form, with just a :file:`lib` directory, +is used for "pure module distributions"---that is, module distributions that +include only pure Python modules. If a module distribution contains any +extensions (modules written in C/C++), then the second form, with two ```` +directories, is used. In that case, the :file:`temp.{plat}` directory holds +temporary files generated by the compile/link process that don't actually get +installed. In either case, the :file:`lib` (or :file:`lib.{plat}`) directory +contains all Python modules (pure Python and extensions) that will be installed. + +In the future, more directories will be added to handle Python scripts, +documentation, binary executables, and whatever else is needed to handle the job +of installing Python modules and applications. + + +.. _inst-how-install-works: + +How installation works +---------------------- + +After the :command:`build` command runs (whether you run it explicitly, or the +:command:`install` command does it for you), the work of the :command:`install` +command is relatively simple: all it has to do is copy everything under +:file:`build/lib` (or :file:`build/lib.{plat}`) to your chosen installation +directory. + +If you don't choose an installation directory---i.e., if you just run ``setup.py +install``\ ---then the :command:`install` command installs to the standard +location for third-party Python modules. This location varies by platform and +by how you built/installed Python itself. On Unix (and Mac OS X, which is also +Unix-based), it also depends on whether the module distribution being installed +is pure Python or contains extensions ("non-pure"): + ++-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ +| Platform | Standard installation location | Default value | Notes | ++=================+=====================================================+==================================================+=======+ +| Unix (pure) | :file:`{prefix}/lib/python{X.Y}/site-packages` | :file:`/usr/local/lib/python{X.Y}/site-packages` | \(1) | ++-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ +| Unix (non-pure) | :file:`{exec-prefix}/lib/python{X.Y}/site-packages` | :file:`/usr/local/lib/python{X.Y}/site-packages` | \(1) | ++-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ +| Windows | :file:`{prefix}\\Lib\\site-packages` | :file:`C:\\Python{XY}\\Lib\\site-packages` | \(2) | ++-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ + +Notes: + +(1) + Most Linux distributions include Python as a standard part of the system, so + :file:`{prefix}` and :file:`{exec-prefix}` are usually both :file:`/usr` on + Linux. If you build Python yourself on Linux (or any Unix-like system), the + default :file:`{prefix}` and :file:`{exec-prefix}` are :file:`/usr/local`. + +(2) + The default installation directory on Windows was :file:`C:\\Program + Files\\Python` under Python 1.6a1, 1.5.2, and earlier. + +:file:`{prefix}` and :file:`{exec-prefix}` stand for the directories that Python +is installed to, and where it finds its libraries at run-time. They are always +the same under Windows, and very often the same under Unix and Mac OS X. You +can find out what your Python installation uses for :file:`{prefix}` and +:file:`{exec-prefix}` by running Python in interactive mode and typing a few +simple commands. Under Unix, just type ``python`` at the shell prompt. Under +Windows, choose :menuselection:`Start --> Programs --> Python X.Y --> +Python (command line)`. Once the interpreter is started, you type Python code +at the prompt. For example, on my Linux system, I type the three Python +statements shown below, and get the output as shown, to find out my +:file:`{prefix}` and :file:`{exec-prefix}`:: + + Python 2.4 (#26, Aug 7 2004, 17:19:02) + Type "help", "copyright", "credits" or "license" for more information. + >>> import sys + >>> sys.prefix + '/usr' + >>> sys.exec_prefix + '/usr' + +If you don't want to install modules to the standard location, or if you don't +have permission to write there, then you need to read about alternate +installations in section :ref:`inst-alt-install`. If you want to customize your +installation directories more heavily, see section :ref:`inst-custom-install` on +custom installations. + + +.. _inst-alt-install: + +Alternate Installation +====================== + +Often, it is necessary or desirable to install modules to a location other than +the standard location for third-party Python modules. For example, on a Unix +system you might not have permission to write to the standard third-party module +directory. Or you might wish to try out a module before making it a standard +part of your local Python installation. This is especially true when upgrading +a distribution already present: you want to make sure your existing base of +scripts still works with the new version before actually upgrading. + +The Distutils :command:`install` command is designed to make installing module +distributions to an alternate location simple and painless. The basic idea is +that you supply a base directory for the installation, and the +:command:`install` command picks a set of directories (called an *installation +scheme*) under this base directory in which to install files. The details +differ across platforms, so read whichever of the following sections applies to +you. + + +.. _inst-alt-install-prefix: + +Alternate installation: the home scheme +--------------------------------------- + +The idea behind the "home scheme" is that you build and maintain a personal +stash of Python modules. This scheme's name is derived from the idea of a +"home" directory on Unix, since it's not unusual for a Unix user to make their +home directory have a layout similar to :file:`/usr/` or :file:`/usr/local/`. +This scheme can be used by anyone, regardless of the operating system they +are installing for. + +Installing a new module distribution is as simple as :: + + python setup.py install --home= + +where you can supply any directory you like for the :option:`--home` option. On +Unix, lazy typists can just type a tilde (``~``); the :command:`install` command +will expand this to your home directory:: + + python setup.py install --home=~ + +The :option:`--home` option defines the installation base directory. Files are +installed to the following directories under the installation base as follows: + ++------------------------------+---------------------------+-----------------------------+ +| Type of file | Installation Directory | Override option | ++==============================+===========================+=============================+ +| pure module distribution | :file:`{home}/lib/python` | :option:`--install-purelib` | ++------------------------------+---------------------------+-----------------------------+ +| non-pure module distribution | :file:`{home}/lib/python` | :option:`--install-platlib` | ++------------------------------+---------------------------+-----------------------------+ +| scripts | :file:`{home}/bin` | :option:`--install-scripts` | ++------------------------------+---------------------------+-----------------------------+ +| data | :file:`{home}/share` | :option:`--install-data` | ++------------------------------+---------------------------+-----------------------------+ + + +.. _inst-alt-install-home: + +Alternate installation: Unix (the prefix scheme) +------------------------------------------------ + +The "prefix scheme" is useful when you wish to use one Python installation to +perform the build/install (i.e., to run the setup script), but install modules +into the third-party module directory of a different Python installation (or +something that looks like a different Python installation). If this sounds a +trifle unusual, it is---that's why the "home scheme" comes first. However, +there are at least two known cases where the prefix scheme will be useful. + +First, consider that many Linux distributions put Python in :file:`/usr`, rather +than the more traditional :file:`/usr/local`. This is entirely appropriate, +since in those cases Python is part of "the system" rather than a local add-on. +However, if you are installing Python modules from source, you probably want +them to go in :file:`/usr/local/lib/python2.{X}` rather than +:file:`/usr/lib/python2.{X}`. This can be done with :: + + /usr/bin/python setup.py install --prefix=/usr/local + +Another possibility is a network filesystem where the name used to write to a +remote directory is different from the name used to read it: for example, the +Python interpreter accessed as :file:`/usr/local/bin/python` might search for +modules in :file:`/usr/local/lib/python2.{X}`, but those modules would have to +be installed to, say, :file:`/mnt/{@server}/export/lib/python2.{X}`. This could +be done with :: + + /usr/local/bin/python setup.py install --prefix=/mnt/@server/export + +In either case, the :option:`--prefix` option defines the installation base, and +the :option:`--exec-prefix` option defines the platform-specific installation +base, which is used for platform-specific files. (Currently, this just means +non-pure module distributions, but could be expanded to C libraries, binary +executables, etc.) If :option:`--exec-prefix` is not supplied, it defaults to +:option:`--prefix`. Files are installed as follows: + ++------------------------------+-----------------------------------------------------+-----------------------------+ +| Type of file | Installation Directory | Override option | ++==============================+=====================================================+=============================+ +| pure module distribution | :file:`{prefix}/lib/python{X.Y}/site-packages` | :option:`--install-purelib` | ++------------------------------+-----------------------------------------------------+-----------------------------+ +| non-pure module distribution | :file:`{exec-prefix}/lib/python{X.Y}/site-packages` | :option:`--install-platlib` | ++------------------------------+-----------------------------------------------------+-----------------------------+ +| scripts | :file:`{prefix}/bin` | :option:`--install-scripts` | ++------------------------------+-----------------------------------------------------+-----------------------------+ +| data | :file:`{prefix}/share` | :option:`--install-data` | ++------------------------------+-----------------------------------------------------+-----------------------------+ + +There is no requirement that :option:`--prefix` or :option:`--exec-prefix` +actually point to an alternate Python installation; if the directories listed +above do not already exist, they are created at installation time. + +Incidentally, the real reason the prefix scheme is important is simply that a +standard Unix installation uses the prefix scheme, but with :option:`--prefix` +and :option:`--exec-prefix` supplied by Python itself as ``sys.prefix`` and +``sys.exec_prefix``. Thus, you might think you'll never use the prefix scheme, +but every time you run ``python setup.py install`` without any other options, +you're using it. + +Note that installing extensions to an alternate Python installation has no +effect on how those extensions are built: in particular, the Python header files +(:file:`Python.h` and friends) installed with the Python interpreter used to run +the setup script will be used in compiling extensions. It is your +responsibility to ensure that the interpreter used to run extensions installed +in this way is compatible with the interpreter used to build them. The best way +to do this is to ensure that the two interpreters are the same version of Python +(possibly different builds, or possibly copies of the same build). (Of course, +if your :option:`--prefix` and :option:`--exec-prefix` don't even point to an +alternate Python installation, this is immaterial.) + + +.. _inst-alt-install-windows: + +Alternate installation: Windows (the prefix scheme) +--------------------------------------------------- + +Windows has no concept of a user's home directory, and since the standard Python +installation under Windows is simpler than under Unix, the :option:`--prefix` +option has traditionally been used to install additional packages in separate +locations on Windows. :: + + python setup.py install --prefix="\Temp\Python" + +to install modules to the :file:`\\Temp\\Python` directory on the current drive. + +The installation base is defined by the :option:`--prefix` option; the +:option:`--exec-prefix` option is not supported under Windows. Files are +installed as follows: + ++------------------------------+---------------------------+-----------------------------+ +| Type of file | Installation Directory | Override option | ++==============================+===========================+=============================+ +| pure module distribution | :file:`{prefix}` | :option:`--install-purelib` | ++------------------------------+---------------------------+-----------------------------+ +| non-pure module distribution | :file:`{prefix}` | :option:`--install-platlib` | ++------------------------------+---------------------------+-----------------------------+ +| scripts | :file:`{prefix}\\Scripts` | :option:`--install-scripts` | ++------------------------------+---------------------------+-----------------------------+ +| data | :file:`{prefix}\\Data` | :option:`--install-data` | ++------------------------------+---------------------------+-----------------------------+ + + +.. _inst-custom-install: + +Custom Installation +=================== + +Sometimes, the alternate installation schemes described in section +:ref:`inst-alt-install` just don't do what you want. You might want to tweak just +one or two directories while keeping everything under the same base directory, +or you might want to completely redefine the installation scheme. In either +case, you're creating a *custom installation scheme*. + +You probably noticed the column of "override options" in the tables describing +the alternate installation schemes above. Those options are how you define a +custom installation scheme. These override options can be relative, absolute, +or explicitly defined in terms of one of the installation base directories. +(There are two installation base directories, and they are normally the same--- +they only differ when you use the Unix "prefix scheme" and supply different +:option:`--prefix` and :option:`--exec-prefix` options.) + +For example, say you're installing a module distribution to your home directory +under Unix---but you want scripts to go in :file:`~/scripts` rather than +:file:`~/bin`. As you might expect, you can override this directory with the +:option:`--install-scripts` option; in this case, it makes most sense to supply +a relative path, which will be interpreted relative to the installation base +directory (your home directory, in this case):: + + python setup.py install --home=~ --install-scripts=scripts + +Another Unix example: suppose your Python installation was built and installed +with a prefix of :file:`/usr/local/python`, so under a standard installation +scripts will wind up in :file:`/usr/local/python/bin`. If you want them in +:file:`/usr/local/bin` instead, you would supply this absolute directory for the +:option:`--install-scripts` option:: + + python setup.py install --install-scripts=/usr/local/bin + +(This performs an installation using the "prefix scheme," where the prefix is +whatever your Python interpreter was installed with--- :file:`/usr/local/python` +in this case.) + +If you maintain Python on Windows, you might want third-party modules to live in +a subdirectory of :file:`{prefix}`, rather than right in :file:`{prefix}` +itself. This is almost as easy as customizing the script installation directory +---you just have to remember that there are two types of modules to worry about, +pure modules and non-pure modules (i.e., modules from a non-pure distribution). +For example:: + + python setup.py install --install-purelib=Site --install-platlib=Site + +The specified installation directories are relative to :file:`{prefix}`. Of +course, you also have to ensure that these directories are in Python's module +search path, such as by putting a :file:`.pth` file in :file:`{prefix}`. See +section :ref:`inst-search-path` to find out how to modify Python's search path. + +If you want to define an entire installation scheme, you just have to supply all +of the installation directory options. The recommended way to do this is to +supply relative paths; for example, if you want to maintain all Python +module-related files under :file:`python` in your home directory, and you want a +separate directory for each platform that you use your home directory from, you +might define the following installation scheme:: + + python setup.py install --home=~ \ + --install-purelib=python/lib \ + --install-platlib=python/lib.$PLAT \ + --install-scripts=python/scripts + --install-data=python/data + +or, equivalently, :: + + python setup.py install --home=~/python \ + --install-purelib=lib \ + --install-platlib='lib.$PLAT' \ + --install-scripts=scripts + --install-data=data + +``$PLAT`` is not (necessarily) an environment variable---it will be expanded by +the Distutils as it parses your command line options, just as it does when +parsing your configuration file(s). + +Obviously, specifying the entire installation scheme every time you install a +new module distribution would be very tedious. Thus, you can put these options +into your Distutils config file (see section :ref:`inst-config-files`):: + + [install] + install-base=$HOME + install-purelib=python/lib + install-platlib=python/lib.$PLAT + install-scripts=python/scripts + install-data=python/data + +or, equivalently, :: + + [install] + install-base=$HOME/python + install-purelib=lib + install-platlib=lib.$PLAT + install-scripts=scripts + install-data=data + +Note that these two are *not* equivalent if you supply a different installation +base directory when you run the setup script. For example, :: + + python setup.py install --install-base=/tmp + +would install pure modules to :file:`{/tmp/python/lib}` in the first case, and +to :file:`{/tmp/lib}` in the second case. (For the second case, you probably +want to supply an installation base of :file:`/tmp/python`.) + +You probably noticed the use of ``$HOME`` and ``$PLAT`` in the sample +configuration file input. These are Distutils configuration variables, which +bear a strong resemblance to environment variables. In fact, you can use +environment variables in config files on platforms that have such a notion but +the Distutils additionally define a few extra variables that may not be in your +environment, such as ``$PLAT``. (And of course, on systems that don't have +environment variables, such as Mac OS 9, the configuration variables supplied by +the Distutils are the only ones you can use.) See section :ref:`inst-config-files` +for details. + +.. XXX need some Windows examples---when would custom installation schemes be + needed on those platforms? + + +.. XXX I'm not sure where this section should go. + +.. _inst-search-path: + +Modifying Python's Search Path +------------------------------ + +When the Python interpreter executes an :keyword:`import` statement, it searches +for both Python code and extension modules along a search path. A default value +for the path is configured into the Python binary when the interpreter is built. +You can determine the path by importing the :mod:`sys` module and printing the +value of ``sys.path``. :: + + $ python + Python 2.2 (#11, Oct 3 2002, 13:31:27) + [GCC 2.96 20000731 (Red Hat Linux 7.3 2.96-112)] on linux2 + Type "help", "copyright", "credits" or "license" for more information. + >>> import sys + >>> sys.path + ['', '/usr/local/lib/python2.3', '/usr/local/lib/python2.3/plat-linux2', + '/usr/local/lib/python2.3/lib-tk', '/usr/local/lib/python2.3/lib-dynload', + '/usr/local/lib/python2.3/site-packages'] + >>> + +The null string in ``sys.path`` represents the current working directory. + +The expected convention for locally installed packages is to put them in the +:file:`{...}/site-packages/` directory, but you may want to install Python +modules into some arbitrary directory. For example, your site may have a +convention of keeping all software related to the web server under :file:`/www`. +Add-on Python modules might then belong in :file:`/www/python`, and in order to +import them, this directory must be added to ``sys.path``. There are several +different ways to add the directory. + +The most convenient way is to add a path configuration file to a directory +that's already on Python's path, usually to the :file:`.../site-packages/` +directory. Path configuration files have an extension of :file:`.pth`, and each +line must contain a single path that will be appended to ``sys.path``. (Because +the new paths are appended to ``sys.path``, modules in the added directories +will not override standard modules. This means you can't use this mechanism for +installing fixed versions of standard modules.) + +Paths can be absolute or relative, in which case they're relative to the +directory containing the :file:`.pth` file. See the documentation of +the :mod:`site` module for more information. + +A slightly less convenient way is to edit the :file:`site.py` file in Python's +standard library, and modify ``sys.path``. :file:`site.py` is automatically +imported when the Python interpreter is executed, unless the :option:`-S` switch +is supplied to suppress this behaviour. So you could simply edit +:file:`site.py` and add two lines to it:: + + import sys + sys.path.append('/www/python/') + +However, if you reinstall the same major version of Python (perhaps when +upgrading from 2.2 to 2.2.2, for example) :file:`site.py` will be overwritten by +the stock version. You'd have to remember that it was modified and save a copy +before doing the installation. + +There are two environment variables that can modify ``sys.path``. +:envvar:`PYTHONHOME` sets an alternate value for the prefix of the Python +installation. For example, if :envvar:`PYTHONHOME` is set to ``/www/python``, +the search path will be set to ``['', '/www/python/lib/pythonX.Y/', +'/www/python/lib/pythonX.Y/plat-linux2', ...]``. + +The :envvar:`PYTHONPATH` variable can be set to a list of paths that will be +added to the beginning of ``sys.path``. For example, if :envvar:`PYTHONPATH` is +set to ``/www/python:/opt/py``, the search path will begin with +``['/www/python', '/opt/py']``. (Note that directories must exist in order to +be added to ``sys.path``; the :mod:`site` module removes paths that don't +exist.) + +Finally, ``sys.path`` is just a regular Python list, so any Python application +can modify it by adding or removing entries. + + +.. _inst-config-files: + +Distutils Configuration Files +============================= + +As mentioned above, you can use Distutils configuration files to record personal +or site preferences for any Distutils options. That is, any option to any +command can be stored in one of two or three (depending on your platform) +configuration files, which will be consulted before the command-line is parsed. +This means that configuration files will override default values, and the +command-line will in turn override configuration files. Furthermore, if +multiple configuration files apply, values from "earlier" files are overridden +by "later" files. + + +.. _inst-config-filenames: + +Location and names of config files +---------------------------------- + +The names and locations of the configuration files vary slightly across +platforms. On Unix and Mac OS X, the three configuration files (in the order +they are processed) are: + ++--------------+----------------------------------------------------------+-------+ +| Type of file | Location and filename | Notes | ++==============+==========================================================+=======+ +| system | :file:`{prefix}/lib/python{ver}/distutils/distutils.cfg` | \(1) | ++--------------+----------------------------------------------------------+-------+ +| personal | :file:`$HOME/.pydistutils.cfg` | \(2) | ++--------------+----------------------------------------------------------+-------+ +| local | :file:`setup.cfg` | \(3) | ++--------------+----------------------------------------------------------+-------+ + +And on Windows, the configuration files are: + ++--------------+-------------------------------------------------+-------+ +| Type of file | Location and filename | Notes | ++==============+=================================================+=======+ +| system | :file:`{prefix}\\Lib\\distutils\\distutils.cfg` | \(4) | ++--------------+-------------------------------------------------+-------+ +| personal | :file:`%HOME%\\pydistutils.cfg` | \(5) | ++--------------+-------------------------------------------------+-------+ +| local | :file:`setup.cfg` | \(3) | ++--------------+-------------------------------------------------+-------+ + +On all platforms, the "personal" file can be temporarily disabled by +passing the `--no-user-cfg` option. + +Notes: + +(1) + Strictly speaking, the system-wide configuration file lives in the directory + where the Distutils are installed; under Python 1.6 and later on Unix, this is + as shown. For Python 1.5.2, the Distutils will normally be installed to + :file:`{prefix}/lib/python1.5/site-packages/distutils`, so the system + configuration file should be put there under Python 1.5.2. + +(2) + On Unix, if the :envvar:`HOME` environment variable is not defined, the user's + home directory will be determined with the :func:`getpwuid` function from the + standard :mod:`pwd` module. This is done by the :func:`os.path.expanduser` + function used by Distutils. + +(3) + I.e., in the current directory (usually the location of the setup script). + +(4) + (See also note (1).) Under Python 1.6 and later, Python's default "installation + prefix" is :file:`C:\\Python`, so the system configuration file is normally + :file:`C:\\Python\\Lib\\distutils\\distutils.cfg`. Under Python 1.5.2, the + default prefix was :file:`C:\\Program Files\\Python`, and the Distutils were not + part of the standard library---so the system configuration file would be + :file:`C:\\Program Files\\Python\\distutils\\distutils.cfg` in a standard Python + 1.5.2 installation under Windows. + +(5) + On Windows, if the :envvar:`HOME` environment variable is not defined, + :envvar:`USERPROFILE` then :envvar:`HOMEDRIVE` and :envvar:`HOMEPATH` will + be tried. This is done by the :func:`os.path.expanduser` function used + by Distutils. + + +.. _inst-config-syntax: + +Syntax of config files +---------------------- + +The Distutils configuration files all have the same syntax. The config files +are grouped into sections. There is one section for each Distutils command, +plus a ``global`` section for global options that affect every command. Each +section consists of one option per line, specified as ``option=value``. + +For example, the following is a complete config file that just forces all +commands to run quietly by default:: + + [global] + verbose=0 + +If this is installed as the system config file, it will affect all processing of +any Python module distribution by any user on the current system. If it is +installed as your personal config file (on systems that support them), it will +affect only module distributions processed by you. And if it is used as the +:file:`setup.cfg` for a particular module distribution, it affects only that +distribution. + +You could override the default "build base" directory and make the +:command:`build\*` commands always forcibly rebuild all files with the +following:: + + [build] + build-base=blib + force=1 + +which corresponds to the command-line arguments :: + + python setup.py build --build-base=blib --force + +except that including the :command:`build` command on the command-line means +that command will be run. Including a particular command in config files has no +such implication; it only means that if the command is run, the options in the +config file will apply. (Or if other commands that derive values from it are +run, they will use the values in the config file.) + +You can find out the complete list of options for any command using the +:option:`--help` option, e.g.:: + + python setup.py build --help + +and you can find out the complete list of global options by using +:option:`--help` without a command:: + + python setup.py --help + +See also the "Reference" section of the "Distributing Python Modules" manual. + + +.. _inst-building-ext: + +Building Extensions: Tips and Tricks +==================================== + +Whenever possible, the Distutils try to use the configuration information made +available by the Python interpreter used to run the :file:`setup.py` script. +For example, the same compiler and linker flags used to compile Python will also +be used for compiling extensions. Usually this will work well, but in +complicated situations this might be inappropriate. This section discusses how +to override the usual Distutils behaviour. + + +.. _inst-tweak-flags: + +Tweaking compiler/linker flags +------------------------------ + +Compiling a Python extension written in C or C++ will sometimes require +specifying custom flags for the compiler and linker in order to use a particular +library or produce a special kind of object code. This is especially true if the +extension hasn't been tested on your platform, or if you're trying to +cross-compile Python. + +In the most general case, the extension author might have foreseen that +compiling the extensions would be complicated, and provided a :file:`Setup` file +for you to edit. This will likely only be done if the module distribution +contains many separate extension modules, or if they often require elaborate +sets of compiler flags in order to work. + +A :file:`Setup` file, if present, is parsed in order to get a list of extensions +to build. Each line in a :file:`Setup` describes a single module. Lines have +the following structure:: + + module ... [sourcefile ...] [cpparg ...] [library ...] + + +Let's examine each of the fields in turn. + +* *module* is the name of the extension module to be built, and should be a + valid Python identifier. You can't just change this in order to rename a module + (edits to the source code would also be needed), so this should be left alone. + +* *sourcefile* is anything that's likely to be a source code file, at least + judging by the filename. Filenames ending in :file:`.c` are assumed to be + written in C, filenames ending in :file:`.C`, :file:`.cc`, and :file:`.c++` are + assumed to be C++, and filenames ending in :file:`.m` or :file:`.mm` are assumed + to be in Objective C. + +* *cpparg* is an argument for the C preprocessor, and is anything starting with + :option:`-I`, :option:`-D`, :option:`-U` or :option:`-C`. + +* *library* is anything ending in :file:`.a` or beginning with :option:`-l` or + :option:`-L`. + +If a particular platform requires a special library on your platform, you can +add it by editing the :file:`Setup` file and running ``python setup.py build``. +For example, if the module defined by the line :: + + foo foomodule.c + +must be linked with the math library :file:`libm.a` on your platform, simply add +:option:`-lm` to the line:: + + foo foomodule.c -lm + +Arbitrary switches intended for the compiler or the linker can be supplied with +the :option:`-Xcompiler` *arg* and :option:`-Xlinker` *arg* options:: + + foo foomodule.c -Xcompiler -o32 -Xlinker -shared -lm + +The next option after :option:`-Xcompiler` and :option:`-Xlinker` will be +appended to the proper command line, so in the above example the compiler will +be passed the :option:`-o32` option, and the linker will be passed +:option:`-shared`. If a compiler option requires an argument, you'll have to +supply multiple :option:`-Xcompiler` options; for example, to pass ``-x c++`` +the :file:`Setup` file would have to contain ``-Xcompiler -x -Xcompiler c++``. + +Compiler flags can also be supplied through setting the :envvar:`CFLAGS` +environment variable. If set, the contents of :envvar:`CFLAGS` will be added to +the compiler flags specified in the :file:`Setup` file. + + +.. _inst-non-ms-compilers: + +Using non-Microsoft compilers on Windows +---------------------------------------- + +.. sectionauthor:: Rene Liebscher + + + +Borland/CodeGear C++ +^^^^^^^^^^^^^^^^^^^^ + +This subsection describes the necessary steps to use Distutils with the Borland +C++ compiler version 5.5. First you have to know that Borland's object file +format (OMF) is different from the format used by the Python version you can +download from the Python or ActiveState Web site. (Python is built with +Microsoft Visual C++, which uses COFF as the object file format.) For this +reason you have to convert Python's library :file:`python25.lib` into the +Borland format. You can do this as follows: + +.. Should we mention that users have to create cfg-files for the compiler? +.. see also http://community.borland.com/article/0,1410,21205,00.html + +:: + + coff2omf python25.lib python25_bcpp.lib + +The :file:`coff2omf` program comes with the Borland compiler. The file +:file:`python25.lib` is in the :file:`Libs` directory of your Python +installation. If your extension uses other libraries (zlib, ...) you have to +convert them too. + +The converted files have to reside in the same directories as the normal +libraries. + +How does Distutils manage to use these libraries with their changed names? If +the extension needs a library (eg. :file:`foo`) Distutils checks first if it +finds a library with suffix :file:`_bcpp` (eg. :file:`foo_bcpp.lib`) and then +uses this library. In the case it doesn't find such a special library it uses +the default name (:file:`foo.lib`.) [#]_ + +To let Distutils compile your extension with Borland C++ you now have to type:: + + python setup.py build --compiler=bcpp + +If you want to use the Borland C++ compiler as the default, you could specify +this in your personal or system-wide configuration file for Distutils (see +section :ref:`inst-config-files`.) .. seealso:: - :ref:`packaging-index` - The manual for developers of Python projects who want to package and - distribute them. This describes how to use :mod:`packaging` to make - projects easily found and added to an existing Python installation. + `C++Builder Compiler `_ + Information about the free C++ compiler from Borland, including links to the + download pages. - :mod:`packaging` - A library reference for developers of packaging tools wanting to use - standalone building blocks like :mod:`~packaging.version` or - :mod:`~packaging.metadata`, or extend Packaging itself. + `Creating Python Extensions Using Borland's Free Compiler `_ + Document describing how to use Borland's free command-line C++ compiler to build + Python. + + +GNU C / Cygwin / MinGW +^^^^^^^^^^^^^^^^^^^^^^ + +This section describes the necessary steps to use Distutils with the GNU C/C++ +compilers in their Cygwin and MinGW distributions. [#]_ For a Python interpreter +that was built with Cygwin, everything should work without any of these +following steps. + +Not all extensions can be built with MinGW or Cygwin, but many can. Extensions +most likely to not work are those that use C++ or depend on Microsoft Visual C +extensions. + +To let Distutils compile your extension with Cygwin you have to type:: + + python setup.py build --compiler=cygwin + +and for Cygwin in no-cygwin mode [#]_ or for MinGW type:: + + python setup.py build --compiler=mingw32 + +If you want to use any of these options/compilers as default, you should +consider writing it in your personal or system-wide configuration file for +Distutils (see section :ref:`inst-config-files`.) + +Older Versions of Python and MinGW +"""""""""""""""""""""""""""""""""" +The following instructions only apply if you're using a version of Python +inferior to 2.4.1 with a MinGW inferior to 3.0.0 (with +binutils-2.13.90-20030111-1). + +These compilers require some special libraries. This task is more complex than +for Borland's C++, because there is no program to convert the library. First +you have to create a list of symbols which the Python DLL exports. (You can find +a good program for this task at +http://www.emmestech.com/software/pexports-0.43/download_pexports.html). + +.. I don't understand what the next line means. --amk +.. (inclusive the references on data structures.) + +:: + + pexports python25.dll >python25.def + +The location of an installed :file:`python25.dll` will depend on the +installation options and the version and language of Windows. In a "just for +me" installation, it will appear in the root of the installation directory. In +a shared installation, it will be located in the system directory. + +Then you can create from these information an import library for gcc. :: + + /cygwin/bin/dlltool --dllname python25.dll --def python25.def --output-lib libpython25.a + +The resulting library has to be placed in the same directory as +:file:`python25.lib`. (Should be the :file:`libs` directory under your Python +installation directory.) + +If your extension uses other libraries (zlib,...) you might have to convert +them too. The converted files have to reside in the same directories as the +normal libraries do. + + +.. seealso:: + + `Building Python modules on MS Windows platform with MinGW `_ + Information about building the required libraries for the MinGW environment. + + +.. rubric:: Footnotes + +.. [#] This also means you could replace all existing COFF-libraries with OMF-libraries + of the same name. + +.. [#] Check http://sources.redhat.com/cygwin/ and http://www.mingw.org/ for more + information + +.. [#] Then you have no POSIX emulation available, but you also don't need + :file:`cygwin1.dll`. diff -r 2e49722c7263 -r 6944bdf1289a Doc/install/install.rst --- a/Doc/install/install.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1029 +0,0 @@ -.. highlightlang:: none - -==================================== -Installing Python projects: overwiew -==================================== - -.. _packaging_packaging-intro: - -Introduction -============ - -Although Python's extensive standard library covers many programming needs, -there often comes a time when you need to add new functionality to your Python -installation in the form of third-party modules. This might be necessary to -support your own programming, or to support an application that you want to use -and that happens to be written in Python. - -In the past, there was little support for adding third-party modules to an -existing Python installation. With the introduction of the Python Distribution -Utilities (Distutils for short) in Python 2.0, this changed. However, not all -problems were solved; end-users had to rely on ``easy_install`` or -``pip`` to download third-party modules from PyPI, uninstall distributions or do -other maintenance operations. Packaging is a more complete replacement for -Distutils, in the standard library, with a backport named Distutils2 available -for older Python versions. - -This document is aimed primarily at people who need to install third-party -Python modules: end-users and system administrators who just need to get some -Python application running, and existing Python programmers who want to add -new goodies to their toolbox. You don't need to know Python to read this -document; there will be some brief forays into using Python's interactive mode -to explore your installation, but that's it. If you're looking for information -on how to distribute your own Python modules so that others may use them, see -the :ref:`packaging-index` manual. - - -.. _packaging-trivial-install: - -Best case: trivial installation -------------------------------- - -In the best case, someone will have prepared a special version of the module -distribution you want to install that is targeted specifically at your platform -and can be installed just like any other software on your platform. For example, -the module's developer might make an executable installer available for Windows -users, an RPM package for users of RPM-based Linux systems (Red Hat, SuSE, -Mandrake, and many others), a Debian package for users of Debian and derivative -systems, and so forth. - -In that case, you would use the standard system tools to download and install -the specific installer for your platform and its dependencies. - -Of course, things will not always be that easy. You might be interested in a -module whose distribution doesn't have an easy-to-use installer for your -platform. In that case, you'll have to start with the source distribution -released by the module's author/maintainer. Installing from a source -distribution is not too hard, as long as the modules are packaged in the -standard way. The bulk of this document addresses the building and installing -of modules from standard source distributions. - - -.. _packaging-distutils: - -The Python standard: Distutils ------------------------------- - -If you download a source distribution of a module, it will be obvious whether -it was packaged and distributed using Distutils. First, the distribution's name -and version number will be featured prominently in the name of the downloaded -archive, e.g. :file:`foo-1.0.tar.gz` or :file:`widget-0.9.7.zip`. Next, the -archive will unpack into a similarly-named directory: :file:`foo-1.0` or -:file:`widget-0.9.7`. Additionally, the distribution may contain a -:file:`setup.cfg` file and a file named :file:`README.txt` ---or possibly just -:file:`README`--- explaining that building and installing the module -distribution is a simple matter of issuing the following command at your shell's -prompt:: - - python setup.py install - -Third-party projects have extended Distutils to work around its limitations or -add functionality. After some years of near-inactivity in Distutils, a new -maintainer has started to standardize good ideas in PEPs and implement them in a -new, improved version of Distutils, called Distutils2 or Packaging. - - -.. _packaging-new-standard: - -The new standard: Packaging ---------------------------- - -The rules described in the first paragraph above apply to Packaging-based -projects too: a source distribution will have a name like -:file:`widget-0.9.7.zip`. One of the main differences with Distutils is that -distributions no longer have a :file:`setup.py` script; it used to cause a -number of issues. Now there is a unique script installed with Python itself:: - - pysetup install widget-0.9.7.zip - -Running this command is enough to build and install projects (Python modules or -packages, scripts or whole applications), without even having to unpack the -archive. It is also compatible with Distutils-based distributions. - -Unless you have to perform non-standard installations or customize the build -process, you can stop reading this manual ---the above command is everything you -need to get out of it. - -With :program:`pysetup`, you won't even have to manually download a distribution -before installing it; see :ref:`packaging-pysetup`. - - -.. _packaging-standard-install: - -Standard build and install -========================== - -As described in section :ref:`packaging-new-standard`, building and installing -a module distribution using Packaging usually comes down to one simple -command:: - - pysetup run install_dist - -How you actually run this command depends on the platform and the command line -interface it provides: - -* **Unix**: Use a shell prompt. -* **Windows**: Open a command prompt ("DOS console") or use :command:`Powershell`. -* **OS X**: Open a :command:`Terminal`. - - -.. _packaging-platform-variations: - -Platform variations -------------------- - -The setup command is meant to be run from the root directory of the source -distribution, i.e. the top-level subdirectory that the module source -distribution unpacks into. For example, if you've just downloaded a module -source distribution :file:`foo-1.0.tar.gz` onto a Unix system, the normal -steps to follow are these:: - - gunzip -c foo-1.0.tar.gz | tar xf - # unpacks into directory foo-1.0 - cd foo-1.0 - pysetup run install_dist - -On Windows, you'd probably download :file:`foo-1.0.zip`. If you downloaded the -archive file to :file:`C:\\Temp`, then it would unpack into -:file:`C:\\Temp\\foo-1.0`. To actually unpack the archive, you can use either -an archive manipulator with a graphical user interface (such as WinZip or 7-Zip) -or a command-line tool (such as :program:`unzip`, :program:`pkunzip` or, again, -:program:`7z`). Then, open a command prompt window ("DOS box" or -Powershell), and run:: - - cd c:\Temp\foo-1.0 - pysetup run install_dist - - -.. _packaging-splitting-up: - -Splitting the job up --------------------- - -Running ``pysetup run install_dist`` builds and installs all modules in one go. If you -prefer to work incrementally ---especially useful if you want to customize the -build process, or if things are going wrong--- you can use the setup script to -do one thing at a time. This is a valuable tool when different users will perform -separately the build and install steps. For example, you might want to build a -module distribution and hand it off to a system administrator for installation -(or do it yourself, but with super-user or admin privileges). - -For example, to build everything in one step and then install everything -in a second step, you aptly invoke two distinct Packaging commands:: - - pysetup run build - pysetup run install_dist - -If you do this, you will notice that invoking the :command:`install_dist` command -first runs the :command:`build` command, which ---in this case--- quickly -notices it can spare itself the work, since everything in the :file:`build` -directory is up-to-date. - -You may often ignore this ability to divide the process in steps if all you do -is installing modules downloaded from the Internet, but it's very handy for -more advanced tasks. If you find yourself in the need for distributing your own -Python modules and extensions, though, you'll most likely run many individual -Packaging commands. - - -.. _packaging-how-build-works: - -How building works ------------------- - -As implied above, the :command:`build` command is responsible for collecting -and placing the files to be installed into a *build directory*. By default, -this is :file:`build`, under the distribution root. If you're excessively -concerned with speed, or want to keep the source tree pristine, you can specify -a different build directory with the :option:`--build-base` option. For example:: - - pysetup run build --build-base /tmp/pybuild/foo-1.0 - -(Or you could do this permanently with a directive in your system or personal -Packaging configuration file; see section :ref:`packaging-config-files`.) -In the usual case, however, all this is unnecessary. - -The build tree's default layout looks like so:: - - --- build/ --- lib/ - or - --- build/ --- lib./ - temp./ - -where ```` expands to a brief description of the current OS/hardware -platform and Python version. The first form, with just a :file:`lib` directory, -is used for pure module distributions (module distributions that -include only pure Python modules). If a module distribution contains any -extensions (modules written in C/C++), then the second form, with two ```` -directories, is used. In that case, the :file:`temp.{plat}` directory holds -temporary files generated during the compile/link process which are not intended -to be installed. In either case, the :file:`lib` (or :file:`lib.{plat}`) directory -contains all Python modules (pure Python and extensions) to be installed. - -In the future, more directories will be added to handle Python scripts, -documentation, binary executables, and whatever else is required to install -Python modules and applications. - - -.. _packaging-how-install-works: - -How installation works ----------------------- - -After the :command:`build` command is run (whether explicitly or by the -:command:`install_dist` command on your behalf), the work of the :command:`install_dist` -command is relatively simple: all it has to do is copy the contents of -:file:`build/lib` (or :file:`build/lib.{plat}`) to the installation directory -of your choice. - -If you don't choose an installation directory ---i.e., if you just run -``pysetup run install_dist``\ --- then the :command:`install_dist` command -installs to the standard location for third-party Python modules. This location -varies by platform and depending on how you built/installed Python itself. On -Unix (and Mac OS X, which is also Unix-based), it also depends on whether the -module distribution being installed is pure Python or contains extensions -("non-pure"): - -+-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ -| Platform | Standard installation location | Default value | Notes | -+=================+=====================================================+==================================================+=======+ -| Unix (pure) | :file:`{prefix}/lib/python{X.Y}/site-packages` | :file:`/usr/local/lib/python{X.Y}/site-packages` | \(1) | -+-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ -| Unix (non-pure) | :file:`{exec-prefix}/lib/python{X.Y}/site-packages` | :file:`/usr/local/lib/python{X.Y}/site-packages` | \(1) | -+-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ -| Windows | :file:`{prefix}\\Lib\\site-packages` | :file:`C:\\Python{XY}\\Lib\\site-packages` | \(2) | -+-----------------+-----------------------------------------------------+--------------------------------------------------+-------+ - -Notes: - -(1) - Most Linux distributions include Python as a standard part of the system, so - :file:`{prefix}` and :file:`{exec-prefix}` are usually both :file:`/usr` on - Linux. If you build Python yourself on Linux (or any Unix-like system), the - default :file:`{prefix}` and :file:`{exec-prefix}` are :file:`/usr/local`. - -(2) - The default installation directory on Windows was :file:`C:\\Program - Files\\Python` under Python 1.6a1, 1.5.2, and earlier. - -:file:`{prefix}` and :file:`{exec-prefix}` stand for the directories that Python -is installed to, and where it finds its libraries at run-time. They are always -the same under Windows, and very often the same under Unix and Mac OS X. You -can find out what your Python installation uses for :file:`{prefix}` and -:file:`{exec-prefix}` by running Python in interactive mode and typing a few -simple commands. - -.. TODO link to Doc/using instead of duplicating - -To start the interactive Python interpreter, you need to follow a slightly -different recipe for each platform. Under Unix, just type :command:`python` at -the shell prompt. Under Windows (assuming the Python executable is on your -:envvar:`PATH`, which is the usual case), you can choose :menuselection:`Start --> Run`, -type ``python`` and press ``enter``. Alternatively, you can simply execute -:command:`python` at a command prompt ("DOS console" or Powershell). - -Once the interpreter is started, you type Python code at the prompt. For -example, on my Linux system, I type the three Python statements shown below, -and get the output as shown, to find out my :file:`{prefix}` and :file:`{exec-prefix}`:: - - Python 3.3 (r32:88445, Apr 2 2011, 10:43:54) - Type "help", "copyright", "credits" or "license" for more information. - >>> import sys - >>> sys.prefix - '/usr' - >>> sys.exec_prefix - '/usr' - -If you don't want to install modules to the standard location, or if you don't -have permission to write there, then you need to read about alternate -installations in section :ref:`packaging-alt-install`. If you want to customize your -installation directories more heavily, see section :ref:`packaging-custom-install`. - - -.. _packaging-alt-install: - -Alternate installation -====================== - -Often, it is necessary or desirable to install modules to a location other than -the standard location for third-party Python modules. For example, on a Unix -system you might not have permission to write to the standard third-party module -directory. Or you might wish to try out a module before making it a standard -part of your local Python installation. This is especially true when upgrading -a distribution already present: you want to make sure your existing base of -scripts still works with the new version before actually upgrading. - -The Packaging :command:`install_dist` command is designed to make installing module -distributions to an alternate location simple and painless. The basic idea is -that you supply a base directory for the installation, and the -:command:`install_dist` command picks a set of directories (called an *installation -scheme*) under this base directory in which to install files. The details -differ across platforms, so read whichever of the following sections applies to -you. - - -.. _packaging-alt-install-prefix: - -Alternate installation: the home scheme ---------------------------------------- - -The idea behind the "home scheme" is that you build and maintain a personal -stash of Python modules. This scheme's name is derived from the concept of a -"home" directory on Unix, since it's not unusual for a Unix user to make their -home directory have a layout similar to :file:`/usr/` or :file:`/usr/local/`. -In spite of its name's origin, this scheme can be used by anyone, regardless -of the operating system. - -Installing a new module distribution in this way is as simple as :: - - pysetup run install_dist --home - -where you can supply any directory you like for the :option:`--home` option. On -Unix, lazy typists can just type a tilde (``~``); the :command:`install_dist` command -will expand this to your home directory:: - - pysetup run install_dist --home ~ - -The :option:`--home` option defines the base directory for the installation. -Under it, files are installed to the following directories: - -+------------------------------+---------------------------+-----------------------------+ -| Type of file | Installation Directory | Override option | -+==============================+===========================+=============================+ -| pure module distribution | :file:`{home}/lib/python` | :option:`--install-purelib` | -+------------------------------+---------------------------+-----------------------------+ -| non-pure module distribution | :file:`{home}/lib/python` | :option:`--install-platlib` | -+------------------------------+---------------------------+-----------------------------+ -| scripts | :file:`{home}/bin` | :option:`--install-scripts` | -+------------------------------+---------------------------+-----------------------------+ -| data | :file:`{home}/share` | :option:`--install-data` | -+------------------------------+---------------------------+-----------------------------+ - - -.. _packaging-alt-install-home: - -Alternate installation: Unix (the prefix scheme) ------------------------------------------------- - -The "prefix scheme" is useful when you wish to use one Python installation to -run the build command, but install modules into the third-party module directory -of a different Python installation (or something that looks like a different -Python installation). If this sounds a trifle unusual, it is ---that's why the -"home scheme" comes first. However, there are at least two known cases where the -prefix scheme will be useful. - -First, consider that many Linux distributions put Python in :file:`/usr`, rather -than the more traditional :file:`/usr/local`. This is entirely appropriate, -since in those cases Python is part of "the system" rather than a local add-on. -However, if you are installing Python modules from source, you probably want -them to go in :file:`/usr/local/lib/python2.{X}` rather than -:file:`/usr/lib/python2.{X}`. This can be done with :: - - pysetup run install_dist --prefix /usr/local - -Another possibility is a network filesystem where the name used to write to a -remote directory is different from the name used to read it: for example, the -Python interpreter accessed as :file:`/usr/local/bin/python` might search for -modules in :file:`/usr/local/lib/python2.{X}`, but those modules would have to -be installed to, say, :file:`/mnt/{@server}/export/lib/python2.{X}`. This could -be done with :: - - pysetup run install_dist --prefix=/mnt/@server/export - -In either case, the :option:`--prefix` option defines the installation base, and -the :option:`--exec-prefix` option defines the platform-specific installation -base, which is used for platform-specific files. (Currently, this just means -non-pure module distributions, but could be expanded to C libraries, binary -executables, etc.) If :option:`--exec-prefix` is not supplied, it defaults to -:option:`--prefix`. Files are installed as follows: - -+------------------------------+-----------------------------------------------------+-----------------------------+ -| Type of file | Installation Directory | Override option | -+==============================+=====================================================+=============================+ -| pure module distribution | :file:`{prefix}/lib/python{X.Y}/site-packages` | :option:`--install-purelib` | -+------------------------------+-----------------------------------------------------+-----------------------------+ -| non-pure module distribution | :file:`{exec-prefix}/lib/python{X.Y}/site-packages` | :option:`--install-platlib` | -+------------------------------+-----------------------------------------------------+-----------------------------+ -| scripts | :file:`{prefix}/bin` | :option:`--install-scripts` | -+------------------------------+-----------------------------------------------------+-----------------------------+ -| data | :file:`{prefix}/share` | :option:`--install-data` | -+------------------------------+-----------------------------------------------------+-----------------------------+ - -There is no requirement that :option:`--prefix` or :option:`--exec-prefix` -actually point to an alternate Python installation; if the directories listed -above do not already exist, they are created at installation time. - -Incidentally, the real reason the prefix scheme is important is simply that a -standard Unix installation uses the prefix scheme, but with :option:`--prefix` -and :option:`--exec-prefix` supplied by Python itself as ``sys.prefix`` and -``sys.exec_prefix``. Thus, you might think you'll never use the prefix scheme, -but every time you run ``pysetup run install_dist`` without any other -options, you're using it. - -Note that installing extensions to an alternate Python installation doesn't have -anything to do with how those extensions are built: in particular, extensions -will be compiled using the Python header files (:file:`Python.h` and friends) -installed with the Python interpreter used to run the build command. It is -therefore your responsibility to ensure compatibility between the interpreter -intended to run extensions installed in this way and the interpreter used to -build these same extensions. To avoid problems, it is best to make sure that -the two interpreters are the same version of Python (possibly different builds, -or possibly copies of the same build). (Of course, if your :option:`--prefix` -and :option:`--exec-prefix` don't even point to an alternate Python installation, -this is immaterial.) - - -.. _packaging-alt-install-windows: - -Alternate installation: Windows (the prefix scheme) ---------------------------------------------------- - -Windows has a different and vaguer notion of home directories than Unix, and -since its standard Python installation is simpler, the :option:`--prefix` option -has traditionally been used to install additional packages to arbitrary -locations. :: - - pysetup run install_dist --prefix "\Temp\Python" - -to install modules to the :file:`\\Temp\\Python` directory on the current drive. - -The installation base is defined by the :option:`--prefix` option; the -:option:`--exec-prefix` option is unsupported under Windows. Files are -installed as follows: - -+------------------------------+---------------------------+-----------------------------+ -| Type of file | Installation Directory | Override option | -+==============================+===========================+=============================+ -| pure module distribution | :file:`{prefix}` | :option:`--install-purelib` | -+------------------------------+---------------------------+-----------------------------+ -| non-pure module distribution | :file:`{prefix}` | :option:`--install-platlib` | -+------------------------------+---------------------------+-----------------------------+ -| scripts | :file:`{prefix}\\Scripts` | :option:`--install-scripts` | -+------------------------------+---------------------------+-----------------------------+ -| data | :file:`{prefix}\\Data` | :option:`--install-data` | -+------------------------------+---------------------------+-----------------------------+ - - -.. _packaging-custom-install: - -Custom installation -=================== - -Sometimes, the alternate installation schemes described in section -:ref:`packaging-alt-install` just don't do what you want. You might want to tweak -just one or two directories while keeping everything under the same base -directory, or you might want to completely redefine the installation scheme. -In either case, you're creating a *custom installation scheme*. - -You probably noticed the column of "override options" in the tables describing -the alternate installation schemes above. Those options are how you define a -custom installation scheme. These override options can be relative, absolute, -or explicitly defined in terms of one of the installation base directories. -(There are two installation base directories, and they are normally the same ----they only differ when you use the Unix "prefix scheme" and supply different -:option:`--prefix` and :option:`--exec-prefix` options.) - -For example, say you're installing a module distribution to your home directory -under Unix, but you want scripts to go in :file:`~/scripts` rather than -:file:`~/bin`. As you might expect, you can override this directory with the -:option:`--install-scripts` option and, in this case, it makes most sense to supply -a relative path, which will be interpreted relative to the installation base -directory (in our example, your home directory):: - - pysetup run install_dist --home ~ --install-scripts scripts - -Another Unix example: suppose your Python installation was built and installed -with a prefix of :file:`/usr/local/python`. Thus, in a standard installation, -scripts will wind up in :file:`/usr/local/python/bin`. If you want them in -:file:`/usr/local/bin` instead, you would supply this absolute directory for -the :option:`--install-scripts` option:: - - pysetup run install_dist --install-scripts /usr/local/bin - -This command performs an installation using the "prefix scheme", where the -prefix is whatever your Python interpreter was installed with ---in this case, -:file:`/usr/local/python`. - -If you maintain Python on Windows, you might want third-party modules to live in -a subdirectory of :file:`{prefix}`, rather than right in :file:`{prefix}` -itself. This is almost as easy as customizing the script installation directory ----you just have to remember that there are two types of modules to worry about, -pure modules and non-pure modules (i.e., modules from a non-pure distribution). -For example:: - - pysetup run install_dist --install-purelib Site --install-platlib Site - -.. XXX Nothing is installed right under prefix in windows, is it?? - -The specified installation directories are relative to :file:`{prefix}`. Of -course, you also have to ensure that these directories are in Python's module -search path, such as by putting a :file:`.pth` file in :file:`{prefix}`. See -section :ref:`packaging-search-path` to find out how to modify Python's search path. - -If you want to define an entire installation scheme, you just have to supply all -of the installation directory options. Using relative paths is recommended here. -For example, if you want to maintain all Python module-related files under -:file:`python` in your home directory, and you want a separate directory for -each platform that you use your home directory from, you might define the -following installation scheme:: - - pysetup run install_dist --home ~ \ - --install-purelib python/lib \ - --install-platlib python/'lib.$PLAT' \ - --install-scripts python/scripts \ - --install-data python/data - -or, equivalently, :: - - pysetup run install_dist --home ~/python \ - --install-purelib lib \ - --install-platlib 'lib.$PLAT' \ - --install-scripts scripts \ - --install-data data - -``$PLAT`` doesn't need to be defined as an environment variable ---it will also -be expanded by Packaging as it parses your command line options, just as it -does when parsing your configuration file(s). (More on that later.) - -Obviously, specifying the entire installation scheme every time you install a -new module distribution would be very tedious. To spare you all that work, you -can store it in a Packaging configuration file instead (see section -:ref:`packaging-config-files`), like so:: - - [install_dist] - install-base = $HOME - install-purelib = python/lib - install-platlib = python/lib.$PLAT - install-scripts = python/scripts - install-data = python/data - -or, equivalently, :: - - [install_dist] - install-base = $HOME/python - install-purelib = lib - install-platlib = lib.$PLAT - install-scripts = scripts - install-data = data - -Note that these two are *not* equivalent if you override their installation -base directory when running the setup script. For example, :: - - pysetup run install_dist --install-base /tmp - -would install pure modules to :file:`/tmp/python/lib` in the first case, and -to :file:`/tmp/lib` in the second case. (For the second case, you'd probably -want to supply an installation base of :file:`/tmp/python`.) - -You may have noticed the use of ``$HOME`` and ``$PLAT`` in the sample -configuration file. These are Packaging configuration variables, which -bear a strong resemblance to environment variables. In fact, you can use -environment variables in configuration files on platforms that have such a notion, but -Packaging additionally defines a few extra variables that may not be in your -environment, such as ``$PLAT``. Of course, on systems that don't have -environment variables, such as Mac OS 9, the configuration variables supplied by -the Packaging are the only ones you can use. See section :ref:`packaging-config-files` -for details. - -.. XXX which vars win out eventually in case of clash env or Packaging? - -.. XXX need some Windows examples---when would custom installation schemes be - needed on those platforms? - - -.. XXX Move this section to Doc/using - -.. _packaging-search-path: - -Modifying Python's search path ------------------------------- - -When the Python interpreter executes an :keyword:`import` statement, it searches -for both Python code and extension modules along a search path. A default value -for this path is configured into the Python binary when the interpreter is built. -You can obtain the search path by importing the :mod:`sys` module and printing -the value of ``sys.path``. :: - - $ python - Python 2.2 (#11, Oct 3 2002, 13:31:27) - [GCC 2.96 20000731 (Red Hat Linux 7.3 2.96-112)] on linux2 - Type "help", "copyright", "credits" or "license" for more information. - >>> import sys - >>> sys.path - ['', '/usr/local/lib/python2.3', '/usr/local/lib/python2.3/plat-linux2', - '/usr/local/lib/python2.3/lib-tk', '/usr/local/lib/python2.3/lib-dynload', - '/usr/local/lib/python2.3/site-packages'] - >>> - -The null string in ``sys.path`` represents the current working directory. - -The expected convention for locally installed packages is to put them in the -:file:`{...}/site-packages/` directory, but you may want to choose a different -location for some reason. For example, if your site kept by convention all web -server-related software under :file:`/www`. Add-on Python modules might then -belong in :file:`/www/python`, and in order to import them, this directory would -have to be added to ``sys.path``. There are several ways to solve this problem. - -The most convenient way is to add a path configuration file to a directory -that's already on Python's path, usually to the :file:`.../site-packages/` -directory. Path configuration files have an extension of :file:`.pth`, and each -line must contain a single path that will be appended to ``sys.path``. (Because -the new paths are appended to ``sys.path``, modules in the added directories -will not override standard modules. This means you can't use this mechanism for -installing fixed versions of standard modules.) - -Paths can be absolute or relative, in which case they're relative to the -directory containing the :file:`.pth` file. See the documentation of -the :mod:`site` module for more information. - -A slightly less convenient way is to edit the :file:`site.py` file in Python's -standard library, and modify ``sys.path``. :file:`site.py` is automatically -imported when the Python interpreter is executed, unless the :option:`-S` switch -is supplied to suppress this behaviour. So you could simply edit -:file:`site.py` and add two lines to it:: - - import sys - sys.path.append('/www/python/') - -However, if you reinstall the same major version of Python (perhaps when -upgrading from 3.3 to 3.3.1, for example) :file:`site.py` will be overwritten by -the stock version. You'd have to remember that it was modified and save a copy -before doing the installation. - -Alternatively, there are two environment variables that can modify ``sys.path``. -:envvar:`PYTHONHOME` sets an alternate value for the prefix of the Python -installation. For example, if :envvar:`PYTHONHOME` is set to ``/www/python``, -the search path will be set to ``['', '/www/python/lib/pythonX.Y/', -'/www/python/lib/pythonX.Y/plat-linux2', ...]``. - -The :envvar:`PYTHONPATH` variable can be set to a list of paths that will be -added to the beginning of ``sys.path``. For example, if :envvar:`PYTHONPATH` is -set to ``/www/python:/opt/py``, the search path will begin with -``['/www/python', '/opt/py']``. (Note that directories must exist in order to -be added to ``sys.path``; the :mod:`site` module removes non-existent paths.) - -Finally, ``sys.path`` is just a regular Python list, so any Python application -can modify it by adding or removing entries. - - -.. _packaging-config-files: - -Configuration files for Packaging -================================= - -As mentioned above, you can use configuration files to store personal or site -preferences for any option supported by any Packaging command. Depending on your -platform, you can use one of two or three possible configuration files. These -files will be read before parsing the command-line, so they take precedence over -default values. In turn, the command-line will override configuration files. -Lastly, if there are multiple configuration files, values from files read -earlier will be overridden by values from files read later. - -.. XXX "one of two or three possible..." seems wrong info. Below always 3 files - are indicated in the tables. - - -.. _packaging-config-filenames: - -Location and names of configuration files ------------------------------------------ - -The name and location of the configuration files vary slightly across -platforms. On Unix and Mac OS X, these are the three configuration files listed -in the order they are processed: - -+--------------+----------------------------------------------------------+-------+ -| Type of file | Location and filename | Notes | -+==============+==========================================================+=======+ -| system | :file:`{prefix}/lib/python{ver}/packaging/packaging.cfg` | \(1) | -+--------------+----------------------------------------------------------+-------+ -| personal | :file:`$HOME/.pydistutils.cfg` | \(2) | -+--------------+----------------------------------------------------------+-------+ -| local | :file:`setup.cfg` | \(3) | -+--------------+----------------------------------------------------------+-------+ - -Similarly, the configuration files on Windows ---also listed in the order they -are processed--- are these: - -+--------------+-------------------------------------------------+-------+ -| Type of file | Location and filename | Notes | -+==============+=================================================+=======+ -| system | :file:`{prefix}\\Lib\\packaging\\packaging.cfg` | \(4) | -+--------------+-------------------------------------------------+-------+ -| personal | :file:`%HOME%\\pydistutils.cfg` | \(5) | -+--------------+-------------------------------------------------+-------+ -| local | :file:`setup.cfg` | \(3) | -+--------------+-------------------------------------------------+-------+ - -On all platforms, the *personal* file can be temporarily disabled by -means of the `--no-user-cfg` option. - -Notes: - -(1) - Strictly speaking, the system-wide configuration file lives in the directory - where Packaging is installed. - -(2) - On Unix, if the :envvar:`HOME` environment variable is not defined, the - user's home directory will be determined with the :func:`getpwuid` function - from the standard :mod:`pwd` module. Packaging uses the - :func:`os.path.expanduser` function to do this. - -(3) - I.e., in the current directory (usually the location of the setup script). - -(4) - (See also note (1).) Python's default installation prefix is - :file:`C:\\Python`, so the system configuration file is normally - :file:`C:\\Python\\Lib\\packaging\\packaging.cfg`. - -(5) - On Windows, if the :envvar:`HOME` environment variable is not defined, - :envvar:`USERPROFILE` then :envvar:`HOMEDRIVE` and :envvar:`HOMEPATH` will - be tried. Packaging uses the :func:`os.path.expanduser` function to do this. - - -.. _packaging-config-syntax: - -Syntax of configuration files ------------------------------ - -All Packaging configuration files share the same syntax. Options defined in -them are grouped into sections, and each Packaging command gets its own section. -Additionally, there's a ``global`` section for options that affect every command. -Sections consist of one or more lines containing a single option specified as -``option = value``. - -For example, here's a complete configuration file that forces all commands to -run quietly by default:: - - [global] - verbose = 0 - -If this was the system configuration file, it would affect all processing -of any Python module distribution by any user on the current system. If it was -installed as your personal configuration file (on systems that support them), -it would affect only module distributions processed by you. Lastly, if it was -used as the :file:`setup.cfg` for a particular module distribution, it would -affect that distribution only. - -.. XXX "(on systems that support them)" seems wrong info - -If you wanted to, you could override the default "build base" directory and -make the :command:`build\*` commands always forcibly rebuild all files with -the following:: - - [build] - build-base = blib - force = 1 - -which corresponds to the command-line arguments:: - - pysetup run build --build-base blib --force - -except that including the :command:`build` command on the command-line means -that command will be run. Including a particular command in configuration files -has no such implication; it only means that if the command is run, the options -for it in the configuration file will apply. (This is also true if you run -other commands that derive values from it.) - -You can find out the complete list of options for any command using the -:option:`--help` option, e.g.:: - - pysetup run build --help - -and you can find out the complete list of global options by using -:option:`--help` without a command:: - - pysetup run --help - -See also the "Reference" section of the "Distributing Python Modules" manual. - -.. XXX no links to the relevant section exist. - - -.. _packaging-building-ext: - -Building extensions: tips and tricks -==================================== - -Whenever possible, Packaging tries to use the configuration information made -available by the Python interpreter used to run `pysetup`. -For example, the same compiler and linker flags used to compile Python will also -be used for compiling extensions. Usually this will work well, but in -complicated situations this might be inappropriate. This section discusses how -to override the usual Packaging behaviour. - - -.. _packaging-tweak-flags: - -Tweaking compiler/linker flags ------------------------------- - -Compiling a Python extension written in C or C++ will sometimes require -specifying custom flags for the compiler and linker in order to use a particular -library or produce a special kind of object code. This is especially true if the -extension hasn't been tested on your platform, or if you're trying to -cross-compile Python. - -.. TODO update to new setup.cfg - -In the most general case, the extension author might have foreseen that -compiling the extensions would be complicated, and provided a :file:`Setup` file -for you to edit. This will likely only be done if the module distribution -contains many separate extension modules, or if they often require elaborate -sets of compiler flags in order to work. - -A :file:`Setup` file, if present, is parsed in order to get a list of extensions -to build. Each line in a :file:`Setup` describes a single module. Lines have -the following structure:: - - module ... [sourcefile ...] [cpparg ...] [library ...] - - -Let's examine each of the fields in turn. - -* *module* is the name of the extension module to be built, and should be a - valid Python identifier. You can't just change this in order to rename a module - (edits to the source code would also be needed), so this should be left alone. - -* *sourcefile* is anything that's likely to be a source code file, at least - judging by the filename. Filenames ending in :file:`.c` are assumed to be - written in C, filenames ending in :file:`.C`, :file:`.cc`, and :file:`.c++` are - assumed to be C++, and filenames ending in :file:`.m` or :file:`.mm` are assumed - to be in Objective C. - -* *cpparg* is an argument for the C preprocessor, and is anything starting with - :option:`-I`, :option:`-D`, :option:`-U` or :option:`-C`. - -* *library* is anything ending in :file:`.a` or beginning with :option:`-l` or - :option:`-L`. - -If a particular platform requires a special library on your platform, you can -add it by editing the :file:`Setup` file and running ``pysetup run build``. -For example, if the module defined by the line :: - - foo foomodule.c - -must be linked with the math library :file:`libm.a` on your platform, simply add -:option:`-lm` to the line:: - - foo foomodule.c -lm - -Arbitrary switches intended for the compiler or the linker can be supplied with -the :option:`-Xcompiler` *arg* and :option:`-Xlinker` *arg* options:: - - foo foomodule.c -Xcompiler -o32 -Xlinker -shared -lm - -The next option after :option:`-Xcompiler` and :option:`-Xlinker` will be -appended to the proper command line, so in the above example the compiler will -be passed the :option:`-o32` option, and the linker will be passed -:option:`-shared`. If a compiler option requires an argument, you'll have to -supply multiple :option:`-Xcompiler` options; for example, to pass ``-x c++`` -the :file:`Setup` file would have to contain ``-Xcompiler -x -Xcompiler c++``. - -Compiler flags can also be supplied through setting the :envvar:`CFLAGS` -environment variable. If set, the contents of :envvar:`CFLAGS` will be added to -the compiler flags specified in the :file:`Setup` file. - - -.. _packaging-non-ms-compilers: - -Using non-Microsoft compilers on Windows ----------------------------------------- - -.. sectionauthor:: Rene Liebscher - - - -Borland/CodeGear C++ -^^^^^^^^^^^^^^^^^^^^ - -This subsection describes the necessary steps to use Packaging with the Borland -C++ compiler version 5.5. First you have to know that Borland's object file -format (OMF) is different from the format used by the Python version you can -download from the Python or ActiveState Web site. (Python is built with -Microsoft Visual C++, which uses COFF as the object file format.) For this -reason, you have to convert Python's library :file:`python25.lib` into the -Borland format. You can do this as follows: - -.. Should we mention that users have to create cfg-files for the compiler? -.. see also http://community.borland.com/article/0,1410,21205,00.html - -:: - - coff2omf python25.lib python25_bcpp.lib - -The :file:`coff2omf` program comes with the Borland compiler. The file -:file:`python25.lib` is in the :file:`Libs` directory of your Python -installation. If your extension uses other libraries (zlib, ...) you have to -convert them too. - -The converted files have to reside in the same directories as the normal -libraries. - -How does Packaging manage to use these libraries with their changed names? If -the extension needs a library (eg. :file:`foo`) Packaging checks first if it -finds a library with suffix :file:`_bcpp` (eg. :file:`foo_bcpp.lib`) and then -uses this library. In the case it doesn't find such a special library it uses -the default name (:file:`foo.lib`.) [#]_ - -To let Packaging compile your extension with Borland, C++ you now have to -type:: - - pysetup run build --compiler bcpp - -If you want to use the Borland C++ compiler as the default, you could specify -this in your personal or system-wide configuration file for Packaging (see -section :ref:`packaging-config-files`.) - - -.. seealso:: - - `C++Builder Compiler `_ - Information about the free C++ compiler from Borland, including links to the - download pages. - - `Creating Python Extensions Using Borland's Free Compiler `_ - Document describing how to use Borland's free command-line C++ compiler to build - Python. - - -GNU C / Cygwin / MinGW -^^^^^^^^^^^^^^^^^^^^^^ - -This section describes the necessary steps to use Packaging with the GNU C/C++ -compilers in their Cygwin and MinGW distributions. [#]_ For a Python interpreter -that was built with Cygwin, everything should work without any of these -following steps. - -Not all extensions can be built with MinGW or Cygwin, but many can. Extensions -most likely to not work are those that use C++ or depend on Microsoft Visual C -extensions. - -To let Packaging compile your extension with Cygwin, you have to type:: - - pysetup run build --compiler=cygwin - -and for Cygwin in no-cygwin mode [#]_ or for MinGW, type:: - - pysetup run build --compiler=mingw32 - -If you want to use any of these options/compilers as default, you should -consider writing it in your personal or system-wide configuration file for -Packaging (see section :ref:`packaging-config-files`.) - -Older Versions of Python and MinGW -"""""""""""""""""""""""""""""""""" -The following instructions only apply if you're using a version of Python -inferior to 2.4.1 with a MinGW inferior to 3.0.0 (with -:file:`binutils-2.13.90-20030111-1`). - -These compilers require some special libraries. This task is more complex than -for Borland's C++, because there is no program to convert the library. First -you have to create a list of symbols which the Python DLL exports. (You can find -a good program for this task at -http://www.emmestech.com/software/pexports-0.43/download_pexports.html). - -.. I don't understand what the next line means. --amk - (inclusive the references on data structures.) - -:: - - pexports python25.dll > python25.def - -The location of an installed :file:`python25.dll` will depend on the -installation options and the version and language of Windows. In a "just for -me" installation, it will appear in the root of the installation directory. In -a shared installation, it will be located in the system directory. - -Then you can create from these information an import library for gcc. :: - - /cygwin/bin/dlltool --dllname python25.dll --def python25.def --output-lib libpython25.a - -The resulting library has to be placed in the same directory as -:file:`python25.lib`. (Should be the :file:`libs` directory under your Python -installation directory.) - -If your extension uses other libraries (zlib,...) you might have to convert -them too. The converted files have to reside in the same directories as the -normal libraries do. - - -.. seealso:: - - `Building Python modules on MS Windows platform with MinGW `_ - Information about building the required libraries for the MinGW - environment. - - -.. rubric:: Footnotes - -.. [#] This also means you could replace all existing COFF-libraries with - OMF-libraries of the same name. - -.. [#] Check http://sources.redhat.com/cygwin/ and http://www.mingw.org/ for - more information. - -.. [#] Then you have no POSIX emulation available, but you also don't need - :file:`cygwin1.dll`. diff -r 2e49722c7263 -r 6944bdf1289a Doc/install/pysetup-config.rst --- a/Doc/install/pysetup-config.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -.. _packaging-pysetup-config: - -===================== -Pysetup Configuration -===================== - -Pysetup supports two configuration files: :file:`.pypirc` and :file:`packaging.cfg`. - -.. FIXME integrate with configfile instead of duplicating - -Configuring indexes -------------------- - -You can configure additional indexes in :file:`.pypirc` to be used for index-related -operations. By default, all configured index-servers and package-servers will be used -in an additive fashion. To limit operations to specific indexes, use the :option:`--index` -and :option:`--package-server options`:: - - $ pysetup install --index pypi --package-server django some.project - -Adding indexes to :file:`.pypirc`:: - - [packaging] - index-servers = - pypi - other - - package-servers = - django - - [pypi] - repository: - username: - password: - - [other] - repository: - username: - password: - - [django] - repository: - username: - password: diff -r 2e49722c7263 -r 6944bdf1289a Doc/install/pysetup-servers.rst --- a/Doc/install/pysetup-servers.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -.. _packaging-pysetup-servers: - -=============== -Package Servers -=============== - -Pysetup supports installing Python packages from *Package Servers* in addition -to PyPI indexes and mirrors. - -Package Servers are simple directory listings of Python distributions. Directories -can be served via HTTP or a local file system. This is useful when you want to -dump source distributions in a directory and not worry about the full index structure. - -Serving distributions from Apache ---------------------------------- -:: - - $ mkdir -p /var/www/html/python/distributions - $ cp *.tar.gz /var/www/html/python/distributions/ - - - ServerAdmin webmaster@domain.com - DocumentRoot "/var/www/html/python" - ServerName python.example.org - ErrorLog logs/python.example.org-error.log - CustomLog logs/python.example.org-access.log common - Options Indexes FollowSymLinks MultiViews - DirectoryIndex index.html index.htm - - - Options Indexes FollowSymLinks MultiViews - Order allow,deny - Allow from all - - - -Add the Apache based distribution server to :file:`.pypirc`:: - - [packaging] - package-servers = - apache - - [apache] - repository: http://python.example.org/distributions/ - - -Serving distributions from a file system ----------------------------------------- -:: - - $ mkdir -p /data/python/distributions - $ cp *.tar.gz /data/python/distributions/ - -Add the directory to :file:`.pypirc`:: - - [packaging] - package-servers = - local - - [local] - repository: file:///data/python/distributions/ diff -r 2e49722c7263 -r 6944bdf1289a Doc/install/pysetup.rst --- a/Doc/install/pysetup.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -.. _packaging-pysetup: - -================ -Pysetup Tutorial -================ - -Getting started ---------------- - -Pysetup is a simple script that supports the following features: - -- install, remove, list, and verify Python packages; -- search for available packages on PyPI or any *Simple Index*; -- verify installed packages (md5sum, installed files, version). - - -Finding out what's installed ----------------------------- - -Pysetup makes it easy to find out what Python packages are installed:: - - $ pysetup search virtualenv - virtualenv 1.6 at /opt/python3.3/lib/python3.3/site-packages/virtualenv-1.6-py3.3.egg-info - - $ pysetup search --all - pyverify 0.8.1 at /opt/python3.3/lib/python3.3/site-packages/pyverify-0.8.1.dist-info - virtualenv 1.6 at /opt/python3.3/lib/python3.3/site-packages/virtualenv-1.6-py3.3.egg-info - wsgiref 0.1.2 at /opt/python3.3/lib/python3.3/wsgiref.egg-info - ... - - -Installing a distribution -------------------------- - -Pysetup can install a Python project from the following sources: - -- PyPI and Simple Indexes; -- source directories containing a valid :file:`setup.py` or :file:`setup.cfg`; -- distribution source archives (:file:`project-1.0.tar.gz`, :file:`project-1.0.zip`); -- HTTP (http://host/packages/project-1.0.tar.gz). - - -Installing from PyPI and Simple Indexes:: - - $ pysetup install project - $ pysetup install project==1.0 - -Installing from a distribution source archive:: - - $ pysetup install project-1.0.tar.gz - -Installing from a source directory containing a valid :file:`setup.py` or -:file:`setup.cfg`:: - - $ cd path/to/source/directory - $ pysetup install - - $ pysetup install path/to/source/directory - -Installing from HTTP:: - - $ pysetup install http://host/packages/project-1.0.tar.gz - - -Retrieving metadata -------------------- - -You can gather metadata from two sources, a project's source directory or an -installed distribution. The `pysetup metadata` command can retrieve one or -more metadata fields using the `-f` option and a metadata field as the -argument. :: - - $ pysetup metadata virtualenv -f version -f name - Version: - 1.6 - Name: - virtualenv - - $ pysetup metadata virtualenv --all - Metadata-Version: - 1.0 - Name: - virtualenv - Version: - 1.6 - Platform: - UNKNOWN - Summary: - Virtual Python Environment builder - ... - -.. seealso:: - - There are three metadata versions, 1.0, 1.1, and 1.2. The following PEPs - describe specifics of the field names, and their semantics and usage. 1.0 - :PEP:`241`, 1.1 :PEP:`314`, and 1.2 :PEP:`345` - - -Removing a distribution ------------------------ - -You can remove one or more installed distributions using the `pysetup remove` -command:: - - $ pysetup remove virtualenv - removing 'virtualenv': - /opt/python3.3/lib/python3.3/site-packages/virtualenv-1.6-py3.3.egg-info/dependency_links.txt - /opt/python3.3/lib/python3.3/site-packages/virtualenv-1.6-py3.3.egg-info/entry_points.txt - /opt/python3.3/lib/python3.3/site-packages/virtualenv-1.6-py3.3.egg-info/not-zip-safe - /opt/python3.3/lib/python3.3/site-packages/virtualenv-1.6-py3.3.egg-info/PKG-INFO - /opt/python3.3/lib/python3.3/site-packages/virtualenv-1.6-py3.3.egg-info/SOURCES.txt - /opt/python3.3/lib/python3.3/site-packages/virtualenv-1.6-py3.3.egg-info/top_level.txt - Proceed (y/n)? y - success: removed 6 files and 1 dirs - -The optional '-y' argument auto confirms, skipping the conformation prompt:: - - $ pysetup remove virtualenv -y - - -Getting help ------------- - -All pysetup actions take the `-h` and `--help` options which prints the commands -help string to stdout. :: - - $ pysetup remove -h - Usage: pysetup remove dist [-y] - or: pysetup remove --help - - Uninstall a Python package. - - positional arguments: - dist installed distribution name - - optional arguments: - -y auto confirm package removal - -Getting a list of all pysetup actions and global options:: - - $ pysetup --help - Usage: pysetup [options] action [action_options] - - Actions: - run: Run one or several commands - metadata: Display the metadata of a project - install: Install a project - remove: Remove a project - search: Search for a project - graph: Display a graph - create: Create a Project - - To get more help on an action, use: - - pysetup action --help - - Global options: - --verbose (-v) run verbosely (default) - --quiet (-q) run quietly (turns verbosity off) - --dry-run (-n) don't actually do anything - --help (-h) show detailed help message - --no-user-cfg ignore pydistutils.cfg in your home directory - --version Display the version diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/abc.rst --- a/Doc/library/abc.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/abc.rst Sat May 14 18:40:38 2011 +0200 @@ -12,13 +12,13 @@ -------------- This module provides the infrastructure for defining an :term:`abstract base -class` (ABC) in Python, as outlined in :pep:`3119`; see the PEP for why this +class` (ABCs) in Python, as outlined in :pep:`3119`; see the PEP for why this was added to Python. (See also :pep:`3141` and the :mod:`numbers` module regarding a type hierarchy for numbers based on ABCs.) The :mod:`collections` module has some concrete classes that derive from ABCs; these can, of course, be further derived. In addition the -:mod:`collections.abc` submodule has some ABCs that can be used to test whether +:mod:`collections` module has some ABCs that can be used to test whether a class or instance provides a particular interface, for example, is it hashable or a mapping. diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/builtins.rst --- a/Doc/library/builtins.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/builtins.rst Sat May 14 18:40:38 2011 +0200 @@ -7,9 +7,7 @@ This module provides direct access to all 'built-in' identifiers of Python; for example, ``builtins.open`` is the full name for the built-in function -:func:`open`. See :ref:`built-in-funcs` and :ref:`built-in-consts` for -documentation. - +:func:`open`. This module is not normally accessed explicitly by most applications, but can be useful in modules that provide objects with the same name as a built-in value, diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/bz2.rst --- a/Doc/library/bz2.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/bz2.rst Sat May 14 18:40:38 2011 +0200 @@ -37,18 +37,14 @@ *fileobj*), or operate directly on a named file (named by *filename*). Exactly one of these two parameters should be provided. - The *mode* argument can be either ``'r'`` for reading (default), ``'w'`` for - overwriting, or ``'a'`` for appending. If *fileobj* is provided, a mode of - ``'w'`` does not truncate the file, and is instead equivalent to ``'a'``. + The *mode* argument can be either ``'r'`` for reading (default), or ``'w'`` + for writing. The *buffering* argument is ignored. Its use is deprecated. - If *mode* is ``'w'`` or ``'a'``, *compresslevel* can be a number between - ``1`` and ``9`` specifying the level of compression: ``1`` produces the - least compression, and ``9`` (default) produces the most compression. - - If *mode* is ``'r'``, the input file may be the concatenation of multiple - compressed streams. + If *mode* is ``'w'``, *compresslevel* can be a number between ``1`` and + ``9`` specifying the level of compression: ``1`` produces the least + compression, and ``9`` (default) produces the most compression. :class:`BZ2File` provides all of the members specified by the :class:`io.BufferedIOBase`, except for :meth:`detach` and :meth:`truncate`. @@ -74,10 +70,6 @@ .. versionchanged:: 3.3 The *fileobj* argument to the constructor was added. - .. versionchanged:: 3.3 - The ``'a'`` (append) mode was added, along with support for reading - multi-stream files. - Incremental (de)compression --------------------------- @@ -114,20 +106,14 @@ incrementally. For one-shot compression, use the :func:`decompress` function instead. - .. note:: - This class does not transparently handle inputs containing multiple - compressed streams, unlike :func:`decompress` and :class:`BZ2File`. If - you need to decompress a multi-stream input with :class:`BZ2Decompressor`, - you must use a new decompressor for each stream. - .. method:: decompress(data) Provide data to the decompressor object. Returns a chunk of decompressed data if possible, or an empty byte string otherwise. - Attempting to decompress data after the end of the current stream is - reached raises an :exc:`EOFError`. If any data is found after the end of - the stream, it is ignored and saved in the :attr:`unused_data` attribute. + Attempting to decompress data after the end of stream is reached raises + an :exc:`EOFError`. If any data is found after the end of the stream, it + is ignored and saved in the :attr:`unused_data` attribute. .. attribute:: eof @@ -141,9 +127,6 @@ Data found after the end of the compressed stream. - If this attribute is accessed before the end of the stream has been - reached, its value will be ``b''``. - One-shot (de)compression ------------------------ @@ -162,11 +145,5 @@ Decompress *data*. - If *data* is the concatenation of multiple compressed streams, decompress - all of the streams. - For incremental decompression, use a :class:`BZ2Decompressor` instead. - .. versionchanged:: 3.3 - Support for multi-stream inputs was added. - diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/codecs.rst --- a/Doc/library/codecs.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/codecs.rst Sat May 14 18:40:38 2011 +0200 @@ -458,8 +458,7 @@ .. method:: reset() - Reset the encoder to the initial state. The output is discarded: call - ``.encode('', final=True)`` to reset the encoder and to get the output. + Reset the encoder to the initial state. .. method:: IncrementalEncoder.getstate() diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/collections.abc.rst --- a/Doc/library/collections.abc.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/collections.abc.rst Sat May 14 18:40:38 2011 +0200 @@ -23,7 +23,7 @@ .. versionchanged:: 3.3 Formerly, this module was part of the :mod:`collections` module. -.. _collections-abstract-base-classes: +.. _abstract-base-classes: Collections Abstract Base Classes --------------------------------- @@ -44,7 +44,7 @@ :class:`Iterable`, ``index``, and ``count`` :class:`Container` -:class:`MutableSequence` :class:`Sequence` ``__setitem__``, Inherited :class:`Sequence` methods and +:class:`MutableSequence` :class:`Sequence` ``__setitem__`` Inherited :class:`Sequence` methods and ``__delitem__``, ``append``, ``reverse``, ``extend``, ``pop``, ``insert`` ``remove``, ``clear``, and ``__iadd__`` @@ -175,7 +175,7 @@ .. seealso:: - * `OrderedSet recipe `_ for an - example built on :class:`MutableSet`. + * `OrderedSet recipe `_ that uses + :class:`MutableSet`. - * For more about ABCs, see the :mod:`abc` module and :pep:`3119`. + * For more about ABCs, see the :mod:`abc` module and :pep:`3119`. diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/collections.rst --- a/Doc/library/collections.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/collections.rst Sat May 14 18:40:38 2011 +0200 @@ -34,7 +34,7 @@ ===================== ==================================================================== .. versionchanged:: 3.3 - Moved :ref:`collections-abstract-base-classes` to the :mod:`collections.abc` module. + Moved :ref:`abstract-base-classes` to the :mod:`collections.abc` module. For backwards compatibility, they continue to be visible in this module as well. @@ -971,6 +971,10 @@ class OrderedCounter(Counter, OrderedDict): 'Counter that remembers the order elements are first encountered' + def __init__(self, iterable=None, **kwds): + OrderedDict.__init__(self) + Counter.__init__(self, iterable, **kwds) + def __repr__(self): return '%s(%r)' % (self.__class__.__name__, OrderedDict(self)) diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/concurrent.futures.rst --- a/Doc/library/concurrent.futures.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/concurrent.futures.rst Sat May 14 18:40:38 2011 +0200 @@ -169,12 +169,6 @@ of at most *max_workers* processes. If *max_workers* is ``None`` or not given, it will default to the number of processors on the machine. - .. versionchanged:: 3.3 - When one of the worker processes terminates abruptly, a - :exc:`BrokenProcessPool` error is now raised. Previously, behaviour - was undefined but operations on the executor or its futures would often - freeze or deadlock. - .. _processpoolexecutor-example: @@ -375,16 +369,3 @@ :pep:`3148` -- futures - execute computations asynchronously The proposal which described this feature for inclusion in the Python standard library. - - -Exception classes ------------------ - -.. exception:: BrokenProcessPool - - Derived from :exc:`RuntimeError`, this exception class is raised when - one of the workers of a :class:`ProcessPoolExecutor` has terminated - in a non-clean fashion (for example, if it was killed from the outside). - - .. versionadded:: 3.3 - diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/constants.rst --- a/Doc/library/constants.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/constants.rst Sat May 14 18:40:38 2011 +0200 @@ -1,5 +1,3 @@ -.. _built-in-consts: - Built-in Constants ================== diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/crypt.rst --- a/Doc/library/crypt.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/crypt.rst Sat May 14 18:40:38 2011 +0200 @@ -29,8 +29,6 @@ Hashing Methods --------------- -.. versionadded:: 3.3 - The :mod:`crypt` module defines the list of hashing methods (not all methods are available on all platforms): @@ -39,26 +37,33 @@ A Modular Crypt Format method with 16 character salt and 86 character hash. This is the strongest method. + .. versionadded:: 3.3 + .. data:: METHOD_SHA256 Another Modular Crypt Format method with 16 character salt and 43 character hash. + .. versionadded:: 3.3 + .. data:: METHOD_MD5 Another Modular Crypt Format method with 8 character salt and 22 character hash. + .. versionadded:: 3.3 + .. data:: METHOD_CRYPT The traditional method with a 2 character salt and 13 characters of hash. This is the weakest method. + .. versionadded:: 3.3 + Module Attributes ----------------- -.. versionadded:: 3.3 .. attribute:: methods @@ -66,6 +71,8 @@ ``crypt.METHOD_*`` objects. This list is sorted from strongest to weakest, and is guaranteed to have at least ``crypt.METHOD_CRYPT``. + .. versionadded:: 3.3 + Module Functions ---------------- @@ -101,8 +108,9 @@ different sizes in the *salt*, it is recommended to use the full crypted password as salt when checking for a password. - .. versionchanged:: 3.3 - Accept ``crypt.METHOD_*`` values in addition to strings for *salt*. +.. versionchanged:: 3.3 + Before version 3.3, *salt* must be specified as a string and cannot + accept ``crypt.METHOD_*`` values (which don't exist anyway). .. function:: mksalt(method=None) @@ -116,27 +124,25 @@ 16 random characters from the set ``[./a-zA-Z0-9]``, suitable for passing as the *salt* argument to :func:`crypt`. - .. versionadded:: 3.3 +.. versionadded:: 3.3 Examples -------- A simple example illustrating typical use:: - import pwd - import crypt - import getpass + import crypt, getpass, pwd def login(): - username = input('Python login: ') + username = input('Python login:') cryptedpasswd = pwd.getpwnam(username)[1] if cryptedpasswd: if cryptedpasswd == 'x' or cryptedpasswd == '*': - raise ValueError('no support for shadow passwords') + raise "Sorry, currently no support for shadow passwords" cleartext = getpass.getpass() return crypt.crypt(cleartext, cryptedpasswd) == cryptedpasswd else: - return True + return 1 To generate a hash of a password using the strongest available method and check it against the original:: @@ -145,4 +151,4 @@ hashed = crypt.crypt(plaintext) if hashed != crypt.crypt(plaintext, hashed): - raise ValueError("hashed version doesn't validate against original") + raise "Hashed version doesn't validate against original" diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/depgraph-output.png Binary file Doc/library/depgraph-output.png has changed diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/distutils.rst --- a/Doc/library/distutils.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/distutils.rst Sat May 14 18:40:38 2011 +0200 @@ -12,26 +12,18 @@ 100%-pure Python, or may be extension modules written in C, or may be collections of Python packages which include modules coded in both Python and C. -.. deprecated:: 3.3 - :mod:`packaging` replaces Distutils. See :ref:`packaging-index` and - :ref:`packaging-install-index`. +This package is discussed in two separate chapters: -User documentation and API reference are provided in another document: - .. seealso:: :ref:`distutils-index` The manual for developers and packagers of Python modules. This describes how to prepare :mod:`distutils`\ -based packages so that they may be - easily installed into an existing Python installation. If also contains - instructions for end-users wanting to install a distutils-based package, - :ref:`install-index`. + easily installed into an existing Python installation. + :ref:`install-index` + An "administrators" manual which includes information on installing + modules into an existing Python installation. You do not need to be a + Python programmer to read this manual. -.. trick to silence a Sphinx warning - -.. toctree:: - :hidden: - - ../distutils/index diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/functions.rst --- a/Doc/library/functions.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/functions.rst Sat May 14 18:40:38 2011 +0200 @@ -290,18 +290,19 @@ The resulting list is sorted alphabetically. For example: >>> import struct - >>> dir() # show the names in the module namespace + >>> dir() # doctest: +SKIP ['__builtins__', '__doc__', '__name__', 'struct'] - >>> dir(struct) # show the names in the struct module + >>> dir(struct) # doctest: +NORMALIZE_WHITESPACE ['Struct', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_clearcache', 'calcsize', 'error', 'pack', 'pack_into', 'unpack', 'unpack_from'] - >>> class Shape(object): - def __dir__(self): - return ['area', 'perimeter', 'location'] - >>> s = Shape() - >>> dir(s) - ['area', 'perimeter', 'location'] + >>> class Foo: + ... def __dir__(self): + ... return ["kan", "ga", "roo"] + ... + >>> f = Foo() + >>> dir(f) + ['ga', 'kan', 'roo'] .. note:: @@ -332,21 +333,15 @@ :meth:`__next__` method of the iterator returned by :func:`enumerate` returns a tuple containing a count (from *start* which defaults to 0) and the corresponding value obtained from iterating over *iterable*. + :func:`enumerate` is useful for obtaining an indexed series: ``(0, seq[0])``, + ``(1, seq[1])``, ``(2, seq[2])``, .... For example: - >>> for i, season in enumerate('Spring Summer Fall Winter'.split(), start=1): - print(i, season) - 1 Spring - 2 Summer - 3 Fall - 4 Winter - - Equivalent to:: - - def enumerate(sequence, start=0): - n = start - for elem in sequence: - yield n, elem - n += 1 + >>> for i, season in enumerate(['Spring', 'Summer', 'Fall', 'Winter']): + ... print(i, season) + 0 Spring + 1 Summer + 2 Fall + 3 Winter .. function:: eval(expression, globals=None, locals=None) @@ -585,7 +580,7 @@ Two objects with non-overlapping lifetimes may have the same :func:`id` value. - .. impl-detail:: This is the address of the object in memory. + .. impl-detail:: This is the address of the object. .. function:: input([prompt]) @@ -657,10 +652,10 @@ One useful application of the second form of :func:`iter` is to read lines of a file until a certain line is reached. The following example reads a file - until the :meth:`readline` method returns an empty string:: + until ``"STOP"`` is reached: :: - with open('mydata.txt') as fp: - for line in iter(fp.readline, ''): + with open("mydata.txt") as fp: + for line in iter(fp.readline, "STOP"): process_line(line) @@ -1174,9 +1169,8 @@ It can be called either on the class (such as ``C.f()``) or on an instance (such as ``C().f()``). The instance is ignored except for its class. - Static methods in Python are similar to those found in Java or C++. Also see - :func:`classmethod` for a variant that is useful for creating alternate class - constructors. + Static methods in Python are similar to those found in Java or C++. For a more + advanced concept, see :func:`classmethod` in this section. For more information on static methods, consult the documentation on the standard type hierarchy in :ref:`types`. @@ -1276,10 +1270,6 @@ references. The zero argument form automatically searches the stack frame for the class (``__class__``) and the first argument. - For practical suggestions on how to design cooperative classes using - :func:`super`, see `guide to using super() - `_. - .. function:: tuple([iterable]) diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/mmap.rst --- a/Doc/library/mmap.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/mmap.rst Sat May 14 18:40:38 2011 +0200 @@ -190,16 +190,12 @@ move will raise a :exc:`TypeError` exception. - .. method:: read([n]) + .. method:: read(num) - Return a :class:`bytes` containing up to *n* bytes starting from the - current file position. If the argument is omitted, *None* or negative, - return all bytes from the current file position to the end of the - mapping. The file position is updated to point after the bytes that were - returned. + Return a :class:`bytes` containing up to *num* bytes starting from the + current file position; the file position is updated to point after the + bytes that were returned. - .. versionchanged:: 3.3 - Argument can be omitted or *None*. .. method:: read_byte() diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/multiprocessing.rst --- a/Doc/library/multiprocessing.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/multiprocessing.rst Sat May 14 18:40:38 2011 +0200 @@ -411,20 +411,6 @@ See :ref:`multiprocessing-auth-keys`. - .. attribute:: sentinel - - A numeric handle of a system object which will become "ready" when - the process ends. - - On Windows, this is an OS handle usable with the ``WaitForSingleObject`` - and ``WaitForMultipleObjects`` family of API calls. On Unix, this is - a file descriptor usable with primitives from the :mod:`select` module. - - You can use this value if you want to wait on several events at once. - Otherwise calling :meth:`join()` is simpler. - - .. versionadded:: 3.3 - .. method:: terminate() Terminate the process. On Unix this is done using the ``SIGTERM`` signal; diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/numbers.rst --- a/Doc/library/numbers.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/numbers.rst Sat May 14 18:40:38 2011 +0200 @@ -5,9 +5,9 @@ :synopsis: Numeric abstract base classes (Complex, Real, Integral, etc.). -The :mod:`numbers` module (:pep:`3141`) defines a hierarchy of numeric -:term:`abstract base classes ` which progressively define -more operations. None of the types defined in this module can be instantiated. +The :mod:`numbers` module (:pep:`3141`) defines a hierarchy of numeric abstract +base classes which progressively define more operations. None of the types +defined in this module can be instantiated. .. class:: Number diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/os.rst --- a/Doc/library/os.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/os.rst Sat May 14 18:40:38 2011 +0200 @@ -1019,19 +1019,6 @@ Availability: Unix, Windows. -.. function:: pipe2(flags) - - Create a pipe with *flags* set atomically. - *flags* can be constructed by ORing together one or more of these values: - :data:`O_NONBLOCK`, :data:`O_CLOEXEC`. - Return a pair of file descriptors ``(r, w)`` usable for reading and writing, - respectively. - - Availability: some flavors of Unix. - - .. versionadded:: 3.3 - - .. function:: posix_fallocate(fd, offset, len) Ensures that enough disk space is allocated for the file specified by *fd* @@ -1311,7 +1298,6 @@ O_NOCTTY O_SHLOCK O_EXLOCK - O_CLOEXEC These constants are only available on Unix. @@ -1360,26 +1346,7 @@ Using :func:`access` to check if a user is authorized to e.g. open a file before actually doing so using :func:`open` creates a security hole, because the user might exploit the short time interval between checking - and opening the file to manipulate it. It's preferable to use :term:`EAFP` - techniques. For example:: - - if os.access("myfile", os.R_OK): - with open("myfile") as fp: - return fp.read() - return "some default data" - - is better written as:: - - try: - fp = open("myfile") - except IOError as e: - if e.errno == errno.EACCESS: - return "some default data" - # Not a permission error. - raise - else: - with fp: - return fp.read() + and opening the file to manipulate it. .. note:: diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging-misc.rst --- a/Doc/library/packaging-misc.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -.. temporary file for modules that don't need a dedicated file yet - -:mod:`packaging.errors` --- Packaging exceptions -================================================ - -.. module:: packaging.errors - :synopsis: Packaging exceptions. - - -Provides exceptions used by the Packaging modules. Note that Packaging modules -may raise standard exceptions; in particular, SystemExit is usually raised for -errors that are obviously the end-user's fault (e.g. bad command-line arguments). - -This module is safe to use in ``from ... import *`` mode; it only exports -symbols whose names start with ``Packaging`` and end with ``Error``. - - -:mod:`packaging.manifest` --- The Manifest class -================================================ - -.. module:: packaging.manifest - :synopsis: The Manifest class, used for poking about the file system and - building lists of files. - - -This module provides the :class:`Manifest` class, used for poking about the -filesystem and building lists of files. diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.command.rst --- a/Doc/library/packaging.command.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,111 +0,0 @@ -:mod:`packaging.command` --- Standard Packaging commands -======================================================== - -.. module:: packaging.command - :synopsis: Standard packaging commands. - - -This subpackage contains one module for each standard Packaging command, such as -:command:`build` or :command:`upload`. Each command is implemented as a -separate module, with the command name as the name of the module and of the -class defined therein. - - - -:mod:`packaging.command.cmd` --- Abstract base class for Packaging commands -=========================================================================== - -.. module:: packaging.command.cmd - :synopsis: Abstract base class for commands. - - -This module supplies the abstract base class :class:`Command`. This class is -subclassed by the modules in the packaging.command subpackage. - - -.. class:: Command(dist) - - Abstract base class for defining command classes, the "worker bees" of the - Packaging. A useful analogy for command classes is to think of them as - subroutines with local variables called *options*. The options are declared - in :meth:`initialize_options` and defined (given their final values) in - :meth:`finalize_options`, both of which must be defined by every command - class. The distinction between the two is necessary because option values - might come from the outside world (command line, config file, ...), and any - options dependent on other options must be computed after these outside - influences have been processed --- hence :meth:`finalize_options`. The body - of the subroutine, where it does all its work based on the values of its - options, is the :meth:`run` method, which must also be implemented by every - command class. - - The class constructor takes a single argument *dist*, a - :class:`~packaging.dist.Distribution` instance. - - -Creating a new Packaging command --------------------------------- - -This section outlines the steps to create a new Packaging command. - -.. XXX the following paragraph is focused on the stdlib; expand it to document - how to write and register a command in third-party projects - -A new command lives in a module in the :mod:`packaging.command` package. There -is a sample template in that directory called :file:`command_template`. Copy -this file to a new module with the same name as the new command you're -implementing. This module should implement a class with the same name as the -module (and the command). So, for instance, to create the command -``peel_banana`` (so that users can run ``setup.py peel_banana``), you'd copy -:file:`command_template` to :file:`packaging/command/peel_banana.py`, then edit -it so that it's implementing the class :class:`peel_banana`, a subclass of -:class:`Command`. It must define the following methods: - -.. method:: Command.initialize_options() - - Set default values for all the options that this command supports. Note that - these defaults may be overridden by other commands, by the setup script, by - config files, or by the command line. Thus, this is not the place to code - dependencies between options; generally, :meth:`initialize_options` - implementations are just a bunch of ``self.foo = None`` assignments. - - -.. method:: Command.finalize_options() - - Set final values for all the options that this command supports. This is - always called as late as possible, i.e. after any option assignments from the - command line or from other commands have been done. Thus, this is the place - to to code option dependencies: if *foo* depends on *bar*, then it is safe to - set *foo* from *bar* as long as *foo* still has the same value it was - assigned in :meth:`initialize_options`. - - -.. method:: Command.run() - - A command's raison d'etre: carry out the action it exists to perform, - controlled by the options initialized in :meth:`initialize_options`, - customized by other commands, the setup script, the command line, and config - files, and finalized in :meth:`finalize_options`. All terminal output and - filesystem interaction should be done by :meth:`run`. - - -Command classes may define this attribute: - - -.. attribute:: Command.sub_commands - - *sub_commands* formalizes the notion of a "family" of commands, - e.g. ``install_dist`` as the parent with sub-commands ``install_lib``, - ``install_headers``, etc. The parent of a family of commands defines - *sub_commands* as a class attribute; it's a list of 2-tuples ``(command_name, - predicate)``, with *command_name* a string and *predicate* a function, a - string or ``None``. *predicate* is a method of the parent command that - determines whether the corresponding command is applicable in the current - situation. (E.g. ``install_headers`` is only applicable if we have any C - header files to install.) If *predicate* is ``None``, that command is always - applicable. - - *sub_commands* is usually defined at the *end* of a class, because - predicates can be methods of the class, so they must already have been - defined. The canonical example is the :command:`install_dist` command. - -.. XXX document how to add a custom command to another one's subcommands diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.compiler.rst --- a/Doc/library/packaging.compiler.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,674 +0,0 @@ -:mod:`packaging.compiler` --- Compiler classes -============================================== - -.. module:: packaging.compiler - :synopsis: Compiler classes to build C/C++ extensions or libraries. - - -This subpackage contains an abstract base class representing a compiler and -concrete implementations for common compilers. The compiler classes should not -be instantiated directly, but created using the :func:`new_compiler` factory -function. Compiler types provided by Packaging are listed in -:ref:`packaging-standard-compilers`. - - -Public functions ----------------- - -.. function:: new_compiler(plat=None, compiler=None, verbose=0, dry_run=0, force=0) - - Factory function to generate an instance of some - :class:`~.ccompiler.CCompiler` subclass for the requested platform or - compiler type. - - If no argument is given for *plat* and *compiler*, the default compiler type - for the platform (:attr:`os.name`) will be used: ``'unix'`` for Unix and - Mac OS X, ``'msvc'`` for Windows. - - If *plat* is given, it must be one of ``'posix'``, ``'darwin'`` or ``'nt'``. - An invalid value will not raise an exception but use the default compiler - type for the current platform. - - .. XXX errors should never pass silently; this behavior is particularly - harmful when a compiler type is given as first argument - - If *compiler* is given, *plat* will be ignored, allowing you to get for - example a ``'unix'`` compiler object under Windows or an ``'msvc'`` compiler - under Unix. However, not all compiler types can be instantiated on every - platform. - - -.. function:: customize_compiler(compiler) - - Do any platform-specific customization of a CCompiler instance. Mainly - needed on Unix to plug in the information that varies across Unices and is - stored in CPython's Makefile. - - -.. function:: gen_lib_options(compiler, library_dirs, runtime_library_dirs, libraries) - - Generate linker options for searching library directories and linking with - specific libraries. *libraries* and *library_dirs* are, respectively, lists - of library names (not filenames!) and search directories. Returns a list of - command-line options suitable for use with some compiler (depending on the - two format strings passed in). - - -.. function:: gen_preprocess_options(macros, include_dirs) - - Generate C preprocessor options (:option:`-D`, :option:`-U`, :option:`-I`) as - used by at least two types of compilers: the typical Unix compiler and Visual - C++. *macros* is the usual thing, a list of 1- or 2-tuples, where ``(name,)`` - means undefine (:option:`-U`) macro *name*, and ``(name, value)`` means - define (:option:`-D`) macro *name* to *value*. *include_dirs* is just a list - of directory names to be added to the header file search path (:option:`-I`). - Returns a list of command-line options suitable for either Unix compilers or - Visual C++. - - -.. function:: get_default_compiler(osname, platform) - - Determine the default compiler to use for the given platform. - - *osname* should be one of the standard Python OS names (i.e. the ones - returned by ``os.name``) and *platform* the common value returned by - ``sys.platform`` for the platform in question. - - The default values are ``os.name`` and ``sys.platform``. - - -.. function:: set_compiler(location) - - Add or change a compiler - - -.. function:: show_compilers() - - Print list of available compilers (used by the :option:`--help-compiler` - options to :command:`build`, :command:`build_ext`, :command:`build_clib`). - - -.. _packaging-standard-compilers: - -Standard compilers ------------------- - -Concrete subclasses of :class:`~.ccompiler.CCompiler` are provided in submodules -of the :mod:`packaging.compiler` package. You do not need to import them, using -:func:`new_compiler` is the public API to use. This table documents the -standard compilers; be aware that they can be replaced by other classes on your -platform. - -=============== ======================================================== ======= -name description notes -=============== ======================================================== ======= -``'unix'`` typical Unix-style command-line C compiler [#]_ -``'msvc'`` Microsoft compiler [#]_ -``'bcpp'`` Borland C++ compiler -``'cygwin'`` Cygwin compiler (Windows port of GCC) -``'mingw32'`` Mingw32 port of GCC (same as Cygwin in no-Cygwin mode) -=============== ======================================================== ======= - - -.. [#] The Unix compiler class assumes this behavior: - - * macros defined with :option:`-Dname[=value]` - - * macros undefined with :option:`-Uname` - - * include search directories specified with :option:`-Idir` - - * libraries specified with :option:`-llib` - - * library search directories specified with :option:`-Ldir` - - * compile handled by :program:`cc` (or similar) executable with - :option:`-c` option: compiles :file:`.c` to :file:`.o` - - * link static library handled by :program:`ar` command (possibly with - :program:`ranlib`) - - * link shared library handled by :program:`cc` :option:`-shared` - - -.. [#] On Windows, extension modules typically need to be compiled with the same - compiler that was used to compile CPython (for example Microsoft Visual - Studio .NET 2003 for CPython 2.4 and 2.5). The AMD64 and Itanium - binaries are created using the Platform SDK. - - Under the hood, there are actually two different subclasses of - :class:`~.ccompiler.CCompiler` defined: one is compatible with MSVC 2005 - and 2008, the other works with older versions. This should not be a - concern for regular use of the functions in this module. - - Packaging will normally choose the right compiler, linker etc. on its - own. To override this choice, the environment variables - *DISTUTILS_USE_SDK* and *MSSdk* must be both set. *MSSdk* indicates that - the current environment has been setup by the SDK's ``SetEnv.Cmd`` - script, or that the environment variables had been registered when the - SDK was installed; *DISTUTILS_USE_SDK* indicates that the user has made - an explicit choice to override the compiler selection done by Packaging. - - .. TODO document the envvars in Doc/using and the man page - - -:mod:`packaging.compiler.ccompiler` --- CCompiler base class -============================================================ - -.. module:: packaging.compiler.ccompiler - :synopsis: Abstract CCompiler class. - - -This module provides the abstract base class for the :class:`CCompiler` -classes. A :class:`CCompiler` instance can be used for all the compile and -link steps needed to build a single project. Methods are provided to set -options for the compiler --- macro definitions, include directories, link path, -libraries and the like. - -.. class:: CCompiler([verbose=0, dry_run=0, force=0]) - - The abstract base class :class:`CCompiler` defines the interface that must be - implemented by real compiler classes. The class also has some utility - methods used by several compiler classes. - - The basic idea behind a compiler abstraction class is that each instance can - be used for all the compile/link steps in building a single project. Thus, - attributes common to all of those compile and link steps --- include - directories, macros to define, libraries to link against, etc. --- are - attributes of the compiler instance. To allow for variability in how - individual files are treated, most of those attributes may be varied on a - per-compilation or per-link basis. - - The constructor for each subclass creates an instance of the Compiler object. - Flags are *verbose* (show verbose output), *dry_run* (don't actually execute - the steps) and *force* (rebuild everything, regardless of dependencies). All - of these flags default to ``0`` (off). Note that you probably don't want to - instantiate :class:`CCompiler` or one of its subclasses directly - use the - :func:`packaging.CCompiler.new_compiler` factory function instead. - - The following methods allow you to manually alter compiler options for the - instance of the Compiler class. - - - .. method:: CCompiler.add_include_dir(dir) - - Add *dir* to the list of directories that will be searched for header - files. The compiler is instructed to search directories in the order in - which they are supplied by successive calls to :meth:`add_include_dir`. - - - .. method:: CCompiler.set_include_dirs(dirs) - - Set the list of directories that will be searched to *dirs* (a list of - strings). Overrides any preceding calls to :meth:`add_include_dir`; - subsequent calls to :meth:`add_include_dir` add to the list passed to - :meth:`set_include_dirs`. This does not affect any list of standard - include directories that the compiler may search by default. - - - .. method:: CCompiler.add_library(libname) - - Add *libname* to the list of libraries that will be included in all links - driven by this compiler object. Note that *libname* should *not* be the - name of a file containing a library, but the name of the library itself: - the actual filename will be inferred by the linker, the compiler, or the - compiler class (depending on the platform). - - The linker will be instructed to link against libraries in the order they - were supplied to :meth:`add_library` and/or :meth:`set_libraries`. It is - perfectly valid to duplicate library names; the linker will be instructed - to link against libraries as many times as they are mentioned. - - - .. method:: CCompiler.set_libraries(libnames) - - Set the list of libraries to be included in all links driven by this - compiler object to *libnames* (a list of strings). This does not affect - any standard system libraries that the linker may include by default. - - - .. method:: CCompiler.add_library_dir(dir) - - Add *dir* to the list of directories that will be searched for libraries - specified to :meth:`add_library` and :meth:`set_libraries`. The linker - will be instructed to search for libraries in the order they are supplied - to :meth:`add_library_dir` and/or :meth:`set_library_dirs`. - - - .. method:: CCompiler.set_library_dirs(dirs) - - Set the list of library search directories to *dirs* (a list of strings). - This does not affect any standard library search path that the linker may - search by default. - - - .. method:: CCompiler.add_runtime_library_dir(dir) - - Add *dir* to the list of directories that will be searched for shared - libraries at runtime. - - - .. method:: CCompiler.set_runtime_library_dirs(dirs) - - Set the list of directories to search for shared libraries at runtime to - *dirs* (a list of strings). This does not affect any standard search path - that the runtime linker may search by default. - - - .. method:: CCompiler.define_macro(name[, value=None]) - - Define a preprocessor macro for all compilations driven by this compiler - object. The optional parameter *value* should be a string; if it is not - supplied, then the macro will be defined without an explicit value and the - exact outcome depends on the compiler used (XXX true? does ANSI say - anything about this?) - - - .. method:: CCompiler.undefine_macro(name) - - Undefine a preprocessor macro for all compilations driven by this compiler - object. If the same macro is defined by :meth:`define_macro` and - undefined by :meth:`undefine_macro` the last call takes precedence - (including multiple redefinitions or undefinitions). If the macro is - redefined/undefined on a per-compilation basis (i.e. in the call to - :meth:`compile`), then that takes precedence. - - - .. method:: CCompiler.add_link_object(object) - - Add *object* to the list of object files (or analogues, such as explicitly - named library files or the output of "resource compilers") to be included - in every link driven by this compiler object. - - - .. method:: CCompiler.set_link_objects(objects) - - Set the list of object files (or analogues) to be included in every link - to *objects*. This does not affect any standard object files that the - linker may include by default (such as system libraries). - - The following methods implement methods for autodetection of compiler - options, providing some functionality similar to GNU :program:`autoconf`. - - - .. method:: CCompiler.detect_language(sources) - - Detect the language of a given file, or list of files. Uses the instance - attributes :attr:`language_map` (a dictionary), and :attr:`language_order` - (a list) to do the job. - - - .. method:: CCompiler.find_library_file(dirs, lib[, debug=0]) - - Search the specified list of directories for a static or shared library file - *lib* and return the full path to that file. If *debug* is true, look for a - debugging version (if that makes sense on the current platform). Return - ``None`` if *lib* wasn't found in any of the specified directories. - - - .. method:: CCompiler.has_function(funcname [, includes=None, include_dirs=None, libraries=None, library_dirs=None]) - - Return a boolean indicating whether *funcname* is supported on the current - platform. The optional arguments can be used to augment the compilation - environment by providing additional include files and paths and libraries and - paths. - - - .. method:: CCompiler.library_dir_option(dir) - - Return the compiler option to add *dir* to the list of directories searched for - libraries. - - - .. method:: CCompiler.library_option(lib) - - Return the compiler option to add *dir* to the list of libraries linked into the - shared library or executable. - - - .. method:: CCompiler.runtime_library_dir_option(dir) - - Return the compiler option to add *dir* to the list of directories searched for - runtime libraries. - - - .. method:: CCompiler.set_executables(**args) - - Define the executables (and options for them) that will be run to perform the - various stages of compilation. The exact set of executables that may be - specified here depends on the compiler class (via the 'executables' class - attribute), but most will have: - - +--------------+------------------------------------------+ - | attribute | description | - +==============+==========================================+ - | *compiler* | the C/C++ compiler | - +--------------+------------------------------------------+ - | *linker_so* | linker used to create shared objects and | - | | libraries | - +--------------+------------------------------------------+ - | *linker_exe* | linker used to create binary executables | - +--------------+------------------------------------------+ - | *archiver* | static library creator | - +--------------+------------------------------------------+ - - On platforms with a command line (Unix, DOS/Windows), each of these is a string - that will be split into executable name and (optional) list of arguments. - (Splitting the string is done similarly to how Unix shells operate: words are - delimited by spaces, but quotes and backslashes can override this. See - :func:`packaging.util.split_quoted`.) - - The following methods invoke stages in the build process. - - - .. method:: CCompiler.compile(sources[, output_dir=None, macros=None, include_dirs=None, debug=0, extra_preargs=None, extra_postargs=None, depends=None]) - - Compile one or more source files. Generates object files (e.g. transforms a - :file:`.c` file to a :file:`.o` file.) - - *sources* must be a list of filenames, most likely C/C++ files, but in reality - anything that can be handled by a particular compiler and compiler class (e.g. - an ``'msvc'`` compiler` can handle resource files in *sources*). Return a list of - object filenames, one per source filename in *sources*. Depending on the - implementation, not all source files will necessarily be compiled, but all - corresponding object filenames will be returned. - - If *output_dir* is given, object files will be put under it, while retaining - their original path component. That is, :file:`foo/bar.c` normally compiles to - :file:`foo/bar.o` (for a Unix implementation); if *output_dir* is *build*, then - it would compile to :file:`build/foo/bar.o`. - - *macros*, if given, must be a list of macro definitions. A macro definition is - either a ``(name, value)`` 2-tuple or a ``(name,)`` 1-tuple. The former defines - a macro; if the value is ``None``, the macro is defined without an explicit - value. The 1-tuple case undefines a macro. Later - definitions/redefinitions/undefinitions take precedence. - - *include_dirs*, if given, must be a list of strings, the directories to add to - the default include file search path for this compilation only. - - *debug* is a boolean; if true, the compiler will be instructed to output debug - symbols in (or alongside) the object file(s). - - *extra_preargs* and *extra_postargs* are implementation-dependent. On platforms - that have the notion of a command line (e.g. Unix, DOS/Windows), they are most - likely lists of strings: extra command-line arguments to prepend/append to the - compiler command line. On other platforms, consult the implementation class - documentation. In any event, they are intended as an escape hatch for those - occasions when the abstract compiler framework doesn't cut the mustard. - - *depends*, if given, is a list of filenames that all targets depend on. If a - source file is older than any file in depends, then the source file will be - recompiled. This supports dependency tracking, but only at a coarse - granularity. - - Raises :exc:`CompileError` on failure. - - - .. method:: CCompiler.create_static_lib(objects, output_libname[, output_dir=None, debug=0, target_lang=None]) - - Link a bunch of stuff together to create a static library file. The "bunch of - stuff" consists of the list of object files supplied as *objects*, the extra - object files supplied to :meth:`add_link_object` and/or - :meth:`set_link_objects`, the libraries supplied to :meth:`add_library` and/or - :meth:`set_libraries`, and the libraries supplied as *libraries* (if any). - - *output_libname* should be a library name, not a filename; the filename will be - inferred from the library name. *output_dir* is the directory where the library - file will be put. XXX defaults to what? - - *debug* is a boolean; if true, debugging information will be included in the - library (note that on most platforms, it is the compile step where this matters: - the *debug* flag is included here just for consistency). - - *target_lang* is the target language for which the given objects are being - compiled. This allows specific linkage time treatment of certain languages. - - Raises :exc:`LibError` on failure. - - - .. method:: CCompiler.link(target_desc, objects, output_filename[, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None]) - - Link a bunch of stuff together to create an executable or shared library file. - - The "bunch of stuff" consists of the list of object files supplied as *objects*. - *output_filename* should be a filename. If *output_dir* is supplied, - *output_filename* is relative to it (i.e. *output_filename* can provide - directory components if needed). - - *libraries* is a list of libraries to link against. These are library names, - not filenames, since they're translated into filenames in a platform-specific - way (e.g. *foo* becomes :file:`libfoo.a` on Unix and :file:`foo.lib` on - DOS/Windows). However, they can include a directory component, which means the - linker will look in that specific directory rather than searching all the normal - locations. - - *library_dirs*, if supplied, should be a list of directories to search for - libraries that were specified as bare library names (i.e. no directory - component). These are on top of the system default and those supplied to - :meth:`add_library_dir` and/or :meth:`set_library_dirs`. *runtime_library_dirs* - is a list of directories that will be embedded into the shared library and used - to search for other shared libraries that \*it\* depends on at run-time. (This - may only be relevant on Unix.) - - *export_symbols* is a list of symbols that the shared library will export. - (This appears to be relevant only on Windows.) - - *debug* is as for :meth:`compile` and :meth:`create_static_lib`, with the - slight distinction that it actually matters on most platforms (as opposed to - :meth:`create_static_lib`, which includes a *debug* flag mostly for form's - sake). - - *extra_preargs* and *extra_postargs* are as for :meth:`compile` (except of - course that they supply command-line arguments for the particular linker being - used). - - *target_lang* is the target language for which the given objects are being - compiled. This allows specific linkage time treatment of certain languages. - - Raises :exc:`LinkError` on failure. - - - .. method:: CCompiler.link_executable(objects, output_progname[, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, debug=0, extra_preargs=None, extra_postargs=None, target_lang=None]) - - Link an executable. *output_progname* is the name of the file executable, while - *objects* are a list of object filenames to link in. Other arguments are as for - the :meth:`link` method. - - - .. method:: CCompiler.link_shared_lib(objects, output_libname[, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None]) - - Link a shared library. *output_libname* is the name of the output library, - while *objects* is a list of object filenames to link in. Other arguments are - as for the :meth:`link` method. - - - .. method:: CCompiler.link_shared_object(objects, output_filename[, output_dir=None, libraries=None, library_dirs=None, runtime_library_dirs=None, export_symbols=None, debug=0, extra_preargs=None, extra_postargs=None, build_temp=None, target_lang=None]) - - Link a shared object. *output_filename* is the name of the shared object that - will be created, while *objects* is a list of object filenames to link in. - Other arguments are as for the :meth:`link` method. - - - .. method:: CCompiler.preprocess(source[, output_file=None, macros=None, include_dirs=None, extra_preargs=None, extra_postargs=None]) - - Preprocess a single C/C++ source file, named in *source*. Output will be written - to file named *output_file*, or *stdout* if *output_file* not supplied. - *macros* is a list of macro definitions as for :meth:`compile`, which will - augment the macros set with :meth:`define_macro` and :meth:`undefine_macro`. - *include_dirs* is a list of directory names that will be added to the default - list, in the same way as :meth:`add_include_dir`. - - Raises :exc:`PreprocessError` on failure. - - The following utility methods are defined by the :class:`CCompiler` class, for - use by the various concrete subclasses. - - - .. method:: CCompiler.executable_filename(basename[, strip_dir=0, output_dir='']) - - Returns the filename of the executable for the given *basename*. Typically for - non-Windows platforms this is the same as the basename, while Windows will get - a :file:`.exe` added. - - - .. method:: CCompiler.library_filename(libname[, lib_type='static', strip_dir=0, output_dir='']) - - Returns the filename for the given library name on the current platform. On Unix - a library with *lib_type* of ``'static'`` will typically be of the form - :file:`liblibname.a`, while a *lib_type* of ``'dynamic'`` will be of the form - :file:`liblibname.so`. - - - .. method:: CCompiler.object_filenames(source_filenames[, strip_dir=0, output_dir='']) - - Returns the name of the object files for the given source files. - *source_filenames* should be a list of filenames. - - - .. method:: CCompiler.shared_object_filename(basename[, strip_dir=0, output_dir='']) - - Returns the name of a shared object file for the given file name *basename*. - - - .. method:: CCompiler.execute(func, args[, msg=None, level=1]) - - Invokes :func:`packaging.util.execute` This method invokes a Python function - *func* with the given arguments *args*, after logging and taking into account - the *dry_run* flag. XXX see also. - - - .. method:: CCompiler.spawn(cmd) - - Invokes :func:`packaging.util.spawn`. This invokes an external process to run - the given command. XXX see also. - - - .. method:: CCompiler.mkpath(name[, mode=511]) - - Invokes :func:`packaging.dir_util.mkpath`. This creates a directory and any - missing ancestor directories. XXX see also. - - - .. method:: CCompiler.move_file(src, dst) - - Invokes :meth:`packaging.file_util.move_file`. Renames *src* to *dst*. XXX see - also. - - -:mod:`packaging.compiler.extension` --- The Extension class -=========================================================== - -.. module:: packaging.compiler.extension - :synopsis: Class used to represent C/C++ extension modules. - - -This module provides the :class:`Extension` class, used to represent C/C++ -extension modules. - -.. class:: Extension - - The Extension class describes a single C or C++ extension module. It accepts - the following keyword arguments in its constructor: - - +------------------------+--------------------------------+---------------------------+ - | argument name | value | type [#]_ | - +========================+================================+===========================+ - | *name* | the full name of the | string | - | | extension, including any | | - | | packages --- i.e. *not* a | | - | | filename or pathname, but | | - | | Python dotted name | | - +------------------------+--------------------------------+---------------------------+ - | *sources* | list of source filenames, | string | - | | relative to the distribution | | - | | root (where the setup script | | - | | lives), in Unix form (slash- | | - | | separated) for portability. | | - | | Source files may be C, C++, | | - | | SWIG (.i), platform-specific | | - | | resource files, or whatever | | - | | else is recognized by the | | - | | :command:`build_ext` command | | - | | as source for a Python | | - | | extension. | | - +------------------------+--------------------------------+---------------------------+ - | *include_dirs* | list of directories to search | string | - | | for C/C++ header files (in | | - | | Unix form for portability) | | - +------------------------+--------------------------------+---------------------------+ - | *define_macros* | list of macros to define; each | (string, string) tuple or | - | | macro is defined using a | (name, ``None``) | - | | 2-tuple ``(name, value)``, | | - | | where *value* is | | - | | either the string to define it | | - | | to or ``None`` to define it | | - | | without a particular value | | - | | (equivalent of ``#define FOO`` | | - | | in source or :option:`-DFOO` | | - | | on Unix C compiler command | | - | | line) | | - +------------------------+--------------------------------+---------------------------+ - | *undef_macros* | list of macros to undefine | string | - | | explicitly | | - +------------------------+--------------------------------+---------------------------+ - | *library_dirs* | list of directories to search | string | - | | for C/C++ libraries at link | | - | | time | | - +------------------------+--------------------------------+---------------------------+ - | *libraries* | list of library names (not | string | - | | filenames or paths) to link | | - | | against | | - +------------------------+--------------------------------+---------------------------+ - | *runtime_library_dirs* | list of directories to search | string | - | | for C/C++ libraries at run | | - | | time (for shared extensions, | | - | | this is when the extension is | | - | | loaded) | | - +------------------------+--------------------------------+---------------------------+ - | *extra_objects* | list of extra files to link | string | - | | with (e.g. object files not | | - | | implied by 'sources', static | | - | | library that must be | | - | | explicitly specified, binary | | - | | resource files, etc.) | | - +------------------------+--------------------------------+---------------------------+ - | *extra_compile_args* | any extra platform- and | string | - | | compiler-specific information | | - | | to use when compiling the | | - | | source files in 'sources'. For | | - | | platforms and compilers where | | - | | a command line makes sense, | | - | | this is typically a list of | | - | | command-line arguments, but | | - | | for other platforms it could | | - | | be anything. | | - +------------------------+--------------------------------+---------------------------+ - | *extra_link_args* | any extra platform- and | string | - | | compiler-specific information | | - | | to use when linking object | | - | | files together to create the | | - | | extension (or to create a new | | - | | static Python interpreter). | | - | | Similar interpretation as for | | - | | 'extra_compile_args'. | | - +------------------------+--------------------------------+---------------------------+ - | *export_symbols* | list of symbols to be exported | string | - | | from a shared extension. Not | | - | | used on all platforms, and not | | - | | generally necessary for Python | | - | | extensions, which typically | | - | | export exactly one symbol: | | - | | ``init`` + extension_name. | | - +------------------------+--------------------------------+---------------------------+ - | *depends* | list of files that the | string | - | | extension depends on | | - +------------------------+--------------------------------+---------------------------+ - | *language* | extension language (i.e. | string | - | | ``'c'``, ``'c++'``, | | - | | ``'objc'``). Will be detected | | - | | from the source extensions if | | - | | not provided. | | - +------------------------+--------------------------------+---------------------------+ - -.. [#] For values documented as lists, the given type is the type of each element. diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.database.rst --- a/Doc/library/packaging.database.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,324 +0,0 @@ -:mod:`packaging.database` --- Database of installed distributions -================================================================= - -.. module:: packaging.database - :synopsis: Functions to query and manipulate installed distributions. - - -This module provides an implementation of :PEP:`376`. It was originally -intended to land in :mod:`pkgutil`, but with the inclusion of Packaging in the -standard library, it was thought best to include it in a submodule of -:mod:`packaging`, leaving :mod:`pkgutil` to deal with imports. - -Installed Python distributions are represented by instances of -:class:`Distribution`, or :class:`EggInfoDistribution` for legacy egg formats. -Most functions also provide an extra argument ``use_egg_info`` to take legacy -distributions into account. - - -Classes representing installed distributions --------------------------------------------- - -.. class:: Distribution(path) - - Class representing an installed distribution. It is different from - :class:`packaging.dist.Distribution` which holds the list of files, the - metadata and options during the run of a Packaging command. - - Instantiate with the *path* to a ``.dist-info`` directory. Instances can be - compared and sorted. Other available methods are: - - .. XXX describe how comparison works - - .. method:: get_distinfo_file(path, binary=False) - - Return a read-only file object for a file located at - :file:`{project-version}.dist-info/path}`. *path* should be a - ``'/'``-separated path relative to the ``.dist-info`` directory or an - absolute path; if it is an absolute path and doesn't start with the path - to the :file:`.dist-info` directory, a :class:`PackagingError` is raised. - - If *binary* is ``True``, the file is opened in binary mode. - - .. method:: get_resource_path(relative_path) - - .. TODO - - .. method:: list_distinfo_files(local=False) - - Return an iterator over all files located in the :file:`.dist-info` - directory. If *local* is ``True``, each returned path is transformed into - a local absolute path, otherwise the raw value found in the :file:`RECORD` - file is returned. - - .. method:: list_installed_files(local=False) - - Iterate over the files installed with the distribution and registered in - the :file:`RECORD` file and yield a tuple ``(path, md5, size)`` for each - line. If *local* is ``True``, the returned path is transformed into a - local absolute path, otherwise the raw value is returned. - - A local absolute path is an absolute path in which occurrences of ``'/'`` - have been replaced by :data:`os.sep`. - - .. method:: uses(path) - - Check whether *path* was installed by this distribution (i.e. if the path - is present in the :file:`RECORD` file). *path* can be a local absolute - path or a relative ``'/'``-separated path. Returns a boolean. - - Available attributes: - - .. attribute:: metadata - - Instance of :class:`packaging.metadata.Metadata` filled with the contents - of the :file:`{project-version}.dist-info/METADATA` file. - - .. attribute:: name - - Shortcut for ``metadata['Name']``. - - .. attribute:: version - - Shortcut for ``metadata['Version']``. - - .. attribute:: requested - - Boolean indicating whether this distribution was requested by the user of - automatically installed as a dependency. - - -.. class:: EggInfoDistribution(path) - - Class representing a legacy distribution. It is compatible with distutils' - and setuptools' :file:`.egg-info` and :file:`.egg` files and directories. - - .. FIXME should be named EggDistribution - - Instantiate with the *path* to an egg file or directory. Instances can be - compared and sorted. Other available methods are: - - .. method:: list_installed_files(local=False) - - .. method:: uses(path) - - Available attributes: - - .. attribute:: metadata - - Instance of :class:`packaging.metadata.Metadata` filled with the contents - of the :file:`{project-version}.egg-info/PKG-INFO` or - :file:`{project-version}.egg` file. - - .. attribute:: name - - Shortcut for ``metadata['Name']``. - - .. attribute:: version - - Shortcut for ``metadata['Version']``. - - -Functions to work with the database ------------------------------------ - -.. function:: get_distribution(name, use_egg_info=False, paths=None) - - Return an instance of :class:`Distribution` or :class:`EggInfoDistribution` - for the first installed distribution matching *name*. Egg distributions are - considered only if *use_egg_info* is true; if both a dist-info and an egg - file are found, the dist-info prevails. The directories to be searched are - given in *paths*, which defaults to :data:`sys.path`. Return ``None`` if no - matching distribution is found. - - .. FIXME param should be named use_egg - - -.. function:: get_distributions(use_egg_info=False, paths=None) - - Return an iterator of :class:`Distribution` instances for all installed - distributions found in *paths* (defaults to :data:`sys.path`). If - *use_egg_info* is true, also return instances of :class:`EggInfoDistribution` - for legacy distributions found. - - -.. function:: get_file_users(path) - - Return an iterator over all distributions using *path*, a local absolute path - or a relative ``'/'``-separated path. - - .. XXX does this work with prefixes or full file path only? - - -.. function:: obsoletes_distribution(name, version=None, use_egg_info=False) - - Return an iterator over all distributions that declare they obsolete *name*. - *version* is an optional argument to match only specific releases (see - :mod:`packaging.version`). If *use_egg_info* is true, legacy egg - distributions will be considered as well. - - -.. function:: provides_distribution(name, version=None, use_egg_info=False) - - Return an iterator over all distributions that declare they provide *name*. - *version* is an optional argument to match only specific releases (see - :mod:`packaging.version`). If *use_egg_info* is true, legacy egg - distributions will be considered as well. - - -Utility functions ------------------ - -.. function:: distinfo_dirname(name, version) - - Escape *name* and *version* into a filename-safe form and return the - directory name built from them, for example - :file:`{safename}-{safeversion}.dist-info.` In *name*, runs of - non-alphanumeric characters are replaced with one ``'_'``; in *version*, - spaces become dots, and runs of other non-alphanumeric characters (except - dots) a replaced by one ``'-'``. - - .. XXX wth spaces in version numbers? - -For performance purposes, the list of distributions is being internally -cached. Caching is enabled by default, but you can control it with these -functions: - -.. function:: clear_cache() - - Clear the cache. - -.. function:: disable_cache() - - Disable the cache, without clearing it. - -.. function:: enable_cache() - - Enable the internal cache, without clearing it. - - -Examples --------- - -Print all information about a distribution -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Given a path to a ``.dist-info`` distribution, we shall print out all -information that can be obtained using functions provided in this module:: - - import sys - import packaging.database - - path = input() - # first create the Distribution instance - try: - dist = packaging.database.Distribution(path) - except IOError: - sys.exit('No such distribution') - - print('Information about %r' % dist.name) - print() - - print('Files') - print('=====') - for path, md5, size in dist.list_installed_files(): - print('* Path: %s' % path) - print(' Hash %s, Size: %s bytes' % (md5, size)) - print() - - print('Metadata') - print('========') - for key, value in dist.metadata.items(): - print('%20s: %s' % (key, value)) - print() - - print('Extra') - print('=====') - if dist.requested: - print('* It was installed by user request') - else: - print('* It was installed as a dependency') - -If we save the script above as ``print_info.py``, we can use it to extract -information from a :file:`.dist-info` directory. By typing in the console: - -.. code-block:: sh - - $ echo /tmp/choxie/choxie-2.0.0.9.dist-info | python3 print_info.py - -we get the following output: - -.. code-block:: none - - Information about 'choxie' - - Files - ===== - * Path: ../tmp/distutils2/tests/fake_dists/choxie-2.0.0.9/truffles.py - Hash 5e052db6a478d06bad9ae033e6bc08af, Size: 111 bytes - * Path: ../tmp/distutils2/tests/fake_dists/choxie-2.0.0.9/choxie/chocolate.py - Hash ac56bf496d8d1d26f866235b95f31030, Size: 214 bytes - * Path: ../tmp/distutils2/tests/fake_dists/choxie-2.0.0.9/choxie/__init__.py - Hash 416aab08dfa846f473129e89a7625bbc, Size: 25 bytes - * Path: ../tmp/distutils2/tests/fake_dists/choxie-2.0.0.9.dist-info/INSTALLER - Hash d41d8cd98f00b204e9800998ecf8427e, Size: 0 bytes - * Path: ../tmp/distutils2/tests/fake_dists/choxie-2.0.0.9.dist-info/METADATA - Hash 696a209967fef3c8b8f5a7bb10386385, Size: 225 bytes - * Path: ../tmp/distutils2/tests/fake_dists/choxie-2.0.0.9.dist-info/REQUESTED - Hash d41d8cd98f00b204e9800998ecf8427e, Size: 0 bytes - * Path: ../tmp/distutils2/tests/fake_dists/choxie-2.0.0.9.dist-info/RECORD - Hash None, Size: None bytes - - Metadata - ======== - Metadata-Version: 1.2 - Name: choxie - Version: 2.0.0.9 - Platform: [] - Supported-Platform: UNKNOWN - Summary: Chocolate with a kick! - Description: UNKNOWN - Keywords: [] - Home-page: UNKNOWN - Author: UNKNOWN - Author-email: UNKNOWN - Maintainer: UNKNOWN - Maintainer-email: UNKNOWN - License: UNKNOWN - Classifier: [] - Download-URL: UNKNOWN - Obsoletes-Dist: ['truffles (<=0.8,>=0.5)', 'truffles (<=0.9,>=0.6)'] - Project-URL: [] - Provides-Dist: ['truffles (1.0)'] - Requires-Dist: ['towel-stuff (0.1)'] - Requires-Python: UNKNOWN - Requires-External: [] - - Extra - ===== - * It was installed as a dependency - - -Find out obsoleted distributions -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Now, we take tackle a different problem, we are interested in finding out -which distributions have been obsoleted. This can be easily done as follows:: - - import packaging.database - - # iterate over all distributions in the system - for dist in packaging.database.get_distributions(): - name, version = dist.name, dist.version - # find out which distributions obsolete this name/version combination - replacements = packaging.database.obsoletes_distribution(name, version) - if replacements: - print('%r %s is obsoleted by' % (name, version), - ', '.join(repr(r.name) for r in replacements)) - -This is how the output might look like: - -.. code-block:: none - - 'strawberry' 0.6 is obsoleted by 'choxie' - 'grammar' 1.0a4 is obsoleted by 'towel-stuff' diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.depgraph.rst --- a/Doc/library/packaging.depgraph.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,199 +0,0 @@ -:mod:`packaging.depgraph` --- Dependency graph builder -====================================================== - -.. module:: packaging.depgraph - :synopsis: Graph builder for dependencies between releases. - - -This module provides the means to analyse the dependencies between various -distributions and to create a graph representing these dependency relationships. -In this document, "distribution" refers to an instance of -:class:`packaging.database.Distribution` or -:class:`packaging.database.EggInfoDistribution`. - -.. XXX terminology problem with dist vs. release: dists are installed, but deps - use releases - -.. XXX explain how to use it with dists not installed: Distribution can only be - instantiated with a path, but this module is useful for remote dist too - -.. XXX functions should accept and return iterators, not lists - - -The :class:`DependencyGraph` class ----------------------------------- - -.. class:: DependencyGraph - - Represent a dependency graph between releases. The nodes are distribution - instances; the edge model dependencies. An edge from ``a`` to ``b`` means - that ``a`` depends on ``b``. - - .. method:: add_distribution(distribution) - - Add *distribution* to the graph. - - .. method:: add_edge(x, y, label=None) - - Add an edge from distribution *x* to distribution *y* with the given - *label* (string). - - .. method:: add_missing(distribution, requirement) - - Add a missing *requirement* (string) for the given *distribution*. - - .. method:: repr_node(dist, level=1) - - Print a subgraph starting from *dist*. *level* gives the depth of the - subgraph. - - Direct access to the graph nodes and edges is provided through these - attributes: - - .. attribute:: adjacency_list - - Dictionary mapping distributions to a list of ``(other, label)`` tuples - where ``other`` is a distribution and the edge is labeled with ``label`` - (i.e. the version specifier, if such was provided). - - .. attribute:: reverse_list - - Dictionary mapping distributions to a list of predecessors. This allows - efficient traversal. - - .. attribute:: missing - - Dictionary mapping distributions to a list of requirements that were not - provided by any distribution. - - -Auxiliary functions -------------------- - -.. function:: dependent_dists(dists, dist) - - Recursively generate a list of distributions from *dists* that are dependent - on *dist*. - - .. XXX what does member mean here: "dist is a member of *dists* for which we - are interested" - -.. function:: generate_graph(dists) - - Generate a :class:`DependencyGraph` from the given list of distributions. - - .. XXX make this alternate constructor a DepGraph classmethod or rename; - 'generate' can suggest it creates a file or an image, use 'make' - -.. function:: graph_to_dot(graph, f, skip_disconnected=True) - - Write a DOT output for the graph to the file-like object *f*. - - If *skip_disconnected* is true, all distributions that are not dependent on - any other distribution are skipped. - - .. XXX why is this not a DepGraph method? - - -Example Usage -------------- - -Depict all dependenciess in the system -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -First, we shall generate a graph of all the distributions on the system -and then create an image out of it using the tools provided by -`Graphviz `_:: - - from packaging.database import get_distributions - from packaging.depgraph import generate_graph - - dists = list(get_distributions()) - graph = generate_graph(dists) - -It would be interesting to print out the missing requirements. This can be done -as follows:: - - for dist, reqs in graph.missing.items(): - if reqs: - reqs = ' ,'.join(repr(req) for req in reqs) - print('Missing dependencies for %r: %s' % (dist.name, reqs)) - -Example output is: - -.. code-block:: none - - Missing dependencies for 'TurboCheetah': 'Cheetah' - Missing dependencies for 'TurboGears': 'ConfigObj', 'DecoratorTools', 'RuleDispatch' - Missing dependencies for 'jockey': 'PyKDE4.kdecore', 'PyKDE4.kdeui', 'PyQt4.QtCore', 'PyQt4.QtGui' - Missing dependencies for 'TurboKid': 'kid' - Missing dependencies for 'TurboJson: 'DecoratorTools', 'RuleDispatch' - -Now, we proceed with generating a graphical representation of the graph. First -we write it to a file, and then we generate a PNG image using the -:program:`dot` command-line tool:: - - from packaging.depgraph import graph_to_dot - with open('output.dot', 'w') as f: - # only show the interesting distributions, skipping the disconnected ones - graph_to_dot(graph, f, skip_disconnected=True) - -We can create the final picture using: - -.. code-block:: sh - - $ dot -Tpng output.dot > output.png - -An example result is: - -.. figure:: depgraph-output.png - :alt: Example PNG output from packaging.depgraph and dot - -If you want to include egg distributions as well, then the code requires only -one change, namely the line:: - - dists = list(packaging.database.get_distributions()) - -has to be replaced with:: - - dists = list(packaging.database.get_distributions(use_egg_info=True)) - -On many platforms, a richer graph is obtained because at the moment most -distributions are provided in the egg rather than the new standard -``.dist-info`` format. - -.. XXX missing image - - An example of a more involved graph for illustrative reasons can be seen - here: - - .. image:: depgraph_big.png - - -List all dependent distributions -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -We will list all distributions that are dependent on some given distibution. -This time, egg distributions will be considered as well:: - - import sys - from packaging.database import get_distribution, get_distributions - from packaging.depgraph import dependent_dists - - dists = list(get_distributions(use_egg_info=True)) - dist = get_distribution('bacon', use_egg_info=True) - if dist is None: - sys.exit('No such distribution in the system') - - deps = dependent_dists(dists, dist) - deps = ', '.join(repr(x.name) for x in deps) - print('Distributions depending on %r: %s' % (dist.name, deps)) - -And this is example output: - -.. with the dependency relationships as in the previous section - (depgraph_big) - -.. code-block:: none - - Distributions depending on 'bacon': 'towel-stuff', 'choxie', 'grammar' diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.dist.rst --- a/Doc/library/packaging.dist.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,102 +0,0 @@ -:mod:`packaging.dist` --- The Distribution class -================================================ - -.. module:: packaging.dist - :synopsis: Core Distribution class. - - -This module provides the :class:`Distribution` class, which represents the -module distribution being built/packaged/distributed/installed. - -.. class:: Distribution(arguments) - - A :class:`Distribution` describes how to build, package, distribute and - install a Python project. - - The arguments accepted by the constructor are laid out in the following - table. Some of them will end up in a metadata object, the rest will become - data attributes of the :class:`Distribution` instance. - - .. TODO improve constructor to take a Metadata object + named params? - (i.e. Distribution(metadata, cmdclass, py_modules, etc) - .. TODO also remove obsolete(?) script_name, etc. parameters? see what - py2exe and other tools need - - +--------------------+--------------------------------+-------------------------------------------------------------+ - | argument name | value | type | - +====================+================================+=============================================================+ - | *name* | The name of the project | string | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *version* | The version number of the | See :mod:`packaging.version` | - | | release | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *summary* | A single line describing the | a string | - | | project | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *description* | Longer description of the | a string | - | | project | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *author* | The name of the project author | a string | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *author_email* | The email address of the | a string | - | | project author | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *maintainer* | The name of the current | a string | - | | maintainer, if different from | | - | | the author | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *maintainer_email* | The email address of the | | - | | current maintainer, if | | - | | different from the author | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *home_page* | A URL for the proejct | a URL | - | | (homepage) | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *download_url* | A URL to download the project | a URL | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *packages* | A list of Python packages that | a list of strings | - | | packaging will manipulate | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *py_modules* | A list of Python modules that | a list of strings | - | | packaging will manipulate | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *scripts* | A list of standalone scripts | a list of strings | - | | to be built and installed | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *ext_modules* | A list of Python extensions to | A list of instances of | - | | be built | :class:`packaging.compiler.extension.Extension` | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *classifiers* | A list of categories for the | The list of available | - | | distribution | categorizations is at | - | | | http://pypi.python.org/pypi?:action=list_classifiers. | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *distclass* | the :class:`Distribution` | A subclass of | - | | class to use | :class:`packaging.dist.Distribution` | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *script_name* | The name of the setup.py | a string | - | | script - defaults to | | - | | ``sys.argv[0]`` | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *script_args* | Arguments to supply to the | a list of strings | - | | setup script | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *options* | default options for the setup | a string | - | | script | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *license* | The license for the | a string; should be used when there is no suitable License | - | | distribution | classifier, or to specify a classifier | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *keywords* | Descriptive keywords | a list of strings; used by catalogs | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *platforms* | Platforms compatible with this | a list of strings; should be used when there is no | - | | distribution | suitable Platform classifier | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *cmdclass* | A mapping of command names to | a dictionary | - | | :class:`Command` subclasses | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *data_files* | A list of data files to | a list | - | | install | | - +--------------------+--------------------------------+-------------------------------------------------------------+ - | *package_dir* | A mapping of Python packages | a dictionary | - | | to directory names | | - +--------------------+--------------------------------+-------------------------------------------------------------+ diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.fancy_getopt.rst --- a/Doc/library/packaging.fancy_getopt.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -:mod:`packaging.fancy_getopt` --- Wrapper around the getopt module -================================================================== - -.. module:: packaging.fancy_getopt - :synopsis: Additional getopt functionality. - - -.. warning:: - This module is deprecated and will be replaced with :mod:`optparse`. - -This module provides a wrapper around the standard :mod:`getopt` module that -provides the following additional features: - -* short and long options are tied together - -* options have help strings, so :func:`fancy_getopt` could potentially create a - complete usage summary - -* options set attributes of a passed-in object - -* boolean options can have "negative aliases" --- e.g. if :option:`--quiet` is - the "negative alias" of :option:`--verbose`, then :option:`--quiet` on the - command line sets *verbose* to false. - -.. function:: fancy_getopt(options, negative_opt, object, args) - - Wrapper function. *options* is a list of ``(long_option, short_option, - help_string)`` 3-tuples as described in the constructor for - :class:`FancyGetopt`. *negative_opt* should be a dictionary mapping option names - to option names, both the key and value should be in the *options* list. - *object* is an object which will be used to store values (see the :meth:`getopt` - method of the :class:`FancyGetopt` class). *args* is the argument list. Will use - ``sys.argv[1:]`` if you pass ``None`` as *args*. - - -.. class:: FancyGetopt([option_table=None]) - - The option_table is a list of 3-tuples: ``(long_option, short_option, - help_string)`` - - If an option takes an argument, its *long_option* should have ``'='`` appended; - *short_option* should just be a single character, no ``':'`` in any case. - *short_option* should be ``None`` if a *long_option* doesn't have a - corresponding *short_option*. All option tuples must have long options. - -The :class:`FancyGetopt` class provides the following methods: - - -.. method:: FancyGetopt.getopt([args=None, object=None]) - - Parse command-line options in args. Store as attributes on *object*. - - If *args* is ``None`` or not supplied, uses ``sys.argv[1:]``. If *object* is - ``None`` or not supplied, creates a new :class:`OptionDummy` instance, stores - option values there, and returns a tuple ``(args, object)``. If *object* is - supplied, it is modified in place and :func:`getopt` just returns *args*; in - both cases, the returned *args* is a modified copy of the passed-in *args* list, - which is left untouched. - - .. TODO and args returned are? - - -.. method:: FancyGetopt.get_option_order() - - Returns the list of ``(option, value)`` tuples processed by the previous run of - :meth:`getopt` Raises :exc:`RuntimeError` if :meth:`getopt` hasn't been called - yet. - - -.. method:: FancyGetopt.generate_help([header=None]) - - Generate help text (a list of strings, one per suggested line of output) from - the option table for this :class:`FancyGetopt` object. - - If supplied, prints the supplied *header* at the top of the help. diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.install.rst --- a/Doc/library/packaging.install.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -:mod:`packaging.install` --- Installation tools -=============================================== - -.. module:: packaging.install - :synopsis: Download and installation building blocks - - -Packaging provides a set of tools to deal with downloads and installation of -distributions. Their role is to download the distribution from indexes, resolve -the dependencies, and provide a safe way to install distributions. An operation -that fails will cleanly roll back, not leave half-installed distributions on the -system. Here's the basic process followed: - -#. Move all distributions that will be removed to a temporary location. - -#. Install all the distributions that will be installed in a temporary location. - -#. If the installation fails, move the saved distributions back to their - location and delete the installed distributions. - -#. Otherwise, move the installed distributions to the right location and delete - the temporary locations. - -This is a higher-level module built on :mod:`packaging.database` and -:mod:`packaging.pypi`. - - -Public functions ----------------- - -.. function:: get_infos(requirements, index=None, installed=None, \ - prefer_final=True) - - Return information about what's going to be installed and upgraded. - *requirements* is a string string containing the requirements for this - project, for example ``'FooBar 1.1'`` or ``'BarBaz (<1.2)'``. - - .. XXX are requirements comma-separated? - - If you want to use another index than the main PyPI, give its URI as *index* - argument. - - *installed* is a list of already installed distributions used to find - satisfied dependencies, obsoleted distributions and eventual conflicts. - - By default, alpha, beta and candidate versions are not picked up. Set - *prefer_final* to false to accept them too. - - The results are returned in a dictionary containing all the information - needed to perform installation of the requirements with the - :func:`install_from_infos` function: - - >>> get_install_info("FooBar (<=1.2)") - {'install': [], 'remove': [], 'conflict': []} - - .. TODO should return tuple or named tuple, not dict - .. TODO use "predicate" or "requirement" consistently in version and here - .. FIXME "info" cannot be plural in English, s/infos/info/ - - -.. function:: install(project) - - -.. function:: install_dists(dists, path, paths=None) - - Safely install all distributions provided in *dists* into *path*. *paths* is - a list of paths where already-installed distributions will be looked for to - find satisfied dependencies and conflicts (default: :data:`sys.path`). - Returns a list of installed dists. - - .. FIXME dists are instances of what? - - -.. function:: install_from_infos(install_path=None, install=[], remove=[], \ - conflicts=[], paths=None) - - Safely install and remove given distributions. This function is designed to - work with the return value of :func:`get_infos`: *install*, *remove* and - *conflicts* should be list of distributions returned by :func:`get_infos`. - If *install* is not empty, *install_path* must be given to specify the path - where the distributions should be installed. *paths* is a list of paths - where already-installed distributions will be looked for (default: - :data:`sys.path`). - - This function is a very basic installer; if *conflicts* is not empty, the - system will be in a conflicting state after the function completes. It is a - building block for more sophisticated installers with conflict resolution - systems. - - .. TODO document typical value for install_path - .. TODO document integration with default schemes, esp. user site-packages - - -.. function:: install_local_project(path) - - Install a distribution from a source directory, which must contain either a - Packaging-compliant :file:`setup.cfg` file or a legacy Distutils - :file:`setup.py` script (in which case Distutils will be used under the hood - to perform the installation). - - -.. function:: remove(project_name, paths=None, auto_confirm=True) - - Remove one distribution from the system. - - .. FIXME this is the only function using "project" instead of dist/release - -.. - Example usage - -------------- - - Get the scheme of what's gonna be installed if we install "foobar": diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.metadata.rst --- a/Doc/library/packaging.metadata.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,122 +0,0 @@ -:mod:`packaging.metadata` --- Metadata handling -=============================================== - -.. module:: packaging.metadata - :synopsis: Class holding the metadata of a release. - - -.. TODO use sphinx-autogen to generate basic doc from the docstrings - -.. class:: Metadata - - This class can read and write metadata files complying with any of the - defined versions: 1.0 (:PEP:`241`), 1.1 (:PEP:`314`) and 1.2 (:PEP:`345`). It - implements methods to parse Metadata files and write them, and a mapping - interface to its contents. - - The :PEP:`345` implementation supports the micro-language for the environment - markers, and displays warnings when versions that are supposed to be - :PEP:`386`-compliant are violating the specification. - - -Reading metadata ----------------- - -The :class:`Metadata` class can be instantiated -with the path of the metadata file, and provides a dict-like interface to the -values:: - - >>> from packaging.metadata import Metadata - >>> metadata = Metadata('PKG-INFO') - >>> metadata.keys()[:5] - ('Metadata-Version', 'Name', 'Version', 'Platform', 'Supported-Platform') - >>> metadata['Name'] - 'CLVault' - >>> metadata['Version'] - '0.5' - >>> metadata['Requires-Dist'] - ["pywin32; sys.platform == 'win32'", "Sphinx"] - - -The fields that support environment markers can be automatically ignored if -the object is instantiated using the ``platform_dependent`` option. -:class:`Metadata` will interpret in this case -the markers and will automatically remove the fields that are not compliant -with the running environment. Here's an example under Mac OS X. The win32 -dependency we saw earlier is ignored:: - - >>> from packaging.metadata import Metadata - >>> metadata = Metadata('PKG-INFO', platform_dependent=True) - >>> metadata['Requires-Dist'] - ['Sphinx'] - - -If you want to provide your own execution context, let's say to test the -metadata under a particular environment that is not the current environment, -you can provide your own values in the ``execution_context`` option, which -is the dict that may contain one or more keys of the context the micro-language -expects. - -Here's an example, simulating a win32 environment:: - - >>> from packaging.metadata import Metadata - >>> context = {'sys.platform': 'win32'} - >>> metadata = Metadata('PKG-INFO', platform_dependent=True, - ... execution_context=context) - ... - >>> metadata['Requires-Dist'] = ["pywin32; sys.platform == 'win32'", - ... "Sphinx"] - ... - >>> metadata['Requires-Dist'] - ['pywin32', 'Sphinx'] - - -Writing metadata ----------------- - -Writing metadata can be done using the ``write`` method:: - - >>> metadata.write('/to/my/PKG-INFO') - -The class will pick the best version for the metadata, depending on the values -provided. If all the values provided exist in all versions, the class will -use :attr:`PKG_INFO_PREFERRED_VERSION`. It is set by default to 1.0, the most -widespread version. - - -Conflict checking and best version ----------------------------------- - -Some fields in :PEP:`345` have to comply with the version number specification -defined in :PEP:`386`. When they don't comply, a warning is emitted:: - - >>> from packaging.metadata import Metadata - >>> metadata = Metadata() - >>> metadata['Requires-Dist'] = ['Funky (Groovie)'] - "Funky (Groovie)" is not a valid predicate - >>> metadata['Requires-Dist'] = ['Funky (1.2)'] - -See also :mod:`packaging.version`. - - -.. TODO talk about check() - - -:mod:`packaging.markers` --- Environment markers -================================================ - -.. module:: packaging.markers - :synopsis: Micro-language for environment markers - - -This is an implementation of environment markers `as defined in PEP 345 -`_. It is used -for some metadata fields. - -.. function:: interpret(marker, execution_context=None) - - Interpret a marker and return a boolean result depending on the environment. - Example: - - >>> interpret("python_version > '1.0'") - True diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.pypi.dist.rst --- a/Doc/library/packaging.pypi.dist.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -:mod:`packaging.pypi.dist` --- Classes representing query results -================================================================= - -.. module:: packaging.pypi.dist - :synopsis: Classes representing the results of queries to indexes. - - -Information coming from the indexes is held in instances of the classes defined -in this module. - -Keep in mind that each project (eg. FooBar) can have several releases -(eg. 1.1, 1.2, 1.3), and each of these releases can be provided in multiple -distributions (eg. a source distribution, a binary one, etc). - - -ReleaseInfo ------------ - -Each release has a project name, version, metadata, and related distributions. - -This information is stored in :class:`ReleaseInfo` -objects. - -.. class:: ReleaseInfo - - -DistInfo ---------- - -:class:`DistInfo` is a simple class that contains -information related to distributions; mainly the URLs where distributions -can be found. - -.. class:: DistInfo - - -ReleasesList ------------- - -The :mod:`~packaging.pypi.dist` module provides a class which works -with lists of :class:`ReleaseInfo` classes; -used to filter and order results. - -.. class:: ReleasesList - - -Example usage -------------- - -Build a list of releases and order them -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Assuming we have a list of releases:: - - >>> from packaging.pypi.dist import ReleasesList, ReleaseInfo - >>> fb10 = ReleaseInfo("FooBar", "1.0") - >>> fb11 = ReleaseInfo("FooBar", "1.1") - >>> fb11a = ReleaseInfo("FooBar", "1.1a1") - >>> ReleasesList("FooBar", [fb11, fb11a, fb10]) - >>> releases.sort_releases() - >>> releases.get_versions() - ['1.1', '1.1a1', '1.0'] - >>> releases.add_release("1.2a1") - >>> releases.get_versions() - ['1.1', '1.1a1', '1.0', '1.2a1'] - >>> releases.sort_releases() - ['1.2a1', '1.1', '1.1a1', '1.0'] - >>> releases.sort_releases(prefer_final=True) - >>> releases.get_versions() - ['1.1', '1.0', '1.2a1', '1.1a1'] - - -Add distribution related information to releases -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -It's easy to add distribution information to releases:: - - >>> from packaging.pypi.dist import ReleasesList, ReleaseInfo - >>> r = ReleaseInfo("FooBar", "1.0") - >>> r.add_distribution("sdist", url="http://example.org/foobar-1.0.tar.gz") - >>> r.dists - {'sdist': FooBar 1.0 sdist} - >>> r['sdist'].url - {'url': 'http://example.org/foobar-1.0.tar.gz', 'hashname': None, 'hashval': - None, 'is_external': True} - - -Getting attributes from the dist objects -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -To abstract querying information returned from the indexes, attributes and -release information can be retrieved directly from dist objects. - -For instance, if you have a release instance that does not contain the metadata -attribute, it can be fetched by using the "fetch_metadata" method:: - - >>> r = Release("FooBar", "1.1") - >>> print r.metadata - None # metadata field is actually set to "None" - >>> r.fetch_metadata() - - -.. XXX add proper roles to these constructs - - -It's possible to retrieve a project's releases (`fetch_releases`), -metadata (`fetch_metadata`) and distributions (`fetch_distributions`) using -a similar work flow. - -.. XXX what is possible? - -Internally, this is possible because while retrieving information about -projects, releases or distributions, a reference to the client used is -stored which can be accessed using the objects `_index` attribute. diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.pypi.rst --- a/Doc/library/packaging.pypi.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -:mod:`packaging.pypi` --- Interface to projects indexes -======================================================= - -.. module:: packaging.pypi - :synopsis: Low-level and high-level APIs to query projects indexes. - - -Packaging queries PyPI to get information about projects or download them. The -low-level facilities used internally are also part of the public API designed to -be used by other tools. - -The :mod:`packaging.pypi` package provides those facilities, which can be -used to access information about Python projects registered at indexes, the -main one being PyPI, located ad http://pypi.python.org/. - -There is two ways to retrieve data from these indexes: a screen-scraping -interface called the "simple API", and XML-RPC. The first one uses HTML pages -located under http://pypi.python.org/simple/, the second one makes XML-RPC -requests to http://pypi.python.org/pypi/. All functions and classes also work -with other indexes such as mirrors, which typically implement only the simple -interface. - -Packaging provides a class that wraps both APIs to provide full query and -download functionality: :class:`packaging.pypi.client.ClientWrapper`. If you -want more control, you can use the underlying classes -:class:`packaging.pypi.simple.Crawler` and :class:`packaging.pypi.xmlrpc.Client` -to connect to one specific interface. - - -:mod:`packaging.pypi.client` --- High-level query API -===================================================== - -.. module:: packaging.pypi.client - :synopsis: Wrapper around :mod;`packaging.pypi.xmlrpc` and - :mod:`packaging.pypi.simple` to query indexes. - - -This module provides a high-level API to query indexes and search -for releases and distributions. The aim of this module is to choose the best -way to query the API automatically, either using XML-RPC or the simple index, -with a preference toward the latter. - -.. class:: ClientWrapper - - Instances of this class will use the simple interface or XML-RPC requests to - query indexes and return :class:`packaging.pypi.dist.ReleaseInfo` and - :class:`packaging.pypi.dist.ReleasesList` objects. - - .. method:: find_projects - - .. method:: get_release - - .. method:: get_releases diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.pypi.simple.rst --- a/Doc/library/packaging.pypi.simple.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -:mod:`packaging.pypi.simple` --- Crawler using the PyPI "simple" interface -========================================================================== - -.. module:: packaging.pypi.simple - :synopsis: Crawler using the screen-scraping "simple" interface to fetch info - and distributions. - - -`packaging.pypi.simple` can process Python Package Indexes and provides -useful information about distributions. It also can crawl local indexes, for -instance. - -You should use `packaging.pypi.simple` for: - - * Search distributions by name and versions. - * Process index external pages. - * Download distributions by name and versions. - -And should not be used for: - - * Things that will end up in too long index processing (like "finding all - distributions with a specific version, no matters the name") - - -API ---- - -.. class:: Crawler - - -Usage Exemples ---------------- - -To help you understand how using the `Crawler` class, here are some basic -usages. - -Request the simple index to get a specific distribution -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Supposing you want to scan an index to get a list of distributions for -the "foobar" project. You can use the "get_releases" method for that. -The get_releases method will browse the project page, and return -:class:`ReleaseInfo` objects for each found link that rely on downloads. :: - - >>> from packaging.pypi.simple import Crawler - >>> crawler = Crawler() - >>> crawler.get_releases("FooBar") - [, ] - - -Note that you also can request the client about specific versions, using version -specifiers (described in `PEP 345 -`_):: - - >>> client.get_releases("FooBar < 1.2") - [, ] - - -`get_releases` returns a list of :class:`ReleaseInfo`, but you also can get the -best distribution that fullfil your requirements, using "get_release":: - - >>> client.get_release("FooBar < 1.2") - - - -Download distributions -^^^^^^^^^^^^^^^^^^^^^^ - -As it can get the urls of distributions provided by PyPI, the `Crawler` -client also can download the distributions and put it for you in a temporary -destination:: - - >>> client.download("foobar") - /tmp/temp_dir/foobar-1.2.tar.gz - - -You also can specify the directory you want to download to:: - - >>> client.download("foobar", "/path/to/my/dir") - /path/to/my/dir/foobar-1.2.tar.gz - - -While downloading, the md5 of the archive will be checked, if not matches, it -will try another time, then if fails again, raise `MD5HashDoesNotMatchError`. - -Internally, that's not the Crawler which download the distributions, but the -`DistributionInfo` class. Please refer to this documentation for more details. - - -Following PyPI external links -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The default behavior for packaging is to *not* follow the links provided -by HTML pages in the "simple index", to find distributions related -downloads. - -It's possible to tell the PyPIClient to follow external links by setting the -`follow_externals` attribute, on instantiation or after:: - - >>> client = Crawler(follow_externals=True) - -or :: - - >>> client = Crawler() - >>> client.follow_externals = True - - -Working with external indexes, and mirrors -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The default `Crawler` behavior is to rely on the Python Package index stored -on PyPI (http://pypi.python.org/simple). - -As you can need to work with a local index, or private indexes, you can specify -it using the index_url parameter:: - - >>> client = Crawler(index_url="file://filesystem/path/") - -or :: - - >>> client = Crawler(index_url="http://some.specific.url/") - - -You also can specify mirrors to fallback on in case the first index_url you -provided doesnt respond, or not correctly. The default behavior for -`Crawler` is to use the list provided by Python.org DNS records, as -described in the :PEP:`381` about mirroring infrastructure. - -If you don't want to rely on these, you could specify the list of mirrors you -want to try by specifying the `mirrors` attribute. It's a simple iterable:: - - >>> mirrors = ["http://first.mirror","http://second.mirror"] - >>> client = Crawler(mirrors=mirrors) - - -Searching in the simple index -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -It's possible to search for projects with specific names in the package index. -Assuming you want to find all projects containing the "distutils" keyword:: - - >>> c.search_projects("distutils") - [, , , , , , ] - - -You can also search the projects starting with a specific text, or ending with -that text, using a wildcard:: - - >>> c.search_projects("distutils*") - [, , ] - - >>> c.search_projects("*distutils") - [, , , , ] diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.pypi.xmlrpc.rst --- a/Doc/library/packaging.pypi.xmlrpc.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -:mod:`packaging.pypi.xmlrpc` --- Crawler using the PyPI XML-RPC interface -========================================================================= - -.. module:: packaging.pypi.xmlrpc - :synopsis: Client using XML-RPC requests to fetch info and distributions. - - -Indexes can be queried using XML-RPC calls, and Packaging provides a simple -way to interface with XML-RPC. - -You should **use** XML-RPC when: - -* Searching the index for projects **on other fields than project - names**. For instance, you can search for projects based on the - author_email field. -* Searching all the versions that have existed for a project. -* you want to retrieve METADATAs information from releases or - distributions. - - -You should **avoid using** XML-RPC method calls when: - -* Retrieving the last version of a project -* Getting the projects with a specific name and version. -* The simple index can match your needs - - -When dealing with indexes, keep in mind that the index queries will always -return you :class:`packaging.pypi.dist.ReleaseInfo` and -:class:`packaging.pypi.dist.ReleasesList` objects. - -Some methods here share common APIs with the one you can find on -:class:`packaging.pypi.simple`, internally, :class:`packaging.pypi.client` -is inherited by :class:`Client` - - -API ---- - -.. class:: Client - - -Usage examples --------------- - -Use case described here are use case that are not common to the other clients. -If you want to see all the methods, please refer to API or to usage examples -described in :class:`packaging.pypi.client.Client` - - -Finding releases -^^^^^^^^^^^^^^^^ - -It's a common use case to search for "things" within the index. We can -basically search for projects by their name, which is the most used way for -users (eg. "give me the last version of the FooBar project"). - -This can be accomplished using the following syntax:: - - >>> client = xmlrpc.Client() - >>> client.get_release("Foobar (<= 1.3)) - - >>> client.get_releases("FooBar (<= 1.3)") - [FooBar 1.1, FooBar 1.1.1, FooBar 1.2, FooBar 1.2.1] - - -And we also can find for specific fields:: - - >>> client.search_projects(field=value) - - -You could specify the operator to use, default is "or":: - - >>> client.search_projects(field=value, operator="and") - - -The specific fields you can search are: - -* name -* version -* author -* author_email -* maintainer -* maintainer_email -* home_page -* license -* summary -* description -* keywords -* platform -* download_url - - -Getting metadata information -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -XML-RPC is a prefered way to retrieve metadata information from indexes. -It's really simple to do so:: - - >>> client = xmlrpc.Client() - >>> client.get_metadata("FooBar", "1.1") - - - -Assuming we already have a :class:`packaging.pypi.ReleaseInfo` object defined, -it's possible to pass it to the xmlrpc client to retrieve and complete its -metadata:: - - >>> foobar11 = ReleaseInfo("FooBar", "1.1") - >>> client = xmlrpc.Client() - >>> returned_release = client.get_metadata(release=foobar11) - >>> returned_release - - - -Get all the releases of a project -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -To retrieve all the releases for a project, you can build them using -`get_releases`:: - - >>> client = xmlrpc.Client() - >>> client.get_releases("FooBar") - [, , ] - - -Get information about distributions -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Indexes have information about projects, releases **and** distributions. -If you're not familiar with those, please refer to the documentation of -:mod:`packaging.pypi.dist`. - -It's possible to retrieve information about distributions, e.g "what are the -existing distributions for this release ? How to retrieve them ?":: - - >>> client = xmlrpc.Client() - >>> release = client.get_distributions("FooBar", "1.1") - >>> release.dists - {'sdist': , 'bdist': } - -As you see, this does not return a list of distributions, but a release, -because a release can be used like a list of distributions. diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.rst --- a/Doc/library/packaging.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ -:mod:`packaging` --- Packaging support -====================================== - -.. module:: packaging - :synopsis: Packaging system and building blocks for other packaging systems. -.. sectionauthor:: Fred L. Drake, Jr. , distutils and packaging - contributors - - -The :mod:`packaging` package provides support for building, packaging, -distributing and installing additional projects into a Python installation. -Projects may include Python modules, extension modules, packages and scripts. -:mod:`packaging` also provides building blocks for other packaging systems -that are not tied to the command system. - -This manual is the reference documentation for those standalone building -blocks and for extending Packaging. If you're looking for the user-centric -guides to install a project or package your own code, head to `See also`__. - - -Building blocks ---------------- - -.. toctree:: - :maxdepth: 2 - :numbered: - - packaging-misc - packaging.version - packaging.metadata - packaging.database - packaging.depgraph - packaging.pypi - packaging.pypi.dist - packaging.pypi.simple - packaging.pypi.xmlrpc - packaging.install - - -The command machinery ---------------------- - -.. toctree:: - :maxdepth: 2 - :numbered: - - packaging.dist - packaging.command - packaging.compiler - packaging.fancy_getopt - - -Other utilities ----------------- - -.. toctree:: - :maxdepth: 2 - :numbered: - - packaging.util - packaging.tests.pypi_server - -.. XXX missing: compat config create (dir_util) run pypi.{base,mirrors} - - -.. __: - -.. seealso:: - - :ref:`packaging-index` - The manual for developers of Python projects who want to package and - distribute them. This describes how to use :mod:`packaging` to make - projects easily found and added to an existing Python installation. - - :ref:`packaging-install-index` - A user-centered manual which includes information on adding projects - into an existing Python installation. You do not need to be a Python - programmer to read this manual. diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.tests.pypi_server.rst --- a/Doc/library/packaging.tests.pypi_server.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -:mod:`packaging.tests.pypi_server` --- PyPI mock server -======================================================= - -.. module:: packaging.tests.pypi_server - :synopsis: Mock server used to test PyPI-related modules and commands. - - -When you are testing code that works with Packaging, you might find these tools -useful. - - -The mock server ---------------- - -.. class:: PyPIServer - - PyPIServer is a class that implements an HTTP server running in a separate - thread. All it does is record the requests for further inspection. The recorded - data is available under ``requests`` attribute. The default - HTTP response can be overridden with the ``default_response_status``, - ``default_response_headers`` and ``default_response_data`` attributes. - - By default, when accessing the server with urls beginning with `/simple/`, - the server also record your requests, but will look for files under - the `/tests/pypiserver/simple/` path. - - You can tell the sever to serve static files for other paths. This could be - accomplished by using the `static_uri_paths` parameter, as below:: - - server = PyPIServer(static_uri_paths=["first_path", "second_path"]) - - - You need to create the content that will be served under the - `/tests/pypiserver/default` path. If you want to serve content from another - place, you also can specify another filesystem path (which needs to be under - `tests/pypiserver/`. This will replace the default behavior of the server, and - it will not serve content from the `default` dir :: - - server = PyPIServer(static_filesystem_paths=["path/to/your/dir"]) - - - If you just need to add some paths to the existing ones, you can do as shown, - keeping in mind that the server will always try to load paths in reverse order - (e.g here, try "another/super/path" then the default one) :: - - server = PyPIServer(test_static_path="another/super/path") - server = PyPIServer("another/super/path") - # or - server.static_filesystem_paths.append("another/super/path") - - - As a result of what, in your tests, while you need to use the PyPIServer, in - order to isolates the test cases, the best practice is to place the common files - in the `default` folder, and to create a directory for each specific test case:: - - server = PyPIServer(static_filesystem_paths = ["default", "test_pypi_server"], - static_uri_paths=["simple", "external"]) - - -Base class and decorator for tests ----------------------------------- - -.. class:: PyPIServerTestCase - - ``PyPIServerTestCase`` is a test case class with setUp and tearDown methods that - take care of a single PyPIServer instance attached as a ``pypi`` attribute on - the test class. Use it as one of the base classes in your test case:: - - - class UploadTestCase(PyPIServerTestCase): - - def test_something(self): - cmd = self.prepare_command() - cmd.ensure_finalized() - cmd.repository = self.pypi.full_address - cmd.run() - - environ, request_data = self.pypi.requests[-1] - self.assertEqual(request_data, EXPECTED_REQUEST_DATA) - - -.. decorator:: use_pypi_server - - You also can use a decorator for your tests, if you do not need the same server - instance along all you test case. So, you can specify, for each test method, - some initialisation parameters for the server. - - For this, you need to add a `server` parameter to your method, like this:: - - class SampleTestCase(TestCase): - - @use_pypi_server() - def test_something(self, server): - ... - - - The decorator will instantiate the server for you, and run and stop it just - before and after your method call. You also can pass the server initializer, - just like this:: - - class SampleTestCase(TestCase): - - @use_pypi_server("test_case_name") - def test_something(self, server): - ... diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.util.rst --- a/Doc/library/packaging.util.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,186 +0,0 @@ -:mod:`packaging.util` --- Miscellaneous utility functions -========================================================= - -.. module:: packaging.util - :synopsis: Miscellaneous utility functions. - - -This module contains various helpers for the other modules. - -.. XXX a number of functions are missing, but the module may be split first - (it's ginormous right now, some things could go to compat for example) - -.. function:: get_platform() - - Return a string that identifies the current platform. This is used mainly to - distinguish platform-specific build directories and platform-specific built - distributions. Typically includes the OS name and version and the - architecture (as supplied by 'os.uname()'), although the exact information - included depends on the OS; e.g. for IRIX the architecture isn't particularly - important (IRIX only runs on SGI hardware), but for Linux the kernel version - isn't particularly important. - - Examples of returned values: - - * ``linux-i586`` - * ``linux-alpha`` - * ``solaris-2.6-sun4u`` - * ``irix-5.3`` - * ``irix64-6.2`` - - For non-POSIX platforms, currently just returns ``sys.platform``. - - For Mac OS X systems the OS version reflects the minimal version on which - binaries will run (that is, the value of ``MACOSX_DEPLOYMENT_TARGET`` - during the build of Python), not the OS version of the current system. - - For universal binary builds on Mac OS X the architecture value reflects - the univeral binary status instead of the architecture of the current - processor. For 32-bit universal binaries the architecture is ``fat``, - for 64-bit universal binaries the architecture is ``fat64``, and - for 4-way universal binaries the architecture is ``universal``. Starting - from Python 2.7 and Python 3.2 the architecture ``fat3`` is used for - a 3-way universal build (ppc, i386, x86_64) and ``intel`` is used for - a univeral build with the i386 and x86_64 architectures - - Examples of returned values on Mac OS X: - - * ``macosx-10.3-ppc`` - - * ``macosx-10.3-fat`` - - * ``macosx-10.5-universal`` - - * ``macosx-10.6-intel`` - - .. XXX reinvention of platform module? - - -.. function:: convert_path(pathname) - - Return 'pathname' as a name that will work on the native filesystem, i.e. - split it on '/' and put it back together again using the current directory - separator. Needed because filenames in the setup script are always supplied - in Unix style, and have to be converted to the local convention before we - can actually use them in the filesystem. Raises :exc:`ValueError` on - non-Unix-ish systems if *pathname* either starts or ends with a slash. - - -.. function:: change_root(new_root, pathname) - - Return *pathname* with *new_root* prepended. If *pathname* is relative, this - is equivalent to ``os.path.join(new_root,pathname)`` Otherwise, it requires - making *pathname* relative and then joining the two, which is tricky on - DOS/Windows. - - -.. function:: check_environ() - - Ensure that 'os.environ' has all the environment variables we guarantee that - users can use in config files, command-line options, etc. Currently this - includes: - - * :envvar:`HOME` - user's home directory (Unix only) - * :envvar:`PLAT` - description of the current platform, including hardware - and OS (see :func:`get_platform`) - - -.. function:: find_executable(executable, path=None) - - Search the path for a given executable name. - - -.. function:: subst_vars(s, local_vars) - - Perform shell/Perl-style variable substitution on *s*. Every occurrence of - ``$`` followed by a name is considered a variable, and variable is - substituted by the value found in the *local_vars* dictionary, or in - ``os.environ`` if it's not in *local_vars*. *os.environ* is first - checked/augmented to guarantee that it contains certain values: see - :func:`check_environ`. Raise :exc:`ValueError` for any variables not found - in either *local_vars* or ``os.environ``. - - Note that this is not a fully-fledged string interpolation function. A valid - ``$variable`` can consist only of upper and lower case letters, numbers and - an underscore. No { } or ( ) style quoting is available. - - -.. function:: split_quoted(s) - - Split a string up according to Unix shell-like rules for quotes and - backslashes. In short: words are delimited by spaces, as long as those spaces - are not escaped by a backslash, or inside a quoted string. Single and double - quotes are equivalent, and the quote characters can be backslash-escaped. - The backslash is stripped from any two-character escape sequence, leaving - only the escaped character. The quote characters are stripped from any - quoted string. Returns a list of words. - - .. TODO Should probably be moved into the standard library. - - -.. function:: execute(func, args[, msg=None, verbose=0, dry_run=0]) - - Perform some action that affects the outside world (for instance, writing to - the filesystem). Such actions are special because they are disabled by the - *dry_run* flag. This method takes care of all that bureaucracy for you; - all you have to do is supply the function to call and an argument tuple for - it (to embody the "external action" being performed), and an optional message - to print. - - -.. function:: newer(source, target) - - Return true if *source* exists and is more recently modified than *target*, - or if *source* exists and *target* doesn't. Return false if both exist and - *target* is the same age or newer than *source*. Raise - :exc:`PackagingFileError` if *source* does not exist. - - -.. function:: strtobool(val) - - Convert a string representation of truth to true (1) or false (0). - - True values are ``y``, ``yes``, ``t``, ``true``, ``on`` and ``1``; false - values are ``n``, ``no``, ``f``, ``false``, ``off`` and ``0``. Raises - :exc:`ValueError` if *val* is anything else. - -.. TODO Add :term: markup to bytecode when merging into the stdlib - -.. function:: byte_compile(py_files[, optimize=0, force=0, prefix=None, base_dir=None, verbose=1, dry_run=0, direct=None]) - - Byte-compile a collection of Python source files to either :file:`.pyc` or - :file:`.pyo` files in the same directory. *py_files* is a list of files to - compile; any files that don't end in :file:`.py` are silently skipped. - *optimize* must be one of the following: - - * ``0`` - don't optimize (generate :file:`.pyc`) - * ``1`` - normal optimization (like ``python -O``) - * ``2`` - extra optimization (like ``python -OO``) - - If *force* is true, all files are recompiled regardless of timestamps. - - The source filename encoded in each bytecode file defaults to the filenames - listed in *py_files*; you can modify these with *prefix* and *basedir*. - *prefix* is a string that will be stripped off of each source filename, and - *base_dir* is a directory name that will be prepended (after *prefix* is - stripped). You can supply either or both (or neither) of *prefix* and - *base_dir*, as you wish. - - If *dry_run* is true, doesn't actually do anything that would affect the - filesystem. - - Byte-compilation is either done directly in this interpreter process with the - standard :mod:`py_compile` module, or indirectly by writing a temporary - script and executing it. Normally, you should let :func:`byte_compile` - figure out to use direct compilation or not (see the source for details). - The *direct* flag is used by the script generated in indirect mode; unless - you know what you're doing, leave it set to ``None``. - - -.. function:: rfc822_escape(header) - - Return a version of *header* escaped for inclusion in an :rfc:`822` header, by - ensuring there are 8 spaces space after each newline. Note that it does no - other modification of the string. - - .. TODO this _can_ be replaced diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/packaging.version.rst --- a/Doc/library/packaging.version.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -:mod:`packaging.version` --- Version number classes -=================================================== - -.. module:: packaging.version - :synopsis: Classes that represent project version numbers. - - -This module contains classes and functions useful to deal with version numbers. -It's an implementation of version specifiers `as defined in PEP 345 -`_. - - -Version numbers ---------------- - -.. class:: NormalizedVersion(self, s, error_on_huge_major_num=True) - - A specific version of a distribution, as described in PEP 345. *s* is a - string object containing the version number (for example ``'1.2b1'``), - *error_on_huge_major_num* a boolean specifying whether to consider an - apparent use of a year or full date as the major version number an error. - - The rationale for the second argument is that there were projects using years - or full dates as version numbers, which could cause problems with some - packaging systems sorting. - - Instances of this class can be compared and sorted:: - - >>> NormalizedVersion('1.2b1') < NormalizedVersion('1.2') - True - - :class:`NormalizedVersion` is used internally by :class:`VersionPredicate` to - do its work. - - -.. class:: IrrationalVersionError - - Exception raised when an invalid string is given to - :class:`NormalizedVersion`. - - >>> NormalizedVersion("irrational_version_number") - ... - IrrationalVersionError: irrational_version_number - - -.. function:: suggest_normalized_version(s) - - Before standardization in PEP 386, various schemes were in use. Packaging - provides a function to try to convert any string to a valid, normalized - version:: - - >>> suggest_normalized_version('2.1-rc1') - 2.1c1 - - - If :func:`suggest_normalized_version` can't make sense of the given string, - it will return ``None``:: - - >>> print(suggest_normalized_version('not a version')) - None - - -Version predicates ------------------- - -.. class:: VersionPredicate(predicate) - - This class deals with the parsing of field values like - ``ProjectName (>=version)``. - - .. method:: match(version) - - Test if a version number matches the predicate: - - >>> version = VersionPredicate("ProjectName (<1.2, >1.0)") - >>> version.match("1.2.1") - False - >>> version.match("1.1.1") - True - - -Validation helpers ------------------- - -If you want to use :term:`LBYL`-style checks instead of instantiating the -classes and catching :class:`IrrationalVersionError` and :class:`ValueError`, -you can use these functions: - -.. function:: is_valid_version(predicate) - - Check whether the given string is a valid version number. Example of valid - strings: ``'1.2'``, ``'4.2.0.dev4'``, ``'2.5.4.post2'``. - - -.. function:: is_valid_versions(predicate) - - Check whether the given string is a valid value for specifying multiple - versions, such as in the Requires-Python field. Example: ``'2.7, >=3.2'``. - - -.. function:: is_valid_predicate(predicate) - - Check whether the given string is a valid version predicate. Examples: - ``'some.project == 4.5, <= 4.7'``, ``'speciallib (> 1.0, != 1.4.2, < 2.0)'``. diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/pprint.rst --- a/Doc/library/pprint.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/pprint.rst Sat May 14 18:40:38 2011 +0200 @@ -189,105 +189,37 @@ .. _pprint-example: -Example -------- +pprint Example +-------------- -To demonstrate several uses of the :func:`pprint` function and its parameters, -let's fetch information about a project from PyPI:: +This example demonstrates several uses of the :func:`pprint` function and its +parameters. - >>> import json >>> import pprint - >>> from urllib.request import urlopen - >>> with urlopen('http://pypi.python.org/pypi/configparser/json') as url: - ... http_info = url.info() - ... raw_data = url.read().decode(http_info.get_content_charset()) - >>> project_info = json.loads(raw_data) - >>> result = {'headers': http_info.items(), 'body': project_info} + >>> tup = ('spam', ('eggs', ('lumberjack', ('knights', ('ni', ('dead', + ... ('parrot', ('fresh fruit',)))))))) + >>> stuff = ['a' * 10, tup, ['a' * 30, 'b' * 30], ['c' * 20, 'd' * 20]] + >>> pprint.pprint(stuff) + ['aaaaaaaaaa', + ('spam', + ('eggs', + ('lumberjack', + ('knights', ('ni', ('dead', ('parrot', ('fresh fruit',)))))))), + ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'], + ['cccccccccccccccccccc', 'dddddddddddddddddddd']] + >>> pprint.pprint(stuff, depth=3) + ['aaaaaaaaaa', + ('spam', ('eggs', (...))), + ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'], + ['cccccccccccccccccccc', 'dddddddddddddddddddd']] + >>> pprint.pprint(stuff, width=60) + ['aaaaaaaaaa', + ('spam', + ('eggs', + ('lumberjack', + ('knights', + ('ni', ('dead', ('parrot', ('fresh fruit',)))))))), + ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', + 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb'], + ['cccccccccccccccccccc', 'dddddddddddddddddddd']] -In its basic form, :func:`pprint` shows the whole object:: - - >>> pprint.pprint(result) - {'body': {'info': {'_pypi_hidden': False, - '_pypi_ordering': 12, - 'classifiers': ['Development Status :: 4 - Beta', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: MIT License', - 'Natural Language :: English', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7', - 'Topic :: Software Development :: Libraries', - 'Topic :: Software Development :: Libraries :: Python Modules'], - 'download_url': 'UNKNOWN', - 'home_page': 'http://docs.python.org/py3k/library/configparser.html', - 'keywords': 'configparser ini parsing conf cfg configuration file', - 'license': 'MIT', - 'name': 'configparser', - 'package_url': 'http://pypi.python.org/pypi/configparser', - 'platform': 'any', - 'release_url': 'http://pypi.python.org/pypi/configparser/3.2.0r3', - 'requires_python': None, - 'stable_version': None, - 'summary': 'This library brings the updated configparser from Python 3.2+ to Python 2.6-2.7.', - 'version': '3.2.0r3'}, - 'urls': [{'comment_text': '', - 'downloads': 47, - 'filename': 'configparser-3.2.0r3.tar.gz', - 'has_sig': False, - 'md5_digest': '8500fd87c61ac0de328fc996fce69b96', - 'packagetype': 'sdist', - 'python_version': 'source', - 'size': 32281, - 'upload_time': '2011-05-10T16:28:50', - 'url': 'http://pypi.python.org/packages/source/c/configparser/configparser-3.2.0r3.tar.gz'}]}, - 'headers': [('Date', 'Sat, 14 May 2011 12:48:52 GMT'), - ('Server', 'Apache/2.2.16 (Debian)'), - ('Content-Disposition', 'inline'), - ('Connection', 'close'), - ('Transfer-Encoding', 'chunked'), - ('Content-Type', 'application/json; charset="UTF-8"')]} - -The result can be limited to a certain *depth* (ellipsis is used for deeper -contents):: - - >>> pprint.pprint(result, depth=3) - {'body': {'info': {'_pypi_hidden': False, - '_pypi_ordering': 12, - 'classifiers': [...], - 'download_url': 'UNKNOWN', - 'home_page': 'http://docs.python.org/py3k/library/configparser.html', - 'keywords': 'configparser ini parsing conf cfg configuration file', - 'license': 'MIT', - 'name': 'configparser', - 'package_url': 'http://pypi.python.org/pypi/configparser', - 'platform': 'any', - 'release_url': 'http://pypi.python.org/pypi/configparser/3.2.0r3', - 'requires_python': None, - 'stable_version': None, - 'summary': 'This library brings the updated configparser from Python 3.2+ to Python 2.6-2.7.', - 'version': '3.2.0r3'}, - 'urls': [{...}]}, - 'headers': [('Date', 'Sat, 14 May 2011 12:48:52 GMT'), - ('Server', 'Apache/2.2.16 (Debian)'), - ('Content-Disposition', 'inline'), - ('Connection', 'close'), - ('Transfer-Encoding', 'chunked'), - ('Content-Type', 'application/json; charset="UTF-8"')]} - -Additionally, maximum *width* can be suggested. If a long object cannot be -split, the specified width will be exceeded:: - - >>> pprint.pprint(result['headers'], width=30) - [('Date', - 'Sat, 14 May 2011 12:48:52 GMT'), - ('Server', - 'Apache/2.2.16 (Debian)'), - ('Content-Disposition', - 'inline'), - ('Connection', 'close'), - ('Transfer-Encoding', - 'chunked'), - ('Content-Type', - 'application/json; charset="UTF-8"')] diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/python.rst --- a/Doc/library/python.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/python.rst Sat May 14 18:40:38 2011 +0200 @@ -25,5 +25,4 @@ inspect.rst site.rst fpectl.rst - packaging.rst distutils.rst diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/random.rst --- a/Doc/library/random.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/random.rst Sat May 14 18:40:38 2011 +0200 @@ -43,12 +43,6 @@ uses the system function :func:`os.urandom` to generate random numbers from sources provided by the operating system. -.. warning:: - - The generators of the :mod:`random` module should not be used for security - purposes. Use :func:`ssl.RAND_bytes` if you require a cryptographically - secure pseudorandom number generator. - Bookkeeping functions: diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/re.rst --- a/Doc/library/re.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/re.rst Sat May 14 18:40:38 2011 +0200 @@ -1301,27 +1301,24 @@ to combine those into a single master regular expression and to loop over successive matches:: - import collections - import re - - Token = collections.namedtuple('Token', ['typ', 'value', 'line', 'column']) + Token = collections.namedtuple('Token', 'typ value line column') def tokenize(s): - keywords = {'IF', 'THEN', 'ENDIF', 'FOR', 'NEXT', 'GOSUB', 'RETURN'} - token_specification = [ - ('NUMBER', r'\d+(\.\d*)?'), # Integer or decimal number - ('ASSIGN', r':='), # Assignment operator - ('END', r';'), # Statement terminator - ('ID', r'[A-Za-z]+'), # Identifiers - ('OP', r'[+*\/\-]'), # Arithmetic operators - ('NEWLINE', r'\n'), # Line endings - ('SKIP', r'[ \t]'), # Skip over spaces and tabs + keywords = {'IF', 'THEN', 'FOR', 'NEXT', 'GOSUB', 'RETURN'} + tok_spec = [ + ('NUMBER', r'\d+(\.\d*)?'), # Integer or decimal number + ('ASSIGN', r':='), # Assignment operator + ('END', ';'), # Statement terminator + ('ID', r'[A-Za-z]+'), # Identifiers + ('OP', r'[+*\/\-]'), # Arithmetic operators + ('NEWLINE', r'\n'), # Line endings + ('SKIP', r'[ \t]'), # Skip over spaces and tabs ] - tok_regex = '|'.join('(?P<%s>%s)' % pair for pair in token_specification) - get_token = re.compile(tok_regex).match + tok_re = '|'.join('(?P<%s>%s)' % pair for pair in tok_spec) + gettok = re.compile(tok_re).match line = 1 pos = line_start = 0 - mo = get_token(s) + mo = gettok(s) while mo is not None: typ = mo.lastgroup if typ == 'NEWLINE': @@ -1333,15 +1330,13 @@ typ = val yield Token(typ, val, line, mo.start()-line_start) pos = mo.end() - mo = get_token(s, pos) + mo = gettok(s, pos) if pos != len(s): raise RuntimeError('Unexpected character %r on line %d' %(s[pos], line)) - statements = ''' - IF quantity THEN - total := total + price * quantity; - tax := price * 0.05; - ENDIF; + statements = '''\ + total := total + price * quantity; + tax := price * 0.05; ''' for token in tokenize(statements): @@ -1349,22 +1344,17 @@ The tokenizer produces the following output:: - Token(typ='IF', value='IF', line=2, column=5) - Token(typ='ID', value='quantity', line=2, column=8) - Token(typ='THEN', value='THEN', line=2, column=17) - Token(typ='ID', value='total', line=3, column=9) - Token(typ='ASSIGN', value=':=', line=3, column=15) - Token(typ='ID', value='total', line=3, column=18) - Token(typ='OP', value='+', line=3, column=24) - Token(typ='ID', value='price', line=3, column=26) - Token(typ='OP', value='*', line=3, column=32) - Token(typ='ID', value='quantity', line=3, column=34) - Token(typ='END', value=';', line=3, column=42) - Token(typ='ID', value='tax', line=4, column=9) - Token(typ='ASSIGN', value=':=', line=4, column=13) - Token(typ='ID', value='price', line=4, column=16) - Token(typ='OP', value='*', line=4, column=22) - Token(typ='NUMBER', value='0.05', line=4, column=24) - Token(typ='END', value=';', line=4, column=28) - Token(typ='ENDIF', value='ENDIF', line=5, column=5) - Token(typ='END', value=';', line=5, column=10) + Token(typ='ID', value='total', line=1, column=8) + Token(typ='ASSIGN', value=':=', line=1, column=14) + Token(typ='ID', value='total', line=1, column=17) + Token(typ='OP', value='+', line=1, column=23) + Token(typ='ID', value='price', line=1, column=25) + Token(typ='OP', value='*', line=1, column=31) + Token(typ='ID', value='quantity', line=1, column=33) + Token(typ='END', value=';', line=1, column=41) + Token(typ='ID', value='tax', line=2, column=9) + Token(typ='ASSIGN', value=':=', line=2, column=13) + Token(typ='ID', value='price', line=2, column=16) + Token(typ='OP', value='*', line=2, column=22) + Token(typ='NUMBER', value='0.05', line=2, column=24) + Token(typ='END', value=';', line=2, column=28) diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/signal.rst --- a/Doc/library/signal.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/signal.rst Sat May 14 18:40:38 2011 +0200 @@ -187,9 +187,10 @@ Send the signal *signum* to the thread *thread_id*, another thread in the same process as the caller. The signal is asynchronously directed to thread. - Use :func:`threading.get_ident()` or the :attr:`~threading.Thread.ident` - attribute of :attr:`threading.Thread` to get a 'thread identifier' for - *thread_id*. + *thread_id* can be read from the :attr:`~threading.Thread.ident` attribute + of :attr:`threading.Thread`. For example, + ``threading.current_thread().ident`` gives the identifier of the current + thread. If *signum* is 0, then no signal is sent, but error checking is still performed; this can be used to check if a thread is still running. diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/site.rst --- a/Doc/library/site.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/site.rst Sat May 14 18:40:38 2011 +0200 @@ -129,10 +129,6 @@ unless the :program:`python` interpreter was started with the :option:`-S` flag. - .. versionchanged:: 3.3 - This function used to be called unconditionnally. - - .. function:: addsitedir(sitedir, known_paths=None) Adds a directory to sys.path and processes its pth files. diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/smtplib.rst --- a/Doc/library/smtplib.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/smtplib.rst Sat May 14 18:40:38 2011 +0200 @@ -49,7 +49,7 @@ Support for the :keyword:`with` statement was added. -.. class:: SMTP_SSL(host='', port=0, local_hostname=None, keyfile=None, certfile=None[, timeout], context=None) +.. class:: SMTP_SSL(host='', port=0, local_hostname=None, keyfile=None, certfile=None[, timeout]) A :class:`SMTP_SSL` instance behaves exactly the same as instances of :class:`SMTP`. :class:`SMTP_SSL` should be used for situations where SSL is @@ -57,16 +57,11 @@ not appropriate. If *host* is not specified, the local host is used. If *port* is zero, the standard SMTP-over-SSL port (465) is used. *keyfile* and *certfile* are also optional, and can contain a PEM formatted private key - and certificate chain file for the SSL connection. *context* also optional, can contain - a SSLContext, and is an alternative to keyfile and certfile; If it is specified both - keyfile and certfile must be None. The optional *timeout* + and certificate chain file for the SSL connection. The optional *timeout* parameter specifies a timeout in seconds for blocking operations like the connection attempt (if not specified, the global default timeout setting will be used). - .. versionchanged:: 3.3 - *context* was added. - .. class:: LMTP(host='', port=LMTP_PORT, local_hostname=None) @@ -261,7 +256,7 @@ No suitable authentication method was found. -.. method:: SMTP.starttls(keyfile=None, certfile=None, context=None) +.. method:: SMTP.starttls(keyfile=None, certfile=None) Put the SMTP connection in TLS (Transport Layer Security) mode. All SMTP commands that follow will be encrypted. You should then call :meth:`ehlo` @@ -270,9 +265,6 @@ If *keyfile* and *certfile* are provided, these are passed to the :mod:`socket` module's :func:`ssl` function. - Optional *context* parameter is a :class:`ssl.SSLContext` object; This is an alternative to - using a keyfile and a certfile and if specified both *keyfile* and *certfile* should be None. - If there has been no previous ``EHLO`` or ``HELO`` command this session, this method tries ESMTP ``EHLO`` first. @@ -285,9 +277,6 @@ :exc:`RuntimeError` SSL/TLS support is not available to your Python interpreter. - .. versionchanged:: 3.3 - *context* was added. - .. method:: SMTP.sendmail(from_addr, to_addrs, msg, mail_options=[], rcpt_options=[]) diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/socket.rst --- a/Doc/library/socket.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/socket.rst Sat May 14 18:40:38 2011 +0200 @@ -536,39 +536,6 @@ .. versionadded:: 3.3 -.. function:: if_nameindex() - - Return a list of network interface information - (index int, name string) tuples. - :exc:`socket.error` if the system call fails. - - Availability: Unix. - - .. versionadded:: 3.3 - - -.. function:: if_nametoindex(if_name) - - Return a network interface index number corresponding to an - interface name. - :exc:`socket.error` if no interface with the given name exists. - - Availability: Unix. - - .. versionadded:: 3.3 - - -.. function:: if_indextoname(if_index) - - Return a network interface name corresponding to a - interface index number. - :exc:`socket.error` if no interface with the given index exists. - - Availability: Unix. - - .. versionadded:: 3.3 - - .. data:: SocketType This is a Python type object that represents the socket object type. It is the diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/socketserver.rst --- a/Doc/library/socketserver.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/socketserver.rst Sat May 14 18:40:38 2011 +0200 @@ -153,21 +153,8 @@ .. method:: BaseServer.serve_forever(poll_interval=0.5) Handle requests until an explicit :meth:`shutdown` request. Polls for - shutdown every *poll_interval* seconds. It also calls - :meth:`service_actions` which may be used by a subclass or Mixin to provide - various cleanup actions. For e.g. ForkingMixin class uses - :meth:`service_actions` to cleanup the zombie child processes. + shutdown every *poll_interval* seconds. - .. versionchanged:: 3.3 - Added service_actions call to the serve_forever method. - - -.. method:: BaseServer.service_actions() - - This is called by the serve_forever loop. This method is can be overridden - by Mixin's to add cleanup or service specific actions. - - .. versionadded:: 3.3 .. method:: BaseServer.shutdown() diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/ssl.rst --- a/Doc/library/ssl.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/ssl.rst Sat May 14 18:40:38 2011 +0200 @@ -162,35 +162,6 @@ Random generation ^^^^^^^^^^^^^^^^^ -.. function:: RAND_bytes(num) - - Returns *num* cryptographically strong pseudo-random bytes. Raises an - :class:`SSLError` if the PRNG has not been seeded with enough data or if the - operation is not supported by the current RAND method. :func:`RAND_status` - can be used to check the status of the PRNG and :func:`RAND_add` can be used - to seed the PRNG. - - Read the Wikipedia article, `Cryptographically secure pseudorandom number - generator (CSPRNG) - `_, - to get the requirements of a cryptographically generator. - - .. versionadded:: 3.3 - -.. function:: RAND_pseudo_bytes(num) - - Returns (bytes, is_cryptographic): bytes are *num* pseudo-random bytes, - is_cryptographic is True if the bytes generated are cryptographically - strong. Raises an :class:`SSLError` if the operation is not supported by the - current RAND method. - - Generated pseudo-random byte sequences will be unique if they are of - sufficient length, but are not necessarily unpredictable. They can be used - for non-cryptographic purposes and for certain purposes in cryptographic - protocols, but usually not for key generation etc. - - .. versionadded:: 3.3 - .. function:: RAND_status() Returns True if the SSL pseudo-random number generator has been seeded with @@ -200,7 +171,7 @@ .. function:: RAND_egd(path) - If you are running an entropy-gathering daemon (EGD) somewhere, and *path* + If you are running an entropy-gathering daemon (EGD) somewhere, and ``path`` is the pathname of a socket connection open to it, this will read 256 bytes of randomness from the socket, and add it to the SSL pseudo-random number generator to increase the security of generated secret keys. This is @@ -211,8 +182,8 @@ .. function:: RAND_add(bytes, entropy) - Mixes the given *bytes* into the SSL pseudo-random number generator. The - parameter *entropy* (a float) is a lower bound on the entropy contained in + Mixes the given ``bytes`` into the SSL pseudo-random number generator. The + parameter ``entropy`` (a float) is a lower bound on the entropy contained in string (so you can always use :const:`0.0`). See :rfc:`1750` for more information on sources of entropy. diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/subprocess.rst --- a/Doc/library/subprocess.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/subprocess.rst Sat May 14 18:40:38 2011 +0200 @@ -311,7 +311,7 @@ .. function:: check_output(*popenargs, timeout=None, **kwargs) - Run command with arguments and return its output as a bytes object. + Run command with arguments and return its output as a byte string. If the exit code was non-zero it raises a :exc:`CalledProcessError`. The :exc:`CalledProcessError` object will have the return code in the @@ -447,9 +447,8 @@ Interact with process: Send data to stdin. Read data from stdout and stderr, until end-of-file is reached. Wait for process to terminate. The optional - *input* argument should be data to be sent to the child process, or - ``None``, if no data should be sent to the child. The type of *input* - must be bytes or, if *universal_newlines* was ``True``, a string. + *input* argument should be a byte string to be sent to the child process, or + ``None``, if no data should be sent to the child. :meth:`communicate` returns a tuple ``(stdoutdata, stderrdata)``. diff -r 2e49722c7263 -r 6944bdf1289a Doc/library/threading.rst --- a/Doc/library/threading.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/library/threading.rst Sat May 14 18:40:38 2011 +0200 @@ -48,17 +48,6 @@ returned. -.. function:: get_ident() - - Return the 'thread identifier' of the current thread. This is a nonzero - integer. Its value has no direct meaning; it is intended as a magic cookie - to be used e.g. to index a dictionary of thread-specific data. Thread - identifiers may be recycled when a thread exits and another thread is - created. - - .. versionadded:: 3.3 - - .. function:: enumerate() Return a list of all :class:`Thread` objects currently alive. The list @@ -343,10 +332,10 @@ .. attribute:: ident The 'thread identifier' of this thread or ``None`` if the thread has not - been started. This is a nonzero integer. See the :func:`get_ident()` - function. Thread identifiers may be recycled when a thread exits and - another thread is created. The identifier is available even after the - thread has exited. + been started. This is a nonzero integer. See the + :func:`thread.get_ident()` function. Thread identifiers may be recycled + when a thread exits and another thread is created. The identifier is + available even after the thread has exited. .. method:: is_alive() diff -r 2e49722c7263 -r 6944bdf1289a Doc/license.rst --- a/Doc/license.rst Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/license.rst Sat May 14 18:40:38 2011 +0200 @@ -847,7 +847,7 @@ ----- The :mod:`pyexpat` extension is built using an included copy of the expat -sources unless the build is configured ``--with-system-expat``:: +sources unless the build is configured :option:`--with-system-expat`:: Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd and Clark Cooper @@ -876,7 +876,7 @@ ------ The :mod:`_ctypes` extension is built using an included copy of the libffi -sources unless the build is configured ``--with-system-libffi``:: +sources unless the build is configured :option:`--with-system-libffi`:: Copyright (c) 1996-2008 Red Hat, Inc and others. diff -r 2e49722c7263 -r 6944bdf1289a Doc/packaging/builtdist.rst --- a/Doc/packaging/builtdist.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,307 +0,0 @@ -.. _packaging-built-dist: - -**************************** -Creating Built Distributions -**************************** - -A "built distribution" is what you're probably used to thinking of either as a -"binary package" or an "installer" (depending on your background). It's not -necessarily binary, though, because it might contain only Python source code -and/or byte-code; and we don't call it a package, because that word is already -spoken for in Python. (And "installer" is a term specific to the world of -mainstream desktop systems.) - -A built distribution is how you make life as easy as possible for installers of -your module distribution: for users of RPM-based Linux systems, it's a binary -RPM; for Windows users, it's an executable installer; for Debian-based Linux -users, it's a Debian package; and so forth. Obviously, no one person will be -able to create built distributions for every platform under the sun, so the -Distutils are designed to enable module developers to concentrate on their -specialty---writing code and creating source distributions---while an -intermediary species called *packagers* springs up to turn source distributions -into built distributions for as many platforms as there are packagers. - -Of course, the module developer could be his own packager; or the packager could -be a volunteer "out there" somewhere who has access to a platform which the -original developer does not; or it could be software periodically grabbing new -source distributions and turning them into built distributions for as many -platforms as the software has access to. Regardless of who they are, a packager -uses the setup script and the :command:`bdist` command family to generate built -distributions. - -As a simple example, if I run the following command in the Distutils source -tree:: - - python setup.py bdist - -then the Distutils builds my module distribution (the Distutils itself in this -case), does a "fake" installation (also in the :file:`build` directory), and -creates the default type of built distribution for my platform. The default -format for built distributions is a "dumb" tar file on Unix, and a simple -executable installer on Windows. (That tar file is considered "dumb" because it -has to be unpacked in a specific location to work.) - -Thus, the above command on a Unix system creates -:file:`Distutils-1.0.{plat}.tar.gz`; unpacking this tarball from the right place -installs the Distutils just as though you had downloaded the source distribution -and run ``python setup.py install``. (The "right place" is either the root of -the filesystem or Python's :file:`{prefix}` directory, depending on the options -given to the :command:`bdist_dumb` command; the default is to make dumb -distributions relative to :file:`{prefix}`.) - -Obviously, for pure Python distributions, this isn't any simpler than just -running ``python setup.py install``\ ---but for non-pure distributions, which -include extensions that would need to be compiled, it can mean the difference -between someone being able to use your extensions or not. And creating "smart" -built distributions, such as an executable installer for -Windows, is far more convenient for users even if your distribution doesn't -include any extensions. - -The :command:`bdist` command has a :option:`--formats` option, similar to the -:command:`sdist` command, which you can use to select the types of built -distribution to generate: for example, :: - - python setup.py bdist --format=zip - -would, when run on a Unix system, create :file:`Distutils-1.0.{plat}.zip`\ ----again, this archive would be unpacked from the root directory to install the -Distutils. - -The available formats for built distributions are: - -+-------------+------------------------------+---------+ -| Format | Description | Notes | -+=============+==============================+=========+ -| ``gztar`` | gzipped tar file | (1),(3) | -| | (:file:`.tar.gz`) | | -+-------------+------------------------------+---------+ -| ``ztar`` | compressed tar file | \(3) | -| | (:file:`.tar.Z`) | | -+-------------+------------------------------+---------+ -| ``tar`` | tar file (:file:`.tar`) | \(3) | -+-------------+------------------------------+---------+ -| ``zip`` | zip file (:file:`.zip`) | (2),(4) | -+-------------+------------------------------+---------+ -| ``wininst`` | self-extracting ZIP file for | \(4) | -| | Windows | | -+-------------+------------------------------+---------+ -| ``msi`` | Microsoft Installer. | | -+-------------+------------------------------+---------+ - - -Notes: - -(1) - default on Unix - -(2) - default on Windows - -(3) - requires external utilities: :program:`tar` and possibly one of :program:`gzip`, - :program:`bzip2`, or :program:`compress` - -(4) - requires either external :program:`zip` utility or :mod:`zipfile` module (part - of the standard Python library since Python 1.6) - -You don't have to use the :command:`bdist` command with the :option:`--formats` -option; you can also use the command that directly implements the format you're -interested in. Some of these :command:`bdist` "sub-commands" actually generate -several similar formats; for instance, the :command:`bdist_dumb` command -generates all the "dumb" archive formats (``tar``, ``ztar``, ``gztar``, and -``zip``). The :command:`bdist` sub-commands, and the formats generated by -each, are: - -+--------------------------+-----------------------+ -| Command | Formats | -+==========================+=======================+ -| :command:`bdist_dumb` | tar, ztar, gztar, zip | -+--------------------------+-----------------------+ -| :command:`bdist_wininst` | wininst | -+--------------------------+-----------------------+ -| :command:`bdist_msi` | msi | -+--------------------------+-----------------------+ - -The following sections give details on the individual :command:`bdist_\*` -commands. - - -.. _packaging-creating-dumb: - -Creating dumb built distributions -================================= - -.. XXX Need to document absolute vs. prefix-relative packages here, but first - I have to implement it! - - -.. _packaging-creating-wininst: - -Creating Windows Installers -=========================== - -Executable installers are the natural format for binary distributions on -Windows. They display a nice graphical user interface, display some information -about the module distribution to be installed taken from the metadata in the -setup script, let the user select a few options, and start or cancel the -installation. - -Since the metadata is taken from the setup script, creating Windows installers -is usually as easy as running:: - - python setup.py bdist_wininst - -or the :command:`bdist` command with the :option:`--formats` option:: - - python setup.py bdist --formats=wininst - -If you have a pure module distribution (only containing pure Python modules and -packages), the resulting installer will be version independent and have a name -like :file:`foo-1.0.win32.exe`. These installers can even be created on Unix -platforms or Mac OS X. - -If you have a non-pure distribution, the extensions can only be created on a -Windows platform, and will be Python version dependent. The installer filename -will reflect this and now has the form :file:`foo-1.0.win32-py2.0.exe`. You -have to create a separate installer for every Python version you want to -support. - -.. TODO Add :term: markup to bytecode when merging into the stdlib - -The installer will try to compile pure modules into bytecode after installation -on the target system in normal and optimizing mode. If you don't want this to -happen for some reason, you can run the :command:`bdist_wininst` command with -the :option:`--no-target-compile` and/or the :option:`--no-target-optimize` -option. - -By default the installer will display the cool "Python Powered" logo when it is -run, but you can also supply your own 152x261 bitmap which must be a Windows -:file:`.bmp` file with the :option:`--bitmap` option. - -The installer will also display a large title on the desktop background window -when it is run, which is constructed from the name of your distribution and the -version number. This can be changed to another text by using the -:option:`--title` option. - -The installer file will be written to the "distribution directory" --- normally -:file:`dist/`, but customizable with the :option:`--dist-dir` option. - -.. _packaging-cross-compile-windows: - -Cross-compiling on Windows -========================== - -Starting with Python 2.6, packaging is capable of cross-compiling between -Windows platforms. In practice, this means that with the correct tools -installed, you can use a 32bit version of Windows to create 64bit extensions -and vice-versa. - -To build for an alternate platform, specify the :option:`--plat-name` option -to the build command. Valid values are currently 'win32', 'win-amd64' and -'win-ia64'. For example, on a 32bit version of Windows, you could execute:: - - python setup.py build --plat-name=win-amd64 - -to build a 64bit version of your extension. The Windows Installers also -support this option, so the command:: - - python setup.py build --plat-name=win-amd64 bdist_wininst - -would create a 64bit installation executable on your 32bit version of Windows. - -To cross-compile, you must download the Python source code and cross-compile -Python itself for the platform you are targetting - it is not possible from a -binary installtion of Python (as the .lib etc file for other platforms are -not included.) In practice, this means the user of a 32 bit operating -system will need to use Visual Studio 2008 to open the -:file:`PCBuild/PCbuild.sln` solution in the Python source tree and build the -"x64" configuration of the 'pythoncore' project before cross-compiling -extensions is possible. - -Note that by default, Visual Studio 2008 does not install 64bit compilers or -tools. You may need to reexecute the Visual Studio setup process and select -these tools (using Control Panel->[Add/Remove] Programs is a convenient way to -check or modify your existing install.) - -.. _packaging-postinstallation-script: - -The Postinstallation script ---------------------------- - -Starting with Python 2.3, a postinstallation script can be specified with the -:option:`--install-script` option. The basename of the script must be -specified, and the script filename must also be listed in the scripts argument -to the setup function. - -This script will be run at installation time on the target system after all the -files have been copied, with ``argv[1]`` set to :option:`-install`, and again at -uninstallation time before the files are removed with ``argv[1]`` set to -:option:`-remove`. - -The installation script runs embedded in the windows installer, every output -(``sys.stdout``, ``sys.stderr``) is redirected into a buffer and will be -displayed in the GUI after the script has finished. - -Some functions especially useful in this context are available as additional -built-in functions in the installation script. - -.. currentmodule:: bdist_wininst-postinst-script - -.. function:: directory_created(path) - file_created(path) - - These functions should be called when a directory or file is created by the - postinstall script at installation time. It will register *path* with the - uninstaller, so that it will be removed when the distribution is uninstalled. - To be safe, directories are only removed if they are empty. - - -.. function:: get_special_folder_path(csidl_string) - - This function can be used to retrieve special folder locations on Windows like - the Start Menu or the Desktop. It returns the full path to the folder. - *csidl_string* must be one of the following strings:: - - "CSIDL_APPDATA" - - "CSIDL_COMMON_STARTMENU" - "CSIDL_STARTMENU" - - "CSIDL_COMMON_DESKTOPDIRECTORY" - "CSIDL_DESKTOPDIRECTORY" - - "CSIDL_COMMON_STARTUP" - "CSIDL_STARTUP" - - "CSIDL_COMMON_PROGRAMS" - "CSIDL_PROGRAMS" - - "CSIDL_FONTS" - - If the folder cannot be retrieved, :exc:`OSError` is raised. - - Which folders are available depends on the exact Windows version, and probably - also the configuration. For details refer to Microsoft's documentation of the - c:function:`SHGetSpecialFolderPath` function. - - -.. function:: create_shortcut(target, description, filename[, arguments[, workdir[, iconpath[, iconindex]]]]) - - This function creates a shortcut. *target* is the path to the program to be - started by the shortcut. *description* is the description of the shortcut. - *filename* is the title of the shortcut that the user will see. *arguments* - specifies the command-line arguments, if any. *workdir* is the working directory - for the program. *iconpath* is the file containing the icon for the shortcut, - and *iconindex* is the index of the icon in the file *iconpath*. Again, for - details consult the Microsoft documentation for the :class:`IShellLink` - interface. - - -Vista User Access Control (UAC) -=============================== - -Starting with Python 2.6, bdist_wininst supports a :option:`--user-access-control` -option. The default is 'none' (meaning no UAC handling is done), and other -valid values are 'auto' (meaning prompt for UAC elevation if Python was -installed for all users) and 'force' (meaning always prompt for elevation). diff -r 2e49722c7263 -r 6944bdf1289a Doc/packaging/commandhooks.rst --- a/Doc/packaging/commandhooks.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -.. TODO integrate this in commandref and configfile - -============= -Command hooks -============= - -Packaging provides a way of extending its commands by the use of pre- and -post- command hooks. The hooks are simple Python functions (or any callable -objects) and are specified in the config file using their full qualified names. -The pre-hooks are run after the command is finalized (its options are -processed), but before it is run. The post-hooks are run after the command -itself. Both types of hooks receive an instance of the command object. - -See also global setup hooks in :ref:`setupcfg-spec`. - - -Sample usage of hooks -===================== - -Firstly, you need to make sure your hook is present in the path. This is usually -done by dropping them to the same folder where `setup.py` file lives :: - - # file: myhooks.py - def my_install_hook(install_cmd): - print "Oh la la! Someone is installing my project!" - -Then, you need to point to it in your `setup.cfg` file, under the appropriate -command section :: - - [install_dist] - pre-hook.project = myhooks.my_install_hook - -The hooks defined in different config files (system-wide, user-wide and -package-wide) do not override each other as long as they are specified with -different aliases (additional names after the dot). The alias in the example -above is ``project``. diff -r 2e49722c7263 -r 6944bdf1289a Doc/packaging/commandref.rst --- a/Doc/packaging/commandref.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,349 +0,0 @@ -.. _packaging-command-reference: - -***************** -Command Reference -***************** - -This reference briefly documents all standard Packaging commands and some of -their options. - -.. FIXME does not work: Use pysetup run --help-commands to list all - standard and extra commands availavble on your system, with their - description. Use pysetup run --help to get help about the options - of one command. - - -Preparing distributions -======================= - -:command:`check` ----------------- - -Perform some tests on the metadata of a distribution. - -For example, it verifies that all required metadata fields are provided in the -:file:`setup.cfg` file. - -.. TODO document reST checks - - -:command:`test` ---------------- - -Run a test suite. - -When doing test-driven development, or running automated builds that need -testing before they are installed for downloading or use, it's often useful to -be able to run a project's unit tests without actually installing the project -anywhere. The :command:`test` command runs project's unit tests without -actually installing it, by temporarily putting the project's source on -:data:`sys.path`, after first running :command:`build_ext -i` to ensure that any -C extensions are built. - -You can use this command in one of two ways: either by specifying a -unittest-compatible test suite for your project (or any callable that returns -it) or by passing a test runner function that will run your tests and display -results in the console. Both options take a Python dotted name in the form -``package.module.callable`` to specify the object to use. - -If none of these options are specified, Packaging will try to perform test -discovery using either unittest (for Python 3.2 and higher) or unittest2 (for -older versions, if installed). - -.. this is a pseudo-command name used to disambiguate the options in indexes and - links -.. program:: packaging test - -.. cmdoption:: --suite=NAME, -s NAME - - Specify the test suite (or module, class, or method) to be run. The default - for this option can be set by in the project's :file:`setup.cfg` file:: - - .. code-block:: cfg - - [test] - suite = mypackage.tests.get_all_tests - -.. cmdoption:: --runner=NAME, -r NAME - - Specify the test runner to be called. - - -:command:`config` ------------------ - -Perform distribution configuration. - - -The build step -============== - -This step is mainly useful to compile C/C++ libraries or extension modules. The -build commands can be run manually to check for syntax errors or packaging -issues (for example if the addition of a new source file was forgotten in the -:file:`setup.cfg` file), and is also run automatically by commands which need -it. Packaging checks the mtime of source and built files to avoid re-building -if it's not necessary. - - -:command:`build` ----------------- - -Build all files of a distribution, delegating to the other :command:`build_*` -commands to do the work. - - -:command:`build_clib` ---------------------- - -Build C libraries. - - -:command:`build_ext` --------------------- - -Build C/C++ extension modules. - - -:command:`build_py` -------------------- - -Build the Python modules (just copy them to the build directory) and -byte-compile them to .pyc files. - - -:command:`build_scripts` ------------------------- -Build the scripts (just copy them to the build directory and adjust their -shebang if they're Python scripts). - - -:command:`clean` ----------------- - -Clean the build tree of the release. - -.. program:: packaging clean - -.. cmdoption:: --all, -a - - Remove build directories for modules, scripts, etc., not only temporary build - by-products. - - -Creating source and built distributions -======================================= - -:command:`sdist` ----------------- - -Build a source distribution for a release. - -It is recommended that you always build and upload a source distribution. Users -of OSes with easy access to compilers and users of advanced packaging tools will -prefer to compile from source rather than using pre-built distributions. For -Windows users, providing a binary installer is also recommended practice. - - -:command:`bdist` ----------------- - -Build a binary distribution for a release. - -This command will call other :command:`bdist_*` commands to create one or more -distributions depending on the options given. The default is to create a -.tar.gz archive on Unix and a zip archive on Windows or OS/2. - -.. program:: packaging bdist - -.. cmdoption:: --formats - - Binary formats to build (comma-separated list). - -.. cmdoption:: --show-formats - - Dump list of available formats. - - -:command:`bdist_dumb` ---------------------- - -Build a "dumb" installer, a simple archive of files that could be unpacked under -``$prefix`` or ``$exec_prefix``. - - -:command:`bdist_wininst` ------------------------- - -Build a Windows installer. - - -:command:`bdist_msi` --------------------- - -Build a `Microsoft Installer`_ (.msi) file. - -.. _Microsoft Installer: http://msdn.microsoft.com/en-us/library/cc185688(VS.85).aspx - -In most cases, the :command:`bdist_msi` installer is a better choice than the -:command:`bdist_wininst` installer, because it provides better support for Win64 -platforms, allows administrators to perform non-interactive installations, and -allows installation through group policies. - - -Publishing distributions -======================== - -:command:`register` -------------------- - -This command registers the current release with the Python Package Index. This -is described in more detail in :PEP:`301`. - -.. TODO explain user and project registration with the web UI - - -:command:`upload` ------------------ - -Upload source and/or binary distributions to PyPI. - -The distributions have to be built on the same command line as the -:command:`upload` command; see :ref:`packaging-package-upload` for more info. - -.. program:: packaging upload - -.. cmdoption:: --sign, -s - - Sign each uploaded file using GPG (GNU Privacy Guard). The ``gpg`` program - must be available for execution on the system ``PATH``. - -.. cmdoption:: --identity=NAME, -i NAME - - Specify the identity or key name for GPG to use when signing. The value of - this option will be passed through the ``--local-user`` option of the - ``gpg`` program. - -.. cmdoption:: --show-response - - Display the full response text from server; this is useful for debugging - PyPI problems. - -.. cmdoption:: --repository=URL, -r URL - - The URL of the repository to upload to. Defaults to - http://pypi.python.org/pypi (i.e., the main PyPI installation). - -.. cmdoption:: --upload-docs - - Also run :command:`upload_docs`. Mainly useful as a default value in - :file:`setup.cfg` (on the command line, it's shorter to just type both - commands). - - -:command:`upload_docs` ----------------------- - -Upload HTML documentation to PyPI. - -PyPI now supports publishing project documentation at a URI of the form -``http://packages.python.org/``. :command:`upload_docs` will create -the necessary zip file out of a documentation directory and will post to the -repository. - -Note that to upload the documentation of a project, the corresponding version -must already be registered with PyPI, using the :command:`register` command --- -just like with :command:`upload`. - -Assuming there is an ``Example`` project with documentation in the subdirectory -:file:`docs`, for example:: - - Example/ - example.py - setup.cfg - docs/ - build/ - html/ - index.html - tips_tricks.html - conf.py - index.txt - tips_tricks.txt - -You can simply specify the directory with the HTML files in your -:file:`setup.cfg` file: - -.. code-block:: cfg - - [upload_docs] - upload-dir = docs/build/html - - -.. program:: packaging upload_docs - -.. cmdoption:: --upload-dir - - The directory to be uploaded to the repository. By default documentation - is searched for in ``docs`` (or ``doc``) directory in project root. - -.. cmdoption:: --show-response - - Display the full response text from server; this is useful for debugging - PyPI problems. - -.. cmdoption:: --repository=URL, -r URL - - The URL of the repository to upload to. Defaults to - http://pypi.python.org/pypi (i.e., the main PyPI installation). - - -The install step -================ - -These commands are used by end-users of a project using :program:`pysetup` or -another compatible installer. Each command will run the corresponding -:command:`build_*` command and then move the built files to their destination on -the target system. - - -:command:`install_dist` ------------------------ - -Install a distribution, delegating to the other :command:`install_*` commands to -do the work. - -.. program:: packaging install_dist - -.. cmdoption:: --user - - Install in user site-packages directory (see :PEP:`370`). - - -:command:`install_data` ------------------------ - -Install data files. - - -:command:`install_distinfo` ---------------------------- - -Install files recording details of the installation as specified in :PEP:`376`. - - -:command:`install_headers` --------------------------- - -Install C/C++ header files. - - -:command:`install_lib` ----------------------- - -Install C library files. - - -:command:`install_scripts` --------------------------- - -Install scripts. diff -r 2e49722c7263 -r 6944bdf1289a Doc/packaging/configfile.rst --- a/Doc/packaging/configfile.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,125 +0,0 @@ -.. _packaging-setup-config: - -************************************ -Writing the Setup Configuration File -************************************ - -Often, it's not possible to write down everything needed to build a distribution -*a priori*: you may need to get some information from the user, or from the -user's system, in order to proceed. As long as that information is fairly -simple---a list of directories to search for C header files or libraries, for -example---then providing a configuration file, :file:`setup.cfg`, for users to -edit is a cheap and easy way to solicit it. Configuration files also let you -provide default values for any command option, which the installer can then -override either on the command line or by editing the config file. - -The setup configuration file is a useful middle-ground between the setup script ----which, ideally, would be opaque to installers [#]_---and the command line to -the setup script, which is outside of your control and entirely up to the -installer. In fact, :file:`setup.cfg` (and any other Distutils configuration -files present on the target system) are processed after the contents of the -setup script, but before the command line. This has several useful -consequences: - -.. If you have more advanced needs, such as determining which extensions to - build based on what capabilities are present on the target system, then you - need the Distutils auto-configuration facility. This started to appear in - Distutils 0.9 but, as of this writing, isn't mature or stable enough yet - for real-world use. - -* installers can override some of what you put in :file:`setup.py` by editing - :file:`setup.cfg` - -* you can provide non-standard defaults for options that are not easily set in - :file:`setup.py` - -* installers can override anything in :file:`setup.cfg` using the command-line - options to :file:`setup.py` - -The basic syntax of the configuration file is simple:: - - [command] - option = value - ... - -where *command* is one of the Distutils commands (e.g. :command:`build_py`, -:command:`install_dist`), and *option* is one of the options that command supports. -Any number of options can be supplied for each command, and any number of -command sections can be included in the file. Blank lines are ignored, as are -comments, which run from a ``'#'`` character until the end of the line. Long -option values can be split across multiple lines simply by indenting the -continuation lines. - -You can find out the list of options supported by a particular command with the -universal :option:`--help` option, e.g. :: - - > python setup.py --help build_ext - [...] - Options for 'build_ext' command: - --build-lib (-b) directory for compiled extension modules - --build-temp (-t) directory for temporary files (build by-products) - --inplace (-i) ignore build-lib and put compiled extensions into the - source directory alongside your pure Python modules - --include-dirs (-I) list of directories to search for header files - --define (-D) C preprocessor macros to define - --undef (-U) C preprocessor macros to undefine - --swig-opts list of SWIG command-line options - [...] - -.. XXX do we want to support ``setup.py --help metadata``? - -Note that an option spelled :option:`--foo-bar` on the command line is spelled -:option:`foo_bar` in configuration files. - -For example, say you want your extensions to be built "in-place"---that is, you -have an extension :mod:`pkg.ext`, and you want the compiled extension file -(:file:`ext.so` on Unix, say) to be put in the same source directory as your -pure Python modules :mod:`pkg.mod1` and :mod:`pkg.mod2`. You can always use the -:option:`--inplace` option on the command line to ensure this:: - - python setup.py build_ext --inplace - -But this requires that you always specify the :command:`build_ext` command -explicitly, and remember to provide :option:`--inplace`. An easier way is to -"set and forget" this option, by encoding it in :file:`setup.cfg`, the -configuration file for this distribution:: - - [build_ext] - inplace = 1 - -This will affect all builds of this module distribution, whether or not you -explicitly specify :command:`build_ext`. If you include :file:`setup.cfg` in -your source distribution, it will also affect end-user builds---which is -probably a bad idea for this option, since always building extensions in-place -would break installation of the module distribution. In certain peculiar cases, -though, modules are built right in their installation directory, so this is -conceivably a useful ability. (Distributing extensions that expect to be built -in their installation directory is almost always a bad idea, though.) - -Another example: certain commands take options that vary from project to -project but not depending on the installation system, for example, -:command:`test` needs to know where your test suite is located and what test -runner to use; likewise, :command:`upload_docs` can find HTML documentation in -a :file:`doc` or :file:`docs` directory, but needs an option to find files in -:file:`docs/build/html`. Instead of having to type out these options each -time you want to run the command, you can put them in the project's -:file:`setup.cfg`:: - - [test] - suite = packaging.tests - - [upload_docs] - upload-dir = docs/build/html - - -.. seealso:: - - :ref:`packaging-config-syntax` in "Installing Python Projects" - More information on the configuration files is available in the manual for - system administrators. - - -.. rubric:: Footnotes - -.. [#] This ideal probably won't be achieved until auto-configuration is fully - supported by the Distutils. diff -r 2e49722c7263 -r 6944bdf1289a Doc/packaging/examples.rst --- a/Doc/packaging/examples.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,334 +0,0 @@ -.. _packaging-examples: - -******** -Examples -******** - -This chapter provides a number of basic examples to help get started with -Packaging. - - -.. _packaging-pure-mod: - -Pure Python distribution (by module) -==================================== - -If you're just distributing a couple of modules, especially if they don't live -in a particular package, you can specify them individually using the -:option:`py_modules` option in the setup script. - -In the simplest case, you'll have two files to worry about: a setup script and -the single module you're distributing, :file:`foo.py` in this example:: - - / - setup.py - foo.py - -(In all diagrams in this section, ** will refer to the distribution root -directory.) A minimal setup script to describe this situation would be:: - - from packaging.core import setup - setup(name='foo', - version='1.0', - py_modules=['foo']) - -Note that the name of the distribution is specified independently with the -:option:`name` option, and there's no rule that says it has to be the same as -the name of the sole module in the distribution (although that's probably a good -convention to follow). However, the distribution name is used to generate -filenames, so you should stick to letters, digits, underscores, and hyphens. - -Since :option:`py_modules` is a list, you can of course specify multiple -modules, e.g. if you're distributing modules :mod:`foo` and :mod:`bar`, your -setup might look like this:: - - / - setup.py - foo.py - bar.py - -and the setup script might be :: - - from packaging.core import setup - setup(name='foobar', - version='1.0', - py_modules=['foo', 'bar']) - -You can put module source files into another directory, but if you have enough -modules to do that, it's probably easier to specify modules by package rather -than listing them individually. - - -.. _packaging-pure-pkg: - -Pure Python distribution (by package) -===================================== - -If you have more than a couple of modules to distribute, especially if they are -in multiple packages, it's probably easier to specify whole packages rather than -individual modules. This works even if your modules are not in a package; you -can just tell the Distutils to process modules from the root package, and that -works the same as any other package (except that you don't have to have an -:file:`__init__.py` file). - -The setup script from the last example could also be written as :: - - from packaging.core import setup - setup(name='foobar', - version='1.0', - packages=['']) - -(The empty string stands for the root package.) - -If those two files are moved into a subdirectory, but remain in the root -package, e.g.:: - - / - setup.py - src/ - foo.py - bar.py - -then you would still specify the root package, but you have to tell the -Distutils where source files in the root package live:: - - from packaging.core import setup - setup(name='foobar', - version='1.0', - package_dir={'': 'src'}, - packages=['']) - -More typically, though, you will want to distribute multiple modules in the same -package (or in sub-packages). For example, if the :mod:`foo` and :mod:`bar` -modules belong in package :mod:`foobar`, one way to lay out your source tree is - -:: - - / - setup.py - foobar/ - __init__.py - foo.py - bar.py - -This is in fact the default layout expected by the Distutils, and the one that -requires the least work to describe in your setup script:: - - from packaging.core import setup - setup(name='foobar', - version='1.0', - packages=['foobar']) - -If you want to put modules in directories not named for their package, then you -need to use the :option:`package_dir` option again. For example, if the -:file:`src` directory holds modules in the :mod:`foobar` package:: - - / - setup.py - src/ - __init__.py - foo.py - bar.py - -an appropriate setup script would be :: - - from packaging.core import setup - setup(name='foobar', - version='1.0', - package_dir={'foobar': 'src'}, - packages=['foobar']) - -Or, you might put modules from your main package right in the distribution -root:: - - / - setup.py - __init__.py - foo.py - bar.py - -in which case your setup script would be :: - - from packaging.core import setup - setup(name='foobar', - version='1.0', - package_dir={'foobar': ''}, - packages=['foobar']) - -(The empty string also stands for the current directory.) - -If you have sub-packages, they must be explicitly listed in :option:`packages`, -but any entries in :option:`package_dir` automatically extend to sub-packages. -(In other words, the Distutils does *not* scan your source tree, trying to -figure out which directories correspond to Python packages by looking for -:file:`__init__.py` files.) Thus, if the default layout grows a sub-package:: - - / - setup.py - foobar/ - __init__.py - foo.py - bar.py - subfoo/ - __init__.py - blah.py - -then the corresponding setup script would be :: - - from packaging.core import setup - setup(name='foobar', - version='1.0', - packages=['foobar', 'foobar.subfoo']) - -(Again, the empty string in :option:`package_dir` stands for the current -directory.) - - -.. _packaging-single-ext: - -Single extension module -======================= - -Extension modules are specified using the :option:`ext_modules` option. -:option:`package_dir` has no effect on where extension source files are found; -it only affects the source for pure Python modules. The simplest case, a -single extension module in a single C source file, is:: - - / - setup.py - foo.c - -If the :mod:`foo` extension belongs in the root package, the setup script for -this could be :: - - from packaging.core import setup, Extension - setup(name='foobar', - version='1.0', - ext_modules=[Extension('foo', ['foo.c'])]) - -If the extension actually belongs in a package, say :mod:`foopkg`, then - -With exactly the same source tree layout, this extension can be put in the -:mod:`foopkg` package simply by changing the name of the extension:: - - from packaging.core import setup, Extension - setup(name='foobar', - version='1.0', - packages=['foopkg'], - ext_modules=[Extension('foopkg.foo', ['foo.c'])]) - - -Checking metadata -================= - -The ``check`` command allows you to verify if your project's metadata -meets the minimum requirements to build a distribution. - -To run it, just call it using your :file:`setup.py` script. If something is -missing, ``check`` will display a warning. - -Let's take an example with a simple script:: - - from packaging.core import setup - - setup(name='foobar') - -.. TODO configure logging StreamHandler to match this output - -Running the ``check`` command will display some warnings:: - - $ python setup.py check - running check - warning: check: missing required metadata: version, home_page - warning: check: missing metadata: either (author and author_email) or - (maintainer and maintainer_email) must be supplied - - -If you use the reStructuredText syntax in the ``long_description`` field and -`Docutils `_ is installed you can check if -the syntax is fine with the ``check`` command, using the ``restructuredtext`` -option. - -For example, if the :file:`setup.py` script is changed like this:: - - from packaging.core import setup - - desc = """\ - Welcome to foobar! - =============== - - This is the description of the ``foobar`` project. - """ - - setup(name='foobar', - version='1.0', - author=u'Tarek Ziadé', - author_email='tarek@ziade.org', - summary='Foobar utilities' - description=desc, - home_page='http://example.com') - -Where the long description is broken, ``check`` will be able to detect it -by using the :mod:`docutils` parser:: - - $ python setup.py check --restructuredtext - running check - warning: check: Title underline too short. (line 2) - warning: check: Could not finish the parsing. - - -.. _packaging-reading-metadata: - -Reading the metadata -==================== - -The :func:`packaging.core.setup` function provides a command-line interface -that allows you to query the metadata fields of a project through the -:file:`setup.py` script of a given project:: - - $ python setup.py --name - foobar - -This call reads the ``name`` metadata by running the -:func:`packaging.core.setup` function. When a source or binary -distribution is created with Distutils, the metadata fields are written -in a static file called :file:`PKG-INFO`. When a Distutils-based project is -installed in Python, the :file:`PKG-INFO` file is copied alongside the modules -and packages of the distribution under :file:`NAME-VERSION-pyX.X.egg-info`, -where ``NAME`` is the name of the project, ``VERSION`` its version as defined -in the Metadata, and ``pyX.X`` the major and minor version of Python like -``2.7`` or ``3.2``. - -You can read back this static file, by using the -:class:`packaging.dist.Metadata` class and its -:func:`read_pkg_file` method:: - - >>> from packaging.metadata import Metadata - >>> metadata = Metadata() - >>> metadata.read_pkg_file(open('distribute-0.6.8-py2.7.egg-info')) - >>> metadata.name - 'distribute' - >>> metadata.version - '0.6.8' - >>> metadata.description - 'Easily download, build, install, upgrade, and uninstall Python packages' - -Notice that the class can also be instantiated with a metadata file path to -loads its values:: - - >>> pkg_info_path = 'distribute-0.6.8-py2.7.egg-info' - >>> Metadata(pkg_info_path).name - 'distribute' - - -.. XXX These comments have been here for at least ten years. Write the - sections or delete the comments (we can maybe ask Greg Ward about - the planned contents). (Unindent to make them section titles) - - .. multiple-ext:: - - Multiple extension modules - ========================== - - Putting it all together - ======================= diff -r 2e49722c7263 -r 6944bdf1289a Doc/packaging/extending.rst --- a/Doc/packaging/extending.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -.. _extending-packaging: - -******************* -Extending Distutils -******************* - -Distutils can be extended in various ways. Most extensions take the form of new -commands or replacements for existing commands. New commands may be written to -support new types of platform-specific packaging, for example, while -replacements for existing commands may be made to modify details of how the -command operates on a package. - -Most extensions of the packaging are made within :file:`setup.py` scripts that -want to modify existing commands; many simply add a few file extensions that -should be copied into packages in addition to :file:`.py` files as a -convenience. - -Most packaging command implementations are subclasses of the -:class:`packaging.cmd.Command` class. New commands may directly inherit from -:class:`Command`, while replacements often derive from :class:`Command` -indirectly, directly subclassing the command they are replacing. Commands are -required to derive from :class:`Command`. - -.. .. _extend-existing: - Extending existing commands - =========================== - - -.. .. _new-commands: - Writing new commands - ==================== - - -Integrating new commands -======================== - -There are different ways to integrate new command implementations into -packaging. The most difficult is to lobby for the inclusion of the new features -in packaging itself, and wait for (and require) a version of Python that -provides that support. This is really hard for many reasons. - -The most common, and possibly the most reasonable for most needs, is to include -the new implementations with your :file:`setup.py` script, and cause the -:func:`packaging.core.setup` function use them:: - - from packaging.core import setup - from packaging.command.build_py import build_py as _build_py - - class build_py(_build_py): - """Specialized Python source builder.""" - - # implement whatever needs to be different... - - setup(..., cmdclass={'build_py': build_py}) - -This approach is most valuable if the new implementations must be used to use a -particular package, as everyone interested in the package will need to have the -new command implementation. - -Beginning with Python 2.4, a third option is available, intended to allow new -commands to be added which can support existing :file:`setup.py` scripts without -requiring modifications to the Python installation. This is expected to allow -third-party extensions to provide support for additional packaging systems, but -the commands can be used for anything packaging commands can be used for. A new -configuration option, :option:`command_packages` (command-line option -:option:`--command-packages`), can be used to specify additional packages to be -searched for modules implementing commands. Like all packaging options, this -can be specified on the command line or in a configuration file. This option -can only be set in the ``[global]`` section of a configuration file, or before -any commands on the command line. If set in a configuration file, it can be -overridden from the command line; setting it to an empty string on the command -line causes the default to be used. This should never be set in a configuration -file provided with a package. - -This new option can be used to add any number of packages to the list of -packages searched for command implementations; multiple package names should be -separated by commas. When not specified, the search is only performed in the -:mod:`packaging.command` package. When :file:`setup.py` is run with the option -:option:`--command-packages` :option:`distcmds,buildcmds`, however, the packages -:mod:`packaging.command`, :mod:`distcmds`, and :mod:`buildcmds` will be searched -in that order. New commands are expected to be implemented in modules of the -same name as the command by classes sharing the same name. Given the example -command-line option above, the command :command:`bdist_openpkg` could be -implemented by the class :class:`distcmds.bdist_openpkg.bdist_openpkg` or -:class:`buildcmds.bdist_openpkg.bdist_openpkg`. - - -Adding new distribution types -============================= - -Commands that create distributions (files in the :file:`dist/` directory) need -to add ``(command, filename)`` pairs to ``self.distribution.dist_files`` so that -:command:`upload` can upload it to PyPI. The *filename* in the pair contains no -path information, only the name of the file itself. In dry-run mode, pairs -should still be added to represent what would have been created. diff -r 2e49722c7263 -r 6944bdf1289a Doc/packaging/index.rst --- a/Doc/packaging/index.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -.. _packaging-index: - -############################## - Distributing Python Projects -############################## - -:Authors: The Fellowship of the Packaging -:Email: distutils-sig@python.org -:Release: |version| -:Date: |today| - -This document describes Packaging for Python authors, describing how to use the -module to make Python applications, packages or modules easily available to a -wider audience with very little overhead for build/release/install mechanics. - -.. toctree:: - :maxdepth: 2 - :numbered: - - tutorial - setupcfg - introduction - setupscript - configfile - sourcedist - builtdist - packageindex - uploading - examples - extending - commandhooks - commandref - - -.. seealso:: - - :ref:`packaging-install-index` - A user-centered manual which includes information on adding projects - into an existing Python installation. You do not need to be a Python - programmer to read this manual. - - :mod:`packaging` - A library reference for developers of packaging tools wanting to use - standalone building blocks like :mod:`~packaging.version` or - :mod:`~packaging.metadata`, or extend Packaging itself. diff -r 2e49722c7263 -r 6944bdf1289a Doc/packaging/introduction.rst --- a/Doc/packaging/introduction.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,193 +0,0 @@ -.. _packaging-intro: - -***************************** -An Introduction to Packaging -***************************** - -This document covers using Packaging to distribute your Python modules, -concentrating on the role of developer/distributor. If you're looking for -information on installing Python modules you should refer to the -:ref:`packaging-install-index` chapter. - -Throughout this documentation, the terms "Distutils", "the Distutils" and -"Packaging" will be used interchangeably. - -.. _packaging-concepts: - -Concepts & Terminology -====================== - -Using Distutils is quite simple both for module developers and for -users/administrators installing third-party modules. As a developer, your -responsibilities (apart from writing solid, well-documented and well-tested -code, of course!) are: - -* writing a setup script (:file:`setup.py` by convention) - -* (optional) writing a setup configuration file - -* creating a source distribution - -* (optional) creating one or more "built" (binary) distributions of your - project - -All of these tasks are covered in this document. - -Not all module developers have access to multiple platforms, so one cannot -expect them to create buildt distributions for every platform. To remedy -this, it is hoped that intermediaries called *packagers* will arise to address -this need. Packagers take source distributions released by module developers, -build them on one or more platforms and release the resulting built -distributions. Thus, users on a greater range of platforms will be able to -install the most popular Python modules in the most natural way for their -platform without having to run a setup script or compile a single line of code. - - -.. _packaging-simple-example: - -A Simple Example -================ - -A setup script is usually quite simple, although since it's written in Python -there are no arbitrary limits to what you can do with it, though you should be -careful about putting expensive operations in your setup script. -Unlike, say, Autoconf-style configure scripts the setup script may be run -multiple times in the course of building and installing a module -distribution. - -If all you want to do is distribute a module called :mod:`foo`, contained in a -file :file:`foo.py`, then your setup script can be as simple as:: - - from packaging.core import setup - setup(name='foo', - version='1.0', - py_modules=['foo']) - -Some observations: - -* most information that you supply to the Distutils is supplied as keyword - arguments to the :func:`setup` function - -* those keyword arguments fall into two categories: package metadata (name, - version number, etc.) and information about what's in the package (a list - of pure Python modules in this case) - -* modules are specified by module name, not filename (the same will hold true - for packages and extensions) - -* it's recommended that you supply a little more metadata than we have in the - example. In particular your name, email address and a URL for the - project if appropriate (see section :ref:`packaging-setup-script` for an example) - -To create a source distribution for this module you would create a setup -script, :file:`setup.py`, containing the above code and run:: - - python setup.py sdist - -which will create an archive file (e.g., tarball on Unix, ZIP file on Windows) -containing your setup script :file:`setup.py`, and your module :file:`foo.py`. -The archive file will be named :file:`foo-1.0.tar.gz` (or :file:`.zip`), and -will unpack into a directory :file:`foo-1.0`. - -If an end-user wishes to install your :mod:`foo` module all he has to do is -download :file:`foo-1.0.tar.gz` (or :file:`.zip`), unpack it, and from the -:file:`foo-1.0` directory run :: - - python setup.py install - -which will copy :file:`foo.py` to the appropriate directory for -third-party modules in their Python installation. - -This simple example demonstrates some fundamental concepts of Distutils. -First, both developers and installers have the same basic user interface, i.e. -the setup script. The difference is which Distutils *commands* they use: the -:command:`sdist` command is almost exclusively for module developers, while -:command:`install` is more often used by installers (although some developers -will want to install their own code occasionally). - -If you want to make things really easy for your users, you can create more -than one built distributions for them. For instance, if you are running on a -Windows machine and want to make things easy for other Windows users, you can -create an executable installer (the most appropriate type of built distribution -for this platform) with the :command:`bdist_wininst` command. For example:: - - python setup.py bdist_wininst - -will create an executable installer, :file:`foo-1.0.win32.exe`, in the current -directory. You can find out what distribution formats are available at any time -by running :: - - python setup.py bdist --help-formats - - -.. _packaging-python-terms: - -General Python terminology -========================== - -If you're reading this document, you probably have a good idea of what Python -modules, extensions and so forth are. Nevertheless, just to be sure that -everyone is on the same page, here's a quick overview of Python terms: - -module - The basic unit of code reusability in Python: a block of code imported by - some other code. Three types of modules are important to us here: pure - Python modules, extension modules and packages. - -pure Python module - A module written in Python and contained in a single :file:`.py` file (and - possibly associated :file:`.pyc` and/or :file:`.pyo` files). Sometimes - referred to as a "pure module." - -extension module - A module written in the low-level language of the Python implementation: C/C++ - for Python, Java for Jython. Typically contained in a single dynamically - loaded pre-compiled file, e.g. a shared object (:file:`.so`) file for Python - extensions on Unix, a DLL (given the :file:`.pyd` extension) for Python - extensions on Windows, or a Java class file for Jython extensions. Note that - currently Distutils only handles C/C++ extensions for Python. - -package - A module that contains other modules, typically contained in a directory of - the filesystem and distinguished from other directories by the presence of a - file :file:`__init__.py`. - -root package - The root of the hierarchy of packages. (This isn't really a package, - since it doesn't have an :file:`__init__.py` file. But... we have to - call it something, right?) The vast majority of the standard library is - in the root package, as are many small standalone third-party modules that - don't belong to a larger module collection. Unlike regular packages, - modules in the root package can be found in many directories: in fact, - every directory listed in ``sys.path`` contributes modules to the root - package. - - -.. _packaging-term: - -Distutils-specific terminology -============================== - -The following terms apply more specifically to the domain of distributing Python -modules using Distutils: - -module distribution - A collection of Python modules distributed together as a single downloadable - resource and meant to be installed all as one. Examples of some well-known - module distributions are NumPy, SciPy, PIL (the Python Imaging - Library) or mxBase. (Module distributions would be called a *package*, - except that term is already taken in the Python context: a single module - distribution may contain zero, one, or many Python packages.) - -pure module distribution - A module distribution that contains only pure Python modules and packages. - Sometimes referred to as a "pure distribution." - -non-pure module distribution - A module distribution that contains at least one extension module. Sometimes - referred to as a "non-pure distribution." - -distribution root - The top-level directory of your source tree (or source distribution). The - directory where :file:`setup.py` exists. Generally :file:`setup.py` will - be run from this directory. diff -r 2e49722c7263 -r 6944bdf1289a Doc/packaging/packageindex.rst --- a/Doc/packaging/packageindex.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +0,0 @@ -.. _packaging-package-index: - -********************************** -Registering with the Package Index -********************************** - -The Python Package Index (PyPI) holds metadata describing distributions -packaged with packaging. The packaging command :command:`register` is used to -submit your distribution's metadata to the index. It is invoked as follows:: - - python setup.py register - -Distutils will respond with the following prompt:: - - running register - We need to know who you are, so please choose either: - 1. use your existing login, - 2. register as a new user, - 3. have the server generate a new password for you (and email it to you), or - 4. quit - Your selection [default 1]: - -Note: if your username and password are saved locally, you will not see this -menu. - -If you have not registered with PyPI, then you will need to do so now. You -should choose option 2, and enter your details as required. Soon after -submitting your details, you will receive an email which will be used to confirm -your registration. - -Once you are registered, you may choose option 1 from the menu. You will be -prompted for your PyPI username and password, and :command:`register` will then -submit your metadata to the index. - -You may submit any number of versions of your distribution to the index. If you -alter the metadata for a particular version, you may submit it again and the -index will be updated. - -PyPI holds a record for each (name, version) combination submitted. The first -user to submit information for a given name is designated the Owner of that -name. They may submit changes through the :command:`register` command or through -the web interface. They may also designate other users as Owners or Maintainers. -Maintainers may edit the package information, but not designate other Owners or -Maintainers. - -By default PyPI will list all versions of a given package. To hide certain -versions, the Hidden property should be set to yes. This must be edited through -the web interface. - - -.. _packaging-pypirc: - -The .pypirc file -================ - -The format of the :file:`.pypirc` file is as follows:: - - [packaging] - index-servers = - pypi - - [pypi] - repository: - username: - password: - -The *packaging* section defines a *index-servers* variable that lists the -name of all sections describing a repository. - -Each section describing a repository defines three variables: - -- *repository*, that defines the url of the PyPI server. Defaults to - ``http://www.python.org/pypi``. -- *username*, which is the registered username on the PyPI server. -- *password*, that will be used to authenticate. If omitted the user - will be prompt to type it when needed. - -If you want to define another server a new section can be created and -listed in the *index-servers* variable:: - - [packaging] - index-servers = - pypi - other - - [pypi] - repository: - username: - password: - - [other] - repository: http://example.com/pypi - username: - password: - -:command:`register` can then be called with the -r option to point the -repository to work with:: - - python setup.py register -r http://example.com/pypi - -For convenience, the name of the section that describes the repository -may also be used:: - - python setup.py register -r other diff -r 2e49722c7263 -r 6944bdf1289a Doc/packaging/setupcfg.rst --- a/Doc/packaging/setupcfg.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,854 +0,0 @@ -.. highlightlang:: cfg - -.. _setupcfg-spec: - -******************************************* -Specification of the :file:`setup.cfg` file -******************************************* - -:version: 0.9 - -This document describes the :file:`setup.cfg`, an ini-style configuration file -used by Packaging to replace the :file:`setup.py` file used by Distutils. -This specification is language-agnostic, and will therefore repeat some -information that's already documented for Python in the -:class:`configparser.RawConfigParser` documentation. - -.. contents:: - :depth: 3 - :local: - - -Syntax -====== - -The ini-style format used in the configuration file is a simple collection of -sections that group sets of key-value fields separated by ``=`` or ``:`` and -optional whitespace. Lines starting with ``#`` or ``;`` are comments and will -be ignored. Empty lines are also ignored. Example:: - - [section1] - # comment - name = value - name2 = "other value" - - [section2] - foo = bar - - -Parsing values ---------------- - -Here are a set of rules to parse values: - -- If a value is quoted with ``"`` chars, it's a string. If a quote character is - present in the quoted value, it can be escaped as ``\"`` or left as-is. - -- If the value is ``true``, ``t``, ``yes``, ``y`` (case-insensitive) or ``1``, - it's converted to the language equivalent of a ``True`` value; if it's - ``false``, ``f``, ``no``, ``n`` (case-insensitive) or ``0``, it's converted to - the equivalent of ``False``. - -- A value can contain multiple lines. When read, lines are converted into a - sequence of values. Each line after the first must start with a least one - space or tab character; this leading indentation will be stripped. - -- All other values are considered strings. - -Examples:: - - [section] - foo = one - two - three - - bar = false - baz = 1.3 - boo = "ok" - beee = "wqdqw pojpj w\"ddq" - - -Extending files ---------------- - -A configuration file can be extended (i.e. included) by other files. For this, -a ``DEFAULT`` section must contain an ``extends`` key which value points to one -or more files which will be merged into the current files by adding new sections -and fields. If a file loaded by ``extends`` contains sections or keys that -already exist in the original file, they will not override the previous values. - -Contents of :file:`one.cfg`:: - - [section1] - name = value - - [section2] - foo = foo from one.cfg - -Contents of :file:`two.cfg`:: - - [DEFAULT] - extends = one.cfg - - [section2] - foo = foo from two.cfg - baz = baz from two.cfg - -The result of parsing :file:`two.cfg` is equivalent to this file:: - - [section1] - name = value - - [section2] - foo = foo from one.cfg - baz = baz from two.cfg - -Example use of multi-line notation to include more than one file:: - - [DEFAULT] - extends = one.cfg - two.cfg - -When several files are provided, they are processed sequentially, following the -precedence rules explained above. This means that the list of files should go -from most specialized to most common. - -**Tools will need to provide a way to produce a merged version of the -file**. This will be useful to let users publish a single file. - - -Description of sections and fields -================================== - -Each section contains a description of its options. - -- Options that are marked *multi* can have multiple values, one value per - line. -- Options that are marked *optional* can be omitted. -- Options that are marked *environ* can use environment markers, as described - in :PEP:`345`. - - -The sections are: - -global - Global options not related to one command. - -metadata - Name, version and other information defined by :PEP:`345`. - -files - Modules, scripts, data, documentation and other files to include in the - distribution. - -extension sections - Options used to build extension modules. - -command sections - Options given for specific commands, identical to those that can be given - on the command line. - - -Global options --------------- - -Contains global options for Packaging. This section is shared with Distutils. - - -commands - Defined Packaging command. A command is defined by its fully - qualified name. *optional*, *multi* - - Examples:: - - [global] - commands = - package.setup.CustomSdistCommand - package.setup.BdistDeb - -compilers - Defined Packaging compiler. A compiler is defined by its fully - qualified name. *optional*, *multi* - - Example:: - - [global] - compilers = - hotcompiler.SmartCCompiler - -setup_hook - defines a callable that will be called right after the - :file:`setup.cfg` file is read. The callable receives the configuration - in form of a mapping and can make some changes to it. *optional* - - Example:: - - [global] - setup_hook = package.setup.customize_dist - - -Metadata --------- - -The metadata section contains the metadata for the project as described in -:PEP:`345`. Field names are case-insensitive. - -Fields: - -name - Name of the project. - -version - Version of the project. Must comply with :PEP:`386`. - -platform - Platform specification describing an operating system - supported by the distribution which is not listed in the "Operating System" - Trove classifiers (:PEP:`301`). *optional*, *multi* - -supported-platform - Binary distributions containing a PKG-INFO file will - use the Supported-Platform field in their metadata to specify the OS and - CPU for which the binary distribution was compiled. The semantics of - the Supported-Platform field are free form. *optional*, *multi* - -summary - A one-line summary of what the distribution does. - (Used to be called *description* in Distutils1.) - -description - A longer description. (Used to be called *long_description* - in Distutils1.) A file can be provided in the *description-file* field. - *optional* - -keywords - A list of additional keywords to be used to assist searching - for the distribution in a larger catalog. Comma or space-separated. - *optional* - -home-page - The URL for the distribution's home page. - -download-url - The URL from which this version of the distribution - can be downloaded. *optional* - -author - Author's name. *optional* - -author-email - Author's e-mail. *optional* - -maintainer - Maintainer's name. *optional* - -maintainer-email - Maintainer's e-mail. *optional* - -license - A text indicating the term of uses, when a trove classifier does - not match. *optional*. - -classifiers - Classification for the distribution, as described in PEP 301. - *optional*, *multi*, *environ* - -requires-dist - name of another packaging project required as a dependency. - The format is *name (version)* where version is an optional - version declaration, as described in PEP 345. *optional*, *multi*, *environ* - -provides-dist - name of another packaging project contained within this - distribution. Same format than *requires-dist*. *optional*, *multi*, - *environ* - -obsoletes-dist - name of another packaging project this version obsoletes. - Same format than *requires-dist*. *optional*, *multi*, *environ* - -requires-python - Specifies the Python version the distribution requires. The value is a - comma-separated list of version predicates, as described in PEP 345. - *optional*, *environ* - -requires-externals - a dependency in the system. This field is free-form, - and just a hint for downstream maintainers. *optional*, *multi*, - *environ* - -project-url - A label, followed by a browsable URL for the project. - "label, url". The label is limited to 32 signs. *optional*, *multi* - -One extra field not present in PEP 345 is supported: - -description-file - Path to a text file that will be used to fill the ``description`` field. - ``description-file`` and ``description`` are mutually exclusive. *optional* - - - -Example:: - - [metadata] - name = pypi2rpm - version = 0.1 - author = Tarek Ziadé - author-email = tarek@ziade.org - summary = Script that transforms an sdist archive into a RPM package - description-file = README - home-page = http://bitbucket.org/tarek/pypi2rpm/wiki/Home - project-url: - Repository, http://bitbucket.org/tarek/pypi2rpm/ - RSS feed, https://bitbucket.org/tarek/pypi2rpm/rss - classifier = - Development Status :: 3 - Alpha - License :: OSI Approved :: Mozilla Public License 1.1 (MPL 1.1) - -You should not give any explicit value for metadata-version: it will be guessed -from the fields present in the file. - - -Files ------ - -This section describes the files included in the project. - -packages_root - the root directory containing all packages and modules - (default: current directory). *optional* - -packages - a list of packages the project includes *optional*, *multi* - -modules - a list of packages the project includes *optional*, *multi* - -scripts - a list of scripts the project includes *optional*, *multi* - -extra_files - a list of patterns to include extra files *optional*, - *multi* - -Example:: - - [files] - packages_root = src - packages = - pypi2rpm - pypi2rpm.command - - scripts = - pypi2rpm/pypi2rpm.py - - extra_files = - setup.py - README - - -.. Note:: - The :file:`setup.cfg` configuration file is included by default. Contrary to - Distutils, :file:`README` (or :file:`README.txt`) and :file:`setup.py` are - not included by default. - - -Resources -^^^^^^^^^ - -This section describes the files used by the project which must not be installed -in the same place that python modules or libraries, they are called -**resources**. They are for example documentation files, script files, -databases, etc... - -For declaring resources, you must use this notation:: - - source = destination - -Data-files are declared in the **resources** field in the **file** section, for -example:: - - [files] - resources = - source1 = destination1 - source2 = destination2 - -The **source** part of the declaration are relative paths of resources files -(using unix path separator **/**). For example, if you've this source tree:: - - foo/ - doc/ - doc.man - scripts/ - foo.sh - -Your setup.cfg will look like:: - - [files] - resources = - doc/doc.man = destination_doc - scripts/foo.sh = destination_scripts - -The final paths where files will be placed are composed by : **source** + -**destination**. In the previous example, **doc/doc.man** will be placed in -**destination_doc/doc/doc.man** and **scripts/foo.sh** will be placed in -**destination_scripts/scripts/foo.sh**. (If you want more control on the final -path, take a look at :ref:`setupcfg-resources-base-prefix`). - -The **destination** part of resources declaration are paths with categories. -Indeed, it's generally a bad idea to give absolute path as it will be cross -incompatible. So, you must use resources categories in your **destination** -declaration. Categories will be replaced by their real path at the installation -time. Using categories is all benefit, your declaration will be simpler, cross -platform and it will allow packager to place resources files where they want -without breaking your code. - -Categories can be specified by using this syntax:: - - {category} - -Default categories are: - -* config -* appdata -* appdata.arch -* appdata.persistent -* appdata.disposable -* help -* icon -* scripts -* doc -* info -* man - -A special category also exists **{distribution.name}** that will be replaced by -the name of the distribution, but as most of the defaults categories use them, -so it's not necessary to add **{distribution.name}** into your destination. - -If you use categories in your declarations, and you are encouraged to do, final -path will be:: - - source + destination_expanded - -.. _example_final_path: - -For example, if you have this setup.cfg:: - - [metadata] - name = foo - - [files] - resources = - doc/doc.man = {doc} - -And if **{doc}** is replaced by **{datadir}/doc/{distribution.name}**, final -path will be:: - - {datadir}/doc/foo/doc/doc.man - -Where {datafir} category will be platform-dependent. - - -More control on source part -""""""""""""""""""""""""""" - -Glob syntax -''''''''''' - -When you declare source file, you can use a glob-like syntax to match multiples file, for example:: - - scripts/* = {script} - -Will match all the files in the scripts directory and placed them in the script category. - -Glob tokens are: - - * ``*``: match all files. - * ``?``: match any character. - * ``**``: match any level of tree recursion (even 0). - * ``{}``: will match any part separated by comma (example: ``{sh,bat}``). - -.. TODO Add examples - -Order of declaration -'''''''''''''''''''' - -The order of declaration is important if one file match multiple rules. The last -rules matched by file is used, this is useful if you have this source tree:: - - foo/ - doc/ - index.rst - setup.rst - documentation.txt - doc.tex - README - -And you want all the files in the doc directory to be placed in {doc} category, -but README must be placed in {help} category, instead of listing all the files -one by one, you can declare them in this way:: - - [files] - resources = - doc/* = {doc} - doc/README = {help} - -Exclude -''''''' - -You can exclude some files of resources declaration by giving no destination, it -can be useful if you have a non-resources file in the same directory of -resources files:: - - foo/ - doc/ - RELEASES - doc.tex - documentation.txt - docu.rst - -Your **files** section will be:: - - [files] - resources = - doc/* = {doc} - doc/RELEASES = - -More control on destination part -"""""""""""""""""""""""""""""""" - -.. _setupcfg-resources-base-prefix: - -Defining a base prefix -'''''''''''''''''''''' - -When you define your resources, you can have more control of how the final path -is computed. - -By default, the final path is:: - - destination + source - -This can generate long paths, for example (example_final_path_):: - - {datadir}/doc/foo/doc/doc.man - -When you declare your source, you can use whitespace to split the source in -**prefix** **suffix**. So, for example, if you have this source:: - - docs/ doc.man - -The **prefix** is "docs/" and the **suffix** is "doc.html". - -.. note:: - - Separator can be placed after a path separator or replace it. So these two - sources are equivalent:: - - docs/ doc.man - docs doc.man - -.. note:: - - Glob syntax is working the same way with standard source and split source. - So these rules:: - - docs/* - docs/ * - docs * - - Will match all the files in the docs directory. - -When you use split source, the final path is computed this way:: - - destination + prefix - -So for example, if you have this setup.cfg:: - - [metadata] - name = foo - - [files] - resources = - doc/ doc.man = {doc} - -And if **{doc}** is replaced by **{datadir}/doc/{distribution.name}**, final -path will be:: - - {datadir}/doc/foo/doc.man - - -Overwriting paths for categories -"""""""""""""""""""""""""""""""" - -This part is intended for system administrators or downstream OS packagers. - -The real paths of categories are registered in the *sysconfig.cfg* file -installed in your python installation. This file uses an ini format too. -The content of the file is organized into several sections: - -* globals: Standard categories's paths. -* posix_prefix: Standard paths for categories and installation paths for posix - system. -* other ones XXX - -Standard categories paths are platform independent, they generally refers to -other categories, which are platform dependent. :mod:`sysconfig` will choose -these category from sections matching os.name. For example:: - - doc = {datadir}/doc/{distribution.name} - -It refers to datadir category, which can be different between platforms. In -posix system, it may be:: - - datadir = /usr/share - -So the final path will be:: - - doc = /usr/share/doc/{distribution.name} - -The platform-dependent categories are: - -* confdir -* datadir -* libdir -* base - - -Defining extra categories -""""""""""""""""""""""""" - -.. TODO - - -Examples -"""""""" - -These examples are incremental but work unitarily. - -Resources in root dir -''''''''''''''''''''' - -Source tree:: - - babar-1.0/ - README - babar.sh - launch.sh - babar.py - -:file:`setup.cfg`:: - - [files] - resources = - README = {doc} - *.sh = {scripts} - -So babar.sh and launch.sh will be placed in {scripts} directory. - -Now let's move all the scripts into a scripts directory. - -Resources in sub-directory -'''''''''''''''''''''''''' - -Source tree:: - - babar-1.1/ - README - scripts/ - babar.sh - launch.sh - LAUNCH - babar.py - -:file:`setup.cfg`:: - - [files] - resources = - README = {doc} - scripts/ LAUNCH = {doc} - scripts/ *.sh = {scripts} - -It's important to use the separator after scripts/ to install all the shell -scripts into {scripts} instead of {scripts}/scripts. - -Now let's add some docs. - -Resources in multiple sub-directories -''''''''''''''''''''''''''''''''''''' - -Source tree:: - - babar-1.2/ - README - scripts/ - babar.sh - launch.sh - LAUNCH - docs/ - api - man - babar.py - -:file:`setup.cfg`:: - - [files] - resources = - README = {doc} - scripts/ LAUNCH = {doc} - scripts/ *.sh = {scripts} - doc/ * = {doc} - doc/ man = {man} - -You want to place all the file in the docs script into {doc} category, instead -of man, which must be placed into {man} category, we will use the order of -declaration of globs to choose the destination, the last glob that match the -file is used. - -Now let's add some scripts for windows users. - -Complete example -'''''''''''''''' - -Source tree:: - - babar-1.3/ - README - doc/ - api - man - scripts/ - babar.sh - launch.sh - babar.bat - launch.bat - LAUNCH - -:file:`setup.cfg`:: - - [files] - resources = - README = {doc} - scripts/ LAUNCH = {doc} - scripts/ *.{sh,bat} = {scripts} - doc/ * = {doc} - doc/ man = {man} - -We use brace expansion syntax to place all the shell and batch scripts into -{scripts} category. - - -Extension sections ------------------- - -If a project includes extension modules written in C or C++, each one of them -needs to have its options defined in a dedicated section. Here's an example:: - - [files] - packages = coconut - - [extension=_fastcoconut] - name = coconut._fastcoconut - language = cxx - sources = cxx_src/cononut_utils.cxx - cxx_src/python_module.cxx - include_dirs = /usr/include/gecode - /usr/include/blitz - extra_compile_args = - -fPIC -O2 - -DGECODE_VERSION=$(./gecode_version) -- sys.platform != 'win32' - /DGECODE_VERSION='win32' -- sys.platform == 'win32' - -The section name must start with ``extension=``; the righ-hand part is currently -discarded. Valid fields and their values are listed in the documentation of the -:class:`packaging.compiler.extension.Extension` class; values documented as -Python lists translate to multi-line values in the configuration file. In -addition, multi-line values accept environment markers on each line, after a -``--``. - - -Command sections ----------------- - -To pass options to commands without having to type them on the command line -for each invocation, you can write them in the :file:`setup.cfg` file, in a -section named after the command. Example:: - - [sdist] - # special function to add custom files - manifest-builders = package.setup.list_extra_files - - [build] - use-2to3 = True - - [build_ext] - inplace = on - - [check] - strict = on - all = on - -Option values given in the configuration file can be overriden on the command -line. See :ref:`packaging-setup-config` for more information. - - -Extensibility -============= - -Every section can have fields that are not part of this specification. They are -called **extensions**. - -An extension field starts with ``X-``. Example:: - - [metadata] - name = Distribute - X-Debian-Name = python-distribute - - -Changes in the specification -============================ - -The versioning scheme for this specification is **MAJOR.MINOR**. Changes in the -specification will cause the version number to be updated. - -Changes to the minor number reflect backwards-compatible changes: - -- New fields and sections (optional or mandatory) can be added. -- Optional fields can be removed. - -The major number will be incremented for backwards-incompatible changes: - -- Mandatory fields or sections are removed. -- Fields change their meaning. - -As a consequence, a tool written to consume 1.5 has these properties: - -- Can read 1.1, 1.2 and all versions < 1.5, since the tool knows what - optional fields weren't there. - - .. XXX clarify - -- Can also read 1.6 and other 1.x versions: The tool will just ignore fields it - doesn't know about, even if they are mandatory in the new version. If - optional fields were removed, the tool will just consider them absent. - -- Cannot read 2.x and should refuse to interpret such files. - -A tool written to produce 1.x should have these properties: - -- Writes all mandatory fields. -- May write optional fields. - - -Acknowledgments -=============== - -This specification includes work and feedback from these people: - -- Tarek Ziadé -- Julien Jehannet -- Boris Feld -- Éric Araujo - -(If your name is missing, please :ref:`let us know `.) diff -r 2e49722c7263 -r 6944bdf1289a Doc/packaging/setupscript.rst --- a/Doc/packaging/setupscript.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,689 +0,0 @@ -.. _packaging-setup-script: - -************************ -Writing the Setup Script -************************ - -The setup script is the center of all activity in building, distributing, and -installing modules using Distutils. The main purpose of the setup script is -to describe your module distribution to Distutils, so that the various -commands that operate on your modules do the right thing. As we saw in section -:ref:`packaging-simple-example`, the setup script consists mainly of a -call to :func:`setup` where the most information is supplied as -keyword arguments to :func:`setup`. - -Here's a slightly more involved example, which we'll follow for the next couple -of sections: a setup script that could be used for Packaging itself:: - - #!/usr/bin/env python - - from packaging.core import setup, find_packages - - setup(name='Packaging', - version='1.0', - summary='Python Distribution Utilities', - keywords=['packaging', 'packaging'], - author=u'Tarek Ziadé', - author_email='tarek@ziade.org', - home_page='http://bitbucket.org/tarek/packaging/wiki/Home', - license='PSF', - packages=find_packages()) - - -There are only two differences between this and the trivial one-file -distribution presented in section :ref:`packaging-simple-example`: more -metadata and the specification of pure Python modules by package rather than -by module. This is important since Ristutils consist of a couple of dozen -modules split into (so far) two packages; an explicit list of every module -would be tedious to generate and difficult to maintain. For more information -on the additional metadata, see section :ref:`packaging-metadata`. - -Note that any pathnames (files or directories) supplied in the setup script -should be written using the Unix convention, i.e. slash-separated. The -Distutils will take care of converting this platform-neutral representation into -whatever is appropriate on your current platform before actually using the -pathname. This makes your setup script portable across operating systems, which -of course is one of the major goals of the Distutils. In this spirit, all -pathnames in this document are slash-separated. - -This, of course, only applies to pathnames given to Distutils functions. If -you, for example, use standard Python functions such as :func:`glob.glob` or -:func:`os.listdir` to specify files, you should be careful to write portable -code instead of hardcoding path separators:: - - glob.glob(os.path.join('mydir', 'subdir', '*.html')) - os.listdir(os.path.join('mydir', 'subdir')) - - -.. _packaging-listing-packages: - -Listing whole packages -====================== - -The :option:`packages` option tells the Distutils to process (build, distribute, -install, etc.) all pure Python modules found in each package mentioned in the -:option:`packages` list. In order to do this, of course, there has to be a -correspondence between package names and directories in the filesystem. The -default correspondence is the most obvious one, i.e. package :mod:`packaging` is -found in the directory :file:`packaging` relative to the distribution root. -Thus, when you say ``packages = ['foo']`` in your setup script, you are -promising that the Distutils will find a file :file:`foo/__init__.py` (which -might be spelled differently on your system, but you get the idea) relative to -the directory where your setup script lives. If you break this promise, the -Distutils will issue a warning but still process the broken package anyways. - -If you use a different convention to lay out your source directory, that's no -problem: you just have to supply the :option:`package_dir` option to tell the -Distutils about your convention. For example, say you keep all Python source -under :file:`lib`, so that modules in the "root package" (i.e., not in any -package at all) are in :file:`lib`, modules in the :mod:`foo` package are in -:file:`lib/foo`, and so forth. Then you would put :: - - package_dir = {'': 'lib'} - -in your setup script. The keys to this dictionary are package names, and an -empty package name stands for the root package. The values are directory names -relative to your distribution root. In this case, when you say ``packages = -['foo']``, you are promising that the file :file:`lib/foo/__init__.py` exists. - -Another possible convention is to put the :mod:`foo` package right in -:file:`lib`, the :mod:`foo.bar` package in :file:`lib/bar`, etc. This would be -written in the setup script as :: - - package_dir = {'foo': 'lib'} - -A ``package: dir`` entry in the :option:`package_dir` dictionary implicitly -applies to all packages below *package*, so the :mod:`foo.bar` case is -automatically handled here. In this example, having ``packages = ['foo', -'foo.bar']`` tells the Distutils to look for :file:`lib/__init__.py` and -:file:`lib/bar/__init__.py`. (Keep in mind that although :option:`package_dir` -applies recursively, you must explicitly list all packages in -:option:`packages`: the Distutils will *not* recursively scan your source tree -looking for any directory with an :file:`__init__.py` file.) - - -.. _packaging-listing-modules: - -Listing individual modules -========================== - -For a small module distribution, you might prefer to list all modules rather -than listing packages---especially the case of a single module that goes in the -"root package" (i.e., no package at all). This simplest case was shown in -section :ref:`packaging-simple-example`; here is a slightly more involved -example:: - - py_modules = ['mod1', 'pkg.mod2'] - -This describes two modules, one of them in the "root" package, the other in the -:mod:`pkg` package. Again, the default package/directory layout implies that -these two modules can be found in :file:`mod1.py` and :file:`pkg/mod2.py`, and -that :file:`pkg/__init__.py` exists as well. And again, you can override the -package/directory correspondence using the :option:`package_dir` option. - - -.. _packaging-describing-extensions: - -Describing extension modules -============================ - -Just as writing Python extension modules is a bit more complicated than writing -pure Python modules, describing them to the Distutils is a bit more complicated. -Unlike pure modules, it's not enough just to list modules or packages and expect -the Distutils to go out and find the right files; you have to specify the -extension name, source file(s), and any compile/link requirements (include -directories, libraries to link with, etc.). - -.. XXX read over this section - -All of this is done through another keyword argument to :func:`setup`, the -:option:`ext_modules` option. :option:`ext_modules` is just a list of -:class:`Extension` instances, each of which describes a single extension module. -Suppose your distribution includes a single extension, called :mod:`foo` and -implemented by :file:`foo.c`. If no additional instructions to the -compiler/linker are needed, describing this extension is quite simple:: - - Extension('foo', ['foo.c']) - -The :class:`Extension` class can be imported from :mod:`packaging.core` along -with :func:`setup`. Thus, the setup script for a module distribution that -contains only this one extension and nothing else might be:: - - from packaging.core import setup, Extension - setup(name='foo', - version='1.0', - ext_modules=[Extension('foo', ['foo.c'])]) - -The :class:`Extension` class (actually, the underlying extension-building -machinery implemented by the :command:`build_ext` command) supports a great deal -of flexibility in describing Python extensions, which is explained in the -following sections. - - -Extension names and packages ----------------------------- - -The first argument to the :class:`Extension` constructor is always the name of -the extension, including any package names. For example, :: - - Extension('foo', ['src/foo1.c', 'src/foo2.c']) - -describes an extension that lives in the root package, while :: - - Extension('pkg.foo', ['src/foo1.c', 'src/foo2.c']) - -describes the same extension in the :mod:`pkg` package. The source files and -resulting object code are identical in both cases; the only difference is where -in the filesystem (and therefore where in Python's namespace hierarchy) the -resulting extension lives. - -If you have a number of extensions all in the same package (or all under the -same base package), use the :option:`ext_package` keyword argument to -:func:`setup`. For example, :: - - setup(..., - ext_package='pkg', - ext_modules=[Extension('foo', ['foo.c']), - Extension('subpkg.bar', ['bar.c'])]) - -will compile :file:`foo.c` to the extension :mod:`pkg.foo`, and :file:`bar.c` to -:mod:`pkg.subpkg.bar`. - - -Extension source files ----------------------- - -The second argument to the :class:`Extension` constructor is a list of source -files. Since the Distutils currently only support C, C++, and Objective-C -extensions, these are normally C/C++/Objective-C source files. (Be sure to use -appropriate extensions to distinguish C++\ source files: :file:`.cc` and -:file:`.cpp` seem to be recognized by both Unix and Windows compilers.) - -However, you can also include SWIG interface (:file:`.i`) files in the list; the -:command:`build_ext` command knows how to deal with SWIG extensions: it will run -SWIG on the interface file and compile the resulting C/C++ file into your -extension. - -.. XXX SWIG support is rough around the edges and largely untested! - -This warning notwithstanding, options to SWIG can be currently passed like -this:: - - setup(..., - ext_modules=[Extension('_foo', ['foo.i'], - swig_opts=['-modern', '-I../include'])], - py_modules=['foo']) - -Or on the command line like this:: - - > python setup.py build_ext --swig-opts="-modern -I../include" - -On some platforms, you can include non-source files that are processed by the -compiler and included in your extension. Currently, this just means Windows -message text (:file:`.mc`) files and resource definition (:file:`.rc`) files for -Visual C++. These will be compiled to binary resource (:file:`.res`) files and -linked into the executable. - - -Preprocessor options --------------------- - -Three optional arguments to :class:`Extension` will help if you need to specify -include directories to search or preprocessor macros to define/undefine: -``include_dirs``, ``define_macros``, and ``undef_macros``. - -For example, if your extension requires header files in the :file:`include` -directory under your distribution root, use the ``include_dirs`` option:: - - Extension('foo', ['foo.c'], include_dirs=['include']) - -You can specify absolute directories there; if you know that your extension will -only be built on Unix systems with X11R6 installed to :file:`/usr`, you can get -away with :: - - Extension('foo', ['foo.c'], include_dirs=['/usr/include/X11']) - -You should avoid this sort of non-portable usage if you plan to distribute your -code: it's probably better to write C code like :: - - #include - -If you need to include header files from some other Python extension, you can -take advantage of the fact that header files are installed in a consistent way -by the Distutils :command:`install_header` command. For example, the Numerical -Python header files are installed (on a standard Unix installation) to -:file:`/usr/local/include/python1.5/Numerical`. (The exact location will differ -according to your platform and Python installation.) Since the Python include -directory---\ :file:`/usr/local/include/python1.5` in this case---is always -included in the search path when building Python extensions, the best approach -is to write C code like :: - - #include - -.. TODO check if it's d2.sysconfig or the new sysconfig module now - -If you must put the :file:`Numerical` include directory right into your header -search path, though, you can find that directory using the Distutils -:mod:`packaging.sysconfig` module:: - - from packaging.sysconfig import get_python_inc - incdir = os.path.join(get_python_inc(plat_specific=1), 'Numerical') - setup(..., - Extension(..., include_dirs=[incdir])) - -Even though this is quite portable---it will work on any Python installation, -regardless of platform---it's probably easier to just write your C code in the -sensible way. - -You can define and undefine preprocessor macros with the ``define_macros`` and -``undef_macros`` options. ``define_macros`` takes a list of ``(name, value)`` -tuples, where ``name`` is the name of the macro to define (a string) and -``value`` is its value: either a string or ``None``. (Defining a macro ``FOO`` -to ``None`` is the equivalent of a bare ``#define FOO`` in your C source: with -most compilers, this sets ``FOO`` to the string ``1``.) ``undef_macros`` is -just a list of macros to undefine. - -For example:: - - Extension(..., - define_macros=[('NDEBUG', '1'), - ('HAVE_STRFTIME', None)], - undef_macros=['HAVE_FOO', 'HAVE_BAR']) - -is the equivalent of having this at the top of every C source file:: - - #define NDEBUG 1 - #define HAVE_STRFTIME - #undef HAVE_FOO - #undef HAVE_BAR - - -Library options ---------------- - -You can also specify the libraries to link against when building your extension, -and the directories to search for those libraries. The ``libraries`` option is -a list of libraries to link against, ``library_dirs`` is a list of directories -to search for libraries at link-time, and ``runtime_library_dirs`` is a list of -directories to search for shared (dynamically loaded) libraries at run-time. - -For example, if you need to link against libraries known to be in the standard -library search path on target systems :: - - Extension(..., - libraries=['gdbm', 'readline']) - -If you need to link with libraries in a non-standard location, you'll have to -include the location in ``library_dirs``:: - - Extension(..., - library_dirs=['/usr/X11R6/lib'], - libraries=['X11', 'Xt']) - -(Again, this sort of non-portable construct should be avoided if you intend to -distribute your code.) - -.. XXX Should mention clib libraries here or somewhere else! - - -Other options -------------- - -There are still some other options which can be used to handle special cases. - -The :option:`optional` option is a boolean; if it is true, -a build failure in the extension will not abort the build process, but -instead simply not install the failing extension. - -The :option:`extra_objects` option is a list of object files to be passed to the -linker. These files must not have extensions, as the default extension for the -compiler is used. - -:option:`extra_compile_args` and :option:`extra_link_args` can be used to -specify additional command-line options for the respective compiler and linker -command lines. - -:option:`export_symbols` is only useful on Windows. It can contain a list of -symbols (functions or variables) to be exported. This option is not needed when -building compiled extensions: Distutils will automatically add ``initmodule`` -to the list of exported symbols. - -The :option:`depends` option is a list of files that the extension depends on -(for example header files). The build command will call the compiler on the -sources to rebuild extension if any on this files has been modified since the -previous build. - -Relationships between Distributions and Packages -================================================ - -.. FIXME rewrite to update to PEP 345 (but without dist/release confusion) - -A distribution may relate to packages in three specific ways: - -#. It can require packages or modules. - -#. It can provide packages or modules. - -#. It can obsolete packages or modules. - -These relationships can be specified using keyword arguments to the -:func:`packaging.core.setup` function. - -Dependencies on other Python modules and packages can be specified by supplying -the *requires* keyword argument to :func:`setup`. The value must be a list of -strings. Each string specifies a package that is required, and optionally what -versions are sufficient. - -To specify that any version of a module or package is required, the string -should consist entirely of the module or package name. Examples include -``'mymodule'`` and ``'xml.parsers.expat'``. - -If specific versions are required, a sequence of qualifiers can be supplied in -parentheses. Each qualifier may consist of a comparison operator and a version -number. The accepted comparison operators are:: - - < > == - <= >= != - -These can be combined by using multiple qualifiers separated by commas (and -optional whitespace). In this case, all of the qualifiers must be matched; a -logical AND is used to combine the evaluations. - -Let's look at a bunch of examples: - -+-------------------------+----------------------------------------------+ -| Requires Expression | Explanation | -+=========================+==============================================+ -| ``==1.0`` | Only version ``1.0`` is compatible | -+-------------------------+----------------------------------------------+ -| ``>1.0, !=1.5.1, <2.0`` | Any version after ``1.0`` and before ``2.0`` | -| | is compatible, except ``1.5.1`` | -+-------------------------+----------------------------------------------+ - -Now that we can specify dependencies, we also need to be able to specify what we -provide that other distributions can require. This is done using the *provides* -keyword argument to :func:`setup`. The value for this keyword is a list of -strings, each of which names a Python module or package, and optionally -identifies the version. If the version is not specified, it is assumed to match -that of the distribution. - -Some examples: - -+---------------------+----------------------------------------------+ -| Provides Expression | Explanation | -+=====================+==============================================+ -| ``mypkg`` | Provide ``mypkg``, using the distribution | -| | version | -+---------------------+----------------------------------------------+ -| ``mypkg (1.1)`` | Provide ``mypkg`` version 1.1, regardless of | -| | the distribution version | -+---------------------+----------------------------------------------+ - -A package can declare that it obsoletes other packages using the *obsoletes* -keyword argument. The value for this is similar to that of the *requires* -keyword: a list of strings giving module or package specifiers. Each specifier -consists of a module or package name optionally followed by one or more version -qualifiers. Version qualifiers are given in parentheses after the module or -package name. - -The versions identified by the qualifiers are those that are obsoleted by the -distribution being described. If no qualifiers are given, all versions of the -named module or package are understood to be obsoleted. - -.. _packaging-installing-scripts: - -Installing Scripts -================== - -So far we have been dealing with pure and non-pure Python modules, which are -usually not run by themselves but imported by scripts. - -Scripts are files containing Python source code, intended to be started from the -command line. Scripts don't require Distutils to do anything very complicated. -The only clever feature is that if the first line of the script starts with -``#!`` and contains the word "python", the Distutils will adjust the first line -to refer to the current interpreter location. By default, it is replaced with -the current interpreter location. The :option:`--executable` (or :option:`-e`) -option will allow the interpreter path to be explicitly overridden. - -The :option:`scripts` option simply is a list of files to be handled in this -way. From the PyXML setup script:: - - setup(..., - scripts=['scripts/xmlproc_parse', 'scripts/xmlproc_val']) - -All the scripts will also be added to the ``MANIFEST`` file if no template is -provided. See :ref:`packaging-manifest`. - -.. _packaging-installing-package-data: - -Installing Package Data -======================= - -Often, additional files need to be installed into a package. These files are -often data that's closely related to the package's implementation, or text files -containing documentation that might be of interest to programmers using the -package. These files are called :dfn:`package data`. - -Package data can be added to packages using the ``package_data`` keyword -argument to the :func:`setup` function. The value must be a mapping from -package name to a list of relative path names that should be copied into the -package. The paths are interpreted as relative to the directory containing the -package (information from the ``package_dir`` mapping is used if appropriate); -that is, the files are expected to be part of the package in the source -directories. They may contain glob patterns as well. - -The path names may contain directory portions; any necessary directories will be -created in the installation. - -For example, if a package should contain a subdirectory with several data files, -the files can be arranged like this in the source tree:: - - setup.py - src/ - mypkg/ - __init__.py - module.py - data/ - tables.dat - spoons.dat - forks.dat - -The corresponding call to :func:`setup` might be:: - - setup(..., - packages=['mypkg'], - package_dir={'mypkg': 'src/mypkg'}, - package_data={'mypkg': ['data/*.dat']}) - - -All the files that match ``package_data`` will be added to the ``MANIFEST`` -file if no template is provided. See :ref:`packaging-manifest`. - - -.. _packaging-additional-files: - -Installing Additional Files -=========================== - -The :option:`data_files` option can be used to specify additional files needed -by the module distribution: configuration files, message catalogs, data files, -anything which doesn't fit in the previous categories. - -:option:`data_files` specifies a sequence of (*directory*, *files*) pairs in the -following way:: - - setup(..., - data_files=[('bitmaps', ['bm/b1.gif', 'bm/b2.gif']), - ('config', ['cfg/data.cfg']), - ('/etc/init.d', ['init-script'])]) - -Note that you can specify the directory names where the data files will be -installed, but you cannot rename the data files themselves. - -Each (*directory*, *files*) pair in the sequence specifies the installation -directory and the files to install there. If *directory* is a relative path, it -is interpreted relative to the installation prefix (Python's ``sys.prefix`` for -pure-Python packages, ``sys.exec_prefix`` for packages that contain extension -modules). Each file name in *files* is interpreted relative to the -:file:`setup.py` script at the top of the package source distribution. No -directory information from *files* is used to determine the final location of -the installed file; only the name of the file is used. - -You can specify the :option:`data_files` options as a simple sequence of files -without specifying a target directory, but this is not recommended, and the -:command:`install_dist` command will print a warning in this case. To install data -files directly in the target directory, an empty string should be given as the -directory. - -All the files that match ``data_files`` will be added to the ``MANIFEST`` file -if no template is provided. See :ref:`packaging-manifest`. - - - -.. _packaging-metadata: - -Metadata reference -================== - -The setup script may include additional metadata beyond the name and version. -This table describes required and additional information: - -.. TODO synchronize with setupcfg; link to it (but don't remove it, it's a - useful summary) - -+----------------------+---------------------------+-----------------+--------+ -| Meta-Data | Description | Value | Notes | -+======================+===========================+=================+========+ -| ``name`` | name of the project | short string | \(1) | -+----------------------+---------------------------+-----------------+--------+ -| ``version`` | version of this release | short string | (1)(2) | -+----------------------+---------------------------+-----------------+--------+ -| ``author`` | project author's name | short string | \(3) | -+----------------------+---------------------------+-----------------+--------+ -| ``author_email`` | email address of the | email address | \(3) | -| | project author | | | -+----------------------+---------------------------+-----------------+--------+ -| ``maintainer`` | project maintainer's name | short string | \(3) | -+----------------------+---------------------------+-----------------+--------+ -| ``maintainer_email`` | email address of the | email address | \(3) | -| | project maintainer | | | -+----------------------+---------------------------+-----------------+--------+ -| ``home_page`` | home page for the project | URL | \(1) | -+----------------------+---------------------------+-----------------+--------+ -| ``summary`` | short description of the | short string | | -| | project | | | -+----------------------+---------------------------+-----------------+--------+ -| ``description`` | longer description of the | long string | \(5) | -| | project | | | -+----------------------+---------------------------+-----------------+--------+ -| ``download_url`` | location where the | URL | | -| | project may be downloaded | | | -+----------------------+---------------------------+-----------------+--------+ -| ``classifiers`` | a list of classifiers | list of strings | \(4) | -+----------------------+---------------------------+-----------------+--------+ -| ``platforms`` | a list of platforms | list of strings | | -+----------------------+---------------------------+-----------------+--------+ -| ``license`` | license for the release | short string | \(6) | -+----------------------+---------------------------+-----------------+--------+ - -Notes: - -(1) - These fields are required. - -(2) - It is recommended that versions take the form *major.minor[.patch[.sub]]*. - -(3) - Either the author or the maintainer must be identified. - -(4) - The list of classifiers is available from the `PyPI website - `_. See also :mod:`packaging.create`. - -(5) - The ``description`` field is used by PyPI when you are registering a - release, to build its PyPI page. - -(6) - The ``license`` field is a text indicating the license covering the - distribution where the license is not a selection from the "License" Trove - classifiers. See the ``Classifier`` field. Notice that - there's a ``licence`` distribution option which is deprecated but still - acts as an alias for ``license``. - -'short string' - A single line of text, not more than 200 characters. - -'long string' - Multiple lines of plain text in reStructuredText format (see - http://docutils.sf.net/). - -'list of strings' - See below. - -In Python 2.x, "string value" means a unicode object. If a byte string (str or -bytes) is given, it has to be valid ASCII. - -.. TODO move this section to the version document, keep a summary, add a link - -Encoding the version information is an art in itself. Python projects generally -adhere to the version format *major.minor[.patch][sub]*. The major number is 0 -for initial, experimental releases of software. It is incremented for releases -that represent major milestones in a project. The minor number is incremented -when important new features are added to the project. The patch number -increments when bug-fix releases are made. Additional trailing version -information is sometimes used to indicate sub-releases. These are -"a1,a2,...,aN" (for alpha releases, where functionality and API may change), -"b1,b2,...,bN" (for beta releases, which only fix bugs) and "pr1,pr2,...,prN" -(for final pre-release release testing). Some examples: - -0.1.0 - the first, experimental release of a project - -1.0.1a2 - the second alpha release of the first patch version of 1.0 - -:option:`classifiers` are specified in a Python list:: - - setup(..., - classifiers=[ - 'Development Status :: 4 - Beta', - 'Environment :: Console', - 'Environment :: Web Environment', - 'Intended Audience :: End Users/Desktop', - 'Intended Audience :: Developers', - 'Intended Audience :: System Administrators', - 'License :: OSI Approved :: Python Software Foundation License', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows', - 'Operating System :: POSIX', - 'Programming Language :: Python', - 'Topic :: Communications :: Email', - 'Topic :: Office/Business', - 'Topic :: Software Development :: Bug Tracking', - ]) - - -Debugging the setup script -========================== - -Sometimes things go wrong, and the setup script doesn't do what the developer -wants. - -Distutils catches any exceptions when running the setup script, and print a -simple error message before the script is terminated. The motivation for this -behaviour is to not confuse administrators who don't know much about Python and -are trying to install a project. If they get a big long traceback from deep -inside the guts of Distutils, they may think the project or the Python -installation is broken because they don't read all the way down to the bottom -and see that it's a permission problem. - -.. FIXME DISTUTILS_DEBUG is dead, document logging/warnings here - -On the other hand, this doesn't help the developer to find the cause of the -failure. For this purpose, the DISTUTILS_DEBUG environment variable can be set -to anything except an empty string, and Packaging will now print detailed -information about what it is doing, and prints the full traceback in case an -exception occurs. diff -r 2e49722c7263 -r 6944bdf1289a Doc/packaging/sourcedist.rst --- a/Doc/packaging/sourcedist.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,273 +0,0 @@ -.. _packaging-source-dist: - -****************************** -Creating a Source Distribution -****************************** - -As shown in section :ref:`packaging-simple-example`, you use the :command:`sdist` command -to create a source distribution. In the simplest case, :: - - python setup.py sdist - -(assuming you haven't specified any :command:`sdist` options in the setup script -or config file), :command:`sdist` creates the archive of the default format for -the current platform. The default format is a gzip'ed tar file -(:file:`.tar.gz`) on Unix, and ZIP file on Windows. - -You can specify as many formats as you like using the :option:`--formats` -option, for example:: - - python setup.py sdist --formats=gztar,zip - -to create a gzipped tarball and a zip file. The available formats are: - -+-----------+-------------------------+---------+ -| Format | Description | Notes | -+===========+=========================+=========+ -| ``zip`` | zip file (:file:`.zip`) | (1),(3) | -+-----------+-------------------------+---------+ -| ``gztar`` | gzip'ed tar file | \(2) | -| | (:file:`.tar.gz`) | | -+-----------+-------------------------+---------+ -| ``bztar`` | bzip2'ed tar file | | -| | (:file:`.tar.bz2`) | | -+-----------+-------------------------+---------+ -| ``ztar`` | compressed tar file | \(4) | -| | (:file:`.tar.Z`) | | -+-----------+-------------------------+---------+ -| ``tar`` | tar file (:file:`.tar`) | | -+-----------+-------------------------+---------+ - -Notes: - -(1) - default on Windows - -(2) - default on Unix - -(3) - requires either external :program:`zip` utility or :mod:`zipfile` module (part - of the standard Python library since Python 1.6) - -(4) - requires the :program:`compress` program. Notice that this format is now - pending for deprecation and will be removed in the future versions of Python. - -When using any ``tar`` format (``gztar``, ``bztar``, ``ztar`` or -``tar``) under Unix, you can specify the ``owner`` and ``group`` names -that will be set for each member of the archive. - -For example, if you want all files of the archive to be owned by root:: - - python setup.py sdist --owner=root --group=root - - -.. _packaging-manifest: - -Specifying the files to distribute -================================== - -If you don't supply an explicit list of files (or instructions on how to -generate one), the :command:`sdist` command puts a minimal default set into the -source distribution: - -* all Python source files implied by the :option:`py_modules` and - :option:`packages` options - -* all C source files mentioned in the :option:`ext_modules` or - :option:`libraries` options - -* scripts identified by the :option:`scripts` option - See :ref:`packaging-installing-scripts`. - -* anything that looks like a test script: :file:`test/test\*.py` (currently, the - Packaging don't do anything with test scripts except include them in source - distributions, but in the future there will be a standard for testing Python - module distributions) - -* the configuration file :file:`setup.cfg` - -* all files that matches the ``package_data`` metadata. - See :ref:`packaging-installing-package-data`. - -* all files that matches the ``data_files`` metadata. - See :ref:`packaging-additional-files`. - -Contrary to Distutils, :file:`README` (or :file:`README.txt`) and -:file:`setup.py` are not included by default. - -Sometimes this is enough, but usually you will want to specify additional files -to distribute. The typical way to do this is to write a *manifest template*, -called :file:`MANIFEST.in` by default. The manifest template is just a list of -instructions for how to generate your manifest file, :file:`MANIFEST`, which is -the exact list of files to include in your source distribution. The -:command:`sdist` command processes this template and generates a manifest based -on its instructions and what it finds in the filesystem. - -If you prefer to roll your own manifest file, the format is simple: one filename -per line, regular files (or symlinks to them) only. If you do supply your own -:file:`MANIFEST`, you must specify everything: the default set of files -described above does not apply in this case. - -:file:`MANIFEST` files start with a comment indicating they are generated. -Files without this comment are not overwritten or removed. - -See :ref:`packaging-manifest-template` section for a syntax reference. - - -.. _packaging-manifest-options: - -Manifest-related options -======================== - -The normal course of operations for the :command:`sdist` command is as follows: - -* if the manifest file, :file:`MANIFEST` doesn't exist, read :file:`MANIFEST.in` - and create the manifest - -* if neither :file:`MANIFEST` nor :file:`MANIFEST.in` exist, create a manifest - with just the default file set - -* if either :file:`MANIFEST.in` or the setup script (:file:`setup.py`) are more - recent than :file:`MANIFEST`, recreate :file:`MANIFEST` by reading - :file:`MANIFEST.in` - -* use the list of files now in :file:`MANIFEST` (either just generated or read - in) to create the source distribution archive(s) - -There are a couple of options that modify this behaviour. First, use the -:option:`--no-defaults` and :option:`--no-prune` to disable the standard -"include" and "exclude" sets. - -Second, you might just want to (re)generate the manifest, but not create a -source distribution:: - - python setup.py sdist --manifest-only - -:option:`-o` is a shortcut for :option:`--manifest-only`. - - -.. _packaging-manifest-template: - -The MANIFEST.in template -======================== - -A :file:`MANIFEST.in` file can be added in a project to define the list of -files to include in the distribution built by the :command:`sdist` command. - -When :command:`sdist` is run, it will look for the :file:`MANIFEST.in` file -and interpret it to generate the :file:`MANIFEST` file that contains the -list of files that will be included in the package. - -This mechanism can be used when the default list of files is not enough. -(See :ref:`packaging-manifest`). - -Principle ---------- - -The manifest template has one command per line, where each command specifies a -set of files to include or exclude from the source distribution. For an -example, let's look at the Packaging' own manifest template:: - - include *.txt - recursive-include examples *.txt *.py - prune examples/sample?/build - -The meanings should be fairly clear: include all files in the distribution root -matching :file:`\*.txt`, all files anywhere under the :file:`examples` directory -matching :file:`\*.txt` or :file:`\*.py`, and exclude all directories matching -:file:`examples/sample?/build`. All of this is done *after* the standard -include set, so you can exclude files from the standard set with explicit -instructions in the manifest template. (Or, you can use the -:option:`--no-defaults` option to disable the standard set entirely.) - -The order of commands in the manifest template matters: initially, we have the -list of default files as described above, and each command in the template adds -to or removes from that list of files. Once we have fully processed the -manifest template, we remove files that should not be included in the source -distribution: - -* all files in the Packaging "build" tree (default :file:`build/`) - -* all files in directories named :file:`RCS`, :file:`CVS`, :file:`.svn`, - :file:`.hg`, :file:`.git`, :file:`.bzr` or :file:`_darcs` - -Now we have our complete list of files, which is written to the manifest for -future reference, and then used to build the source distribution archive(s). - -You can disable the default set of included files with the -:option:`--no-defaults` option, and you can disable the standard exclude set -with :option:`--no-prune`. - -Following the Packaging' own manifest template, let's trace how the -:command:`sdist` command builds the list of files to include in the Packaging -source distribution: - -#. include all Python source files in the :file:`packaging` and - :file:`packaging/command` subdirectories (because packages corresponding to - those two directories were mentioned in the :option:`packages` option in the - setup script---see section :ref:`packaging-setup-script`) - -#. include :file:`README.txt`, :file:`setup.py`, and :file:`setup.cfg` (standard - files) - -#. include :file:`test/test\*.py` (standard files) - -#. include :file:`\*.txt` in the distribution root (this will find - :file:`README.txt` a second time, but such redundancies are weeded out later) - -#. include anything matching :file:`\*.txt` or :file:`\*.py` in the sub-tree - under :file:`examples`, - -#. exclude all files in the sub-trees starting at directories matching - :file:`examples/sample?/build`\ ---this may exclude files included by the - previous two steps, so it's important that the ``prune`` command in the manifest - template comes after the ``recursive-include`` command - -#. exclude the entire :file:`build` tree, and any :file:`RCS`, :file:`CVS`, - :file:`.svn`, :file:`.hg`, :file:`.git`, :file:`.bzr` and :file:`_darcs` - directories - -Just like in the setup script, file and directory names in the manifest template -should always be slash-separated; the Packaging will take care of converting -them to the standard representation on your platform. That way, the manifest -template is portable across operating systems. - -Commands --------- - -The manifest template commands are: - -+-------------------------------------------+-----------------------------------------------+ -| Command | Description | -+===========================================+===============================================+ -| :command:`include pat1 pat2 ...` | include all files matching any of the listed | -| | patterns | -+-------------------------------------------+-----------------------------------------------+ -| :command:`exclude pat1 pat2 ...` | exclude all files matching any of the listed | -| | patterns | -+-------------------------------------------+-----------------------------------------------+ -| :command:`recursive-include dir pat1 pat2 | include all files under *dir* matching any of | -| ...` | the listed patterns | -+-------------------------------------------+-----------------------------------------------+ -| :command:`recursive-exclude dir pat1 pat2 | exclude all files under *dir* matching any of | -| ...` | the listed patterns | -+-------------------------------------------+-----------------------------------------------+ -| :command:`global-include pat1 pat2 ...` | include all files anywhere in the source tree | -| | matching --- & any of the listed patterns | -+-------------------------------------------+-----------------------------------------------+ -| :command:`global-exclude pat1 pat2 ...` | exclude all files anywhere in the source tree | -| | matching --- & any of the listed patterns | -+-------------------------------------------+-----------------------------------------------+ -| :command:`prune dir` | exclude all files under *dir* | -+-------------------------------------------+-----------------------------------------------+ -| :command:`graft dir` | include all files under *dir* | -+-------------------------------------------+-----------------------------------------------+ - -The patterns here are Unix-style "glob" patterns: ``*`` matches any sequence of -regular filename characters, ``?`` matches any single regular filename -character, and ``[range]`` matches any of the characters in *range* (e.g., -``a-z``, ``a-zA-Z``, ``a-f0-9_.``). The definition of "regular filename -character" is platform-specific: on Unix it is anything except slash; on Windows -anything except backslash or colon. diff -r 2e49722c7263 -r 6944bdf1289a Doc/packaging/tutorial.rst --- a/Doc/packaging/tutorial.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,112 +0,0 @@ -================== -Packaging tutorial -================== - -Welcome to the Packaging tutorial! We will learn how to use Packaging -to package your project. - -.. TODO merge with introduction.rst - - -Getting started ---------------- - -Packaging works with the *setup.cfg* file. It contains all the metadata for -your project, as defined in PEP 345, but also declare what your project -contains. - -Let's say you have a project called *CLVault* containing one package called -*clvault*, and a few scripts inside. You can use the *pysetup* script to create -a *setup.cfg* file for the project. The script will ask you a few questions:: - - $ mkdir CLVault - $ cd CLVault - $ pysetup create - Project name [CLVault]: - Current version number: 0.1 - Package description: - >Command-line utility to store and retrieve passwords - Author name: Tarek Ziade - Author e-mail address: tarek@ziade.org - Project Home Page: http://bitbucket.org/tarek/clvault - Do you want to add a package ? (y/n): y - Package name: clvault - Do you want to add a package ? (y/n): n - Do you want to set Trove classifiers? (y/n): y - Please select the project status: - - 1 - Planning - 2 - Pre-Alpha - 3 - Alpha - 4 - Beta - 5 - Production/Stable - 6 - Mature - 7 - Inactive - - Status: 3 - What license do you use: GPL - Matching licenses: - - 1) License :: OSI Approved :: GNU General Public License (GPL) - 2) License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL) - - Type the number of the license you wish to use or ? to try again:: 1 - Do you want to set other trove identifiers (y/n) [n]: n - Wrote "setup.cfg". - - -A setup.cfg file is created, containing the metadata of your project and the -list of the packages it contains:: - - $ cat setup.cfg - [metadata] - name = CLVault - version = 0.1 - author = Tarek Ziade - author_email = tarek@ziade.org - description = Command-line utility to store and retrieve passwords - home_page = http://bitbucket.org/tarek/clvault - - classifier = Development Status :: 3 - Alpha - License :: OSI Approved :: GNU General Public License (GPL) - - [files] - packages = clvault - - -Our project will depend on the *keyring* project. Let's add it in the -[metadata] section:: - - [metadata] - ... - requires_dist = - keyring - - -Running commands ----------------- - -You can run useful commands on your project once the setup.cfg file is ready: - -- sdist: creates a source distribution -- register: register your project to PyPI -- upload: upload the distribution to PyPI -- install_dist: install it - -All commands are run using the run script:: - - $ pysetup run install_dist - $ pysetup run sdist - $ pysetup run upload - -If you want to push a source distribution of your project to PyPI, do:: - - $ pysetup run sdist register upload - - -Installing the project ----------------------- - -The project can be installed by manually running the packaging install command:: - - $ pysetup run install_dist diff -r 2e49722c7263 -r 6944bdf1289a Doc/packaging/uploading.rst --- a/Doc/packaging/uploading.rst Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -.. _packaging-package-upload: - -*************************************** -Uploading Packages to the Package Index -*************************************** - -The Python Package Index (PyPI) not only stores the package info, but also the -package data if the author of the package wishes to. The packaging command -:command:`upload` pushes the distribution files to PyPI. - -The command is invoked immediately after building one or more distribution -files. For example, the command :: - - python setup.py sdist bdist_wininst upload - -will cause the source distribution and the Windows installer to be uploaded to -PyPI. Note that these will be uploaded even if they are built using an earlier -invocation of :file:`setup.py`, but that only distributions named on the command -line for the invocation including the :command:`upload` command are uploaded. - -The :command:`upload` command uses the username, password, and repository URL -from the :file:`$HOME/.pypirc` file (see section :ref:`packaging-pypirc` for more on this -file). If a :command:`register` command was previously called in the same -command, and if the password was entered in the prompt, :command:`upload` will -reuse the entered password. This is useful if you do not want to store a clear -text password in the :file:`$HOME/.pypirc` file. - -You can specify another PyPI server with the :option:`--repository=*url*` -option:: - - python setup.py sdist bdist_wininst upload -r http://example.com/pypi - -See section :ref:`packaging-pypirc` for more on defining several servers. - -You can use the :option:`--sign` option to tell :command:`upload` to sign each -uploaded file using GPG (GNU Privacy Guard). The :program:`gpg` program must -be available for execution on the system :envvar:`PATH`. You can also specify -which key to use for signing using the :option:`--identity=*name*` option. - -Other :command:`upload` options include :option:`--repository=` or -:option:`--repository=
` where *url* is the url of the server and -*section* the name of the section in :file:`$HOME/.pypirc`, and -:option:`--show-response` (which displays the full response text from the PyPI -server for help in debugging upload problems). - -PyPI package display -==================== - -The ``description`` field plays a special role at PyPI. It is used by -the server to display a home page for the registered package. - -If you use the `reStructuredText `_ -syntax for this field, PyPI will parse it and display an HTML output for -the package home page. - -The ``description`` field can be filled from a text file located in the -project:: - - from packaging.core import setup - - fp = open('README.txt') - try: - description = fp.read() - finally: - fp.close() - - setup(name='Packaging', - description=description) - -In that case, :file:`README.txt` is a regular reStructuredText text file located -in the root of the package besides :file:`setup.py`. - -To prevent registering broken reStructuredText content, you can use the -:program:`rst2html` program that is provided by the :mod:`docutils` package -and check the ``description`` from the command line:: - - $ python setup.py --description | rst2html.py > output.html - -:mod:`docutils` will display a warning if there's something wrong with your -syntax. diff -r 2e49722c7263 -r 6944bdf1289a Doc/tools/sphinxext/indexcontent.html --- a/Doc/tools/sphinxext/indexcontent.html Thu Jun 09 15:52:31 2011 -0400 +++ b/Doc/tools/sphinxext/indexcontent.html Sat May 14 18:40:38 2011 +0200 @@ -20,10 +20,10 @@ tutorial for C/C++ programmers

- - + + ..." % action) - - dir = convert_path(words[1]) - patterns = [convert_path(word) for word in words[2:]] - - elif action in ('graft', 'prune'): - if len(words) != 2: - raise PackagingTemplateError( - "%r expects a single " % action) - - dir_pattern = convert_path(words[1]) - - else: - raise PackagingTemplateError("unknown action %r" % action) - - return action, patterns, dir, dir_pattern - - def _process_template_line(self, line): - # Parse the line: split it up, make sure the right number of words - # is there, and return the relevant words. 'action' is always - # defined: it's the first word of the line. Which of the other - # three are defined depends on the action; it'll be either - # patterns, (dir and patterns), or (dir_pattern). - action, patterns, dir, dir_pattern = self._parse_template_line(line) - - # OK, now we know that the action is valid and we have the - # right number of words on the line for that action -- so we - # can proceed with minimal error-checking. - if action == 'include': - for pattern in patterns: - if not self._include_pattern(pattern, anchor=True): - logger.warning("no files found matching %r", pattern) - - elif action == 'exclude': - for pattern in patterns: - if not self.exclude_pattern(pattern, anchor=True): - logger.warning("no previously-included files " - "found matching %r", pattern) - - elif action == 'global-include': - for pattern in patterns: - if not self._include_pattern(pattern, anchor=False): - logger.warning("no files found matching %r " - "anywhere in distribution", pattern) - - elif action == 'global-exclude': - for pattern in patterns: - if not self.exclude_pattern(pattern, anchor=False): - logger.warning("no previously-included files " - "matching %r found anywhere in " - "distribution", pattern) - - elif action == 'recursive-include': - for pattern in patterns: - if not self._include_pattern(pattern, prefix=dir): - logger.warning("no files found matching %r " - "under directory %r", pattern, dir) - - elif action == 'recursive-exclude': - for pattern in patterns: - if not self.exclude_pattern(pattern, prefix=dir): - logger.warning("no previously-included files " - "matching %r found under directory %r", - pattern, dir) - - elif action == 'graft': - if not self._include_pattern(None, prefix=dir_pattern): - logger.warning("no directories found matching %r", - dir_pattern) - - elif action == 'prune': - if not self.exclude_pattern(None, prefix=dir_pattern): - logger.warning("no previously-included directories found " - "matching %r", dir_pattern) - else: - raise PackagingInternalError( - "this cannot happen: invalid action %r" % action) - - def _include_pattern(self, pattern, anchor=True, prefix=None, - is_regex=False): - """Select strings (presumably filenames) from 'self.files' that - match 'pattern', a Unix-style wildcard (glob) pattern. - - Patterns are not quite the same as implemented by the 'fnmatch' - module: '*' and '?' match non-special characters, where "special" - is platform-dependent: slash on Unix; colon, slash, and backslash on - DOS/Windows; and colon on Mac OS. - - If 'anchor' is true (the default), then the pattern match is more - stringent: "*.py" will match "foo.py" but not "foo/bar.py". If - 'anchor' is false, both of these will match. - - If 'prefix' is supplied, then only filenames starting with 'prefix' - (itself a pattern) and ending with 'pattern', with anything in between - them, will match. 'anchor' is ignored in this case. - - If 'is_regex' is true, 'anchor' and 'prefix' are ignored, and - 'pattern' is assumed to be either a string containing a regex or a - regex object -- no translation is done, the regex is just compiled - and used as-is. - - Selected strings will be added to self.files. - - Return True if files are found. - """ - files_found = False - pattern_re = _translate_pattern(pattern, anchor, prefix, is_regex) - - # delayed loading of allfiles list - if self.allfiles is None: - self.findall() - - for name in self.allfiles: - if pattern_re.search(name): - self.files.append(name) - files_found = True - - return files_found - - -# -# Utility functions -# -def _findall(dir=os.curdir): - """Find all files under 'dir' and return the list of full filenames - (relative to 'dir'). - """ - from stat import S_ISREG, S_ISDIR, S_ISLNK - - list = [] - stack = [dir] - pop = stack.pop - push = stack.append - - while stack: - dir = pop() - names = os.listdir(dir) - - for name in names: - if dir != os.curdir: # avoid the dreaded "./" syndrome - fullname = os.path.join(dir, name) - else: - fullname = name - - # Avoid excess stat calls -- just one will do, thank you! - stat = os.stat(fullname) - mode = stat.st_mode - if S_ISREG(mode): - list.append(fullname) - elif S_ISDIR(mode) and not S_ISLNK(mode): - push(fullname) - - return list - - -def _glob_to_re(pattern): - """Translate a shell-like glob pattern to a regular expression. - - Return a string containing the regex. Differs from - 'fnmatch.translate()' in that '*' does not match "special characters" - (which are platform-specific). - """ - pattern_re = fnmatch.translate(pattern) - - # '?' and '*' in the glob pattern become '.' and '.*' in the RE, which - # IMHO is wrong -- '?' and '*' aren't supposed to match slash in Unix, - # and by extension they shouldn't match such "special characters" under - # any OS. So change all non-escaped dots in the RE to match any - # character except the special characters. - # XXX currently the "special characters" are just slash -- i.e. this is - # Unix-only. - pattern_re = re.sub(r'((?': lambda x, y: x > y, - '>=': lambda x, y: x >= y, - '<': lambda x, y: x < y, - '<=': lambda x, y: x <= y, - 'in': lambda x, y: x in y, - 'not in': lambda x, y: x not in y} - - -def _operate(operation, x, y): - return _OPERATORS[operation](x, y) - - -# restricted set of variables -_VARS = {'sys.platform': sys.platform, - 'python_version': sys.version[:3], - 'python_full_version': sys.version.split(' ', 1)[0], - 'os.name': os.name, - 'platform.version': platform.version(), - 'platform.machine': platform.machine(), - 'platform.python_implementation': platform.python_implementation()} - - -class _Operation: - - def __init__(self, execution_context=None): - self.left = None - self.op = None - self.right = None - if execution_context is None: - execution_context = {} - self.execution_context = execution_context - - def _get_var(self, name): - if name in self.execution_context: - return self.execution_context[name] - return _VARS[name] - - def __repr__(self): - return '%s %s %s' % (self.left, self.op, self.right) - - def _is_string(self, value): - if value is None or len(value) < 2: - return False - for delimiter in '"\'': - if value[0] == value[-1] == delimiter: - return True - return False - - def _is_name(self, value): - return value in _VARS - - def _convert(self, value): - if value in _VARS: - return self._get_var(value) - return value.strip('"\'') - - def _check_name(self, value): - if value not in _VARS: - raise NameError(value) - - def _nonsense_op(self): - msg = 'This operation is not supported : "%s"' % self - raise SyntaxError(msg) - - def __call__(self): - # make sure we do something useful - if self._is_string(self.left): - if self._is_string(self.right): - self._nonsense_op() - self._check_name(self.right) - else: - if not self._is_string(self.right): - self._nonsense_op() - self._check_name(self.left) - - if self.op not in _OPERATORS: - raise TypeError('Operator not supported "%s"' % self.op) - - left = self._convert(self.left) - right = self._convert(self.right) - return _operate(self.op, left, right) - - -class _OR: - def __init__(self, left, right=None): - self.left = left - self.right = right - - def filled(self): - return self.right is not None - - def __repr__(self): - return 'OR(%r, %r)' % (self.left, self.right) - - def __call__(self): - return self.left() or self.right() - - -class _AND: - def __init__(self, left, right=None): - self.left = left - self.right = right - - def filled(self): - return self.right is not None - - def __repr__(self): - return 'AND(%r, %r)' % (self.left, self.right) - - def __call__(self): - return self.left() and self.right() - - -def interpret(marker, execution_context=None): - """Interpret a marker and return a result depending on environment.""" - marker = marker.strip().encode() - ops = [] - op_starting = True - for token in tokenize(BytesIO(marker).readline): - # Unpack token - toktype, tokval, rowcol, line, logical_line = token - if toktype not in (NAME, OP, STRING, ENDMARKER, ENCODING): - raise SyntaxError('Type not supported "%s"' % tokval) - - if op_starting: - op = _Operation(execution_context) - if len(ops) > 0: - last = ops[-1] - if isinstance(last, (_OR, _AND)) and not last.filled(): - last.right = op - else: - ops.append(op) - else: - ops.append(op) - op_starting = False - else: - op = ops[-1] - - if (toktype == ENDMARKER or - (toktype == NAME and tokval in ('and', 'or'))): - if toktype == NAME and tokval == 'and': - ops.append(_AND(ops.pop())) - elif toktype == NAME and tokval == 'or': - ops.append(_OR(ops.pop())) - op_starting = True - continue - - if isinstance(op, (_OR, _AND)) and op.right is not None: - op = op.right - - if ((toktype in (NAME, STRING) and tokval not in ('in', 'not')) - or (toktype == OP and tokval == '.')): - if op.op is None: - if op.left is None: - op.left = tokval - else: - op.left += tokval - else: - if op.right is None: - op.right = tokval - else: - op.right += tokval - elif toktype == OP or tokval in ('in', 'not'): - if tokval == 'in' and op.op == 'not': - op.op = 'not in' - else: - op.op = tokval - - for op in ops: - if not op(): - return False - return True diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/metadata.py --- a/Lib/packaging/metadata.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,554 +0,0 @@ -"""Implementation of the Metadata for Python packages PEPs. - -Supports all metadata formats (1.0, 1.1, 1.2). -""" - -import re -import logging - -from io import StringIO -from email import message_from_file -from packaging import logger -from packaging.markers import interpret -from packaging.version import (is_valid_predicate, is_valid_version, - is_valid_versions) -from packaging.errors import (MetadataMissingError, - MetadataConflictError, - MetadataUnrecognizedVersionError) - -try: - # docutils is installed - from docutils.utils import Reporter - from docutils.parsers.rst import Parser - from docutils import frontend - from docutils import nodes - - class SilentReporter(Reporter): - - def __init__(self, source, report_level, halt_level, stream=None, - debug=0, encoding='ascii', error_handler='replace'): - self.messages = [] - Reporter.__init__(self, source, report_level, halt_level, stream, - debug, encoding, error_handler) - - def system_message(self, level, message, *children, **kwargs): - self.messages.append((level, message, children, kwargs)) - - _HAS_DOCUTILS = True -except ImportError: - # docutils is not installed - _HAS_DOCUTILS = False - -# public API of this module -__all__ = ['Metadata', 'PKG_INFO_ENCODING', 'PKG_INFO_PREFERRED_VERSION'] - -# Encoding used for the PKG-INFO files -PKG_INFO_ENCODING = 'utf-8' - -# preferred version. Hopefully will be changed -# to 1.2 once PEP 345 is supported everywhere -PKG_INFO_PREFERRED_VERSION = '1.0' - -_LINE_PREFIX = re.compile('\n \|') -_241_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', - 'Summary', 'Description', - 'Keywords', 'Home-page', 'Author', 'Author-email', - 'License') - -_314_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', - 'Supported-Platform', 'Summary', 'Description', - 'Keywords', 'Home-page', 'Author', 'Author-email', - 'License', 'Classifier', 'Download-URL', 'Obsoletes', - 'Provides', 'Requires') - -_314_MARKERS = ('Obsoletes', 'Provides', 'Requires') - -_345_FIELDS = ('Metadata-Version', 'Name', 'Version', 'Platform', - 'Supported-Platform', 'Summary', 'Description', - 'Keywords', 'Home-page', 'Author', 'Author-email', - 'Maintainer', 'Maintainer-email', 'License', - 'Classifier', 'Download-URL', 'Obsoletes-Dist', - 'Project-URL', 'Provides-Dist', 'Requires-Dist', - 'Requires-Python', 'Requires-External') - -_345_MARKERS = ('Provides-Dist', 'Requires-Dist', 'Requires-Python', - 'Obsoletes-Dist', 'Requires-External', 'Maintainer', - 'Maintainer-email', 'Project-URL') - -_ALL_FIELDS = set() -_ALL_FIELDS.update(_241_FIELDS) -_ALL_FIELDS.update(_314_FIELDS) -_ALL_FIELDS.update(_345_FIELDS) - - -def _version2fieldlist(version): - if version == '1.0': - return _241_FIELDS - elif version == '1.1': - return _314_FIELDS - elif version == '1.2': - return _345_FIELDS - raise MetadataUnrecognizedVersionError(version) - - -def _best_version(fields): - """Detect the best version depending on the fields used.""" - def _has_marker(keys, markers): - for marker in markers: - if marker in keys: - return True - return False - - keys = list(fields) - possible_versions = ['1.0', '1.1', '1.2'] - - # first let's try to see if a field is not part of one of the version - for key in keys: - if key not in _241_FIELDS and '1.0' in possible_versions: - possible_versions.remove('1.0') - if key not in _314_FIELDS and '1.1' in possible_versions: - possible_versions.remove('1.1') - if key not in _345_FIELDS and '1.2' in possible_versions: - possible_versions.remove('1.2') - - # possible_version contains qualified versions - if len(possible_versions) == 1: - return possible_versions[0] # found ! - elif len(possible_versions) == 0: - raise MetadataConflictError('Unknown metadata set') - - # let's see if one unique marker is found - is_1_1 = '1.1' in possible_versions and _has_marker(keys, _314_MARKERS) - is_1_2 = '1.2' in possible_versions and _has_marker(keys, _345_MARKERS) - if is_1_1 and is_1_2: - raise MetadataConflictError('You used incompatible 1.1 and 1.2 fields') - - # we have the choice, either 1.0, or 1.2 - # - 1.0 has a broken Summary field but works with all tools - # - 1.1 is to avoid - # - 1.2 fixes Summary but is not widespread yet - if not is_1_1 and not is_1_2: - # we couldn't find any specific marker - if PKG_INFO_PREFERRED_VERSION in possible_versions: - return PKG_INFO_PREFERRED_VERSION - if is_1_1: - return '1.1' - - # default marker when 1.0 is disqualified - return '1.2' - - -_ATTR2FIELD = { - 'metadata_version': 'Metadata-Version', - 'name': 'Name', - 'version': 'Version', - 'platform': 'Platform', - 'supported_platform': 'Supported-Platform', - 'summary': 'Summary', - 'description': 'Description', - 'keywords': 'Keywords', - 'home_page': 'Home-page', - 'author': 'Author', - 'author_email': 'Author-email', - 'maintainer': 'Maintainer', - 'maintainer_email': 'Maintainer-email', - 'license': 'License', - 'classifier': 'Classifier', - 'download_url': 'Download-URL', - 'obsoletes_dist': 'Obsoletes-Dist', - 'provides_dist': 'Provides-Dist', - 'requires_dist': 'Requires-Dist', - 'requires_python': 'Requires-Python', - 'requires_external': 'Requires-External', - 'requires': 'Requires', - 'provides': 'Provides', - 'obsoletes': 'Obsoletes', - 'project_url': 'Project-URL', -} - -_PREDICATE_FIELDS = ('Requires-Dist', 'Obsoletes-Dist', 'Provides-Dist') -_VERSIONS_FIELDS = ('Requires-Python',) -_VERSION_FIELDS = ('Version',) -_LISTFIELDS = ('Platform', 'Classifier', 'Obsoletes', - 'Requires', 'Provides', 'Obsoletes-Dist', - 'Provides-Dist', 'Requires-Dist', 'Requires-External', - 'Project-URL', 'Supported-Platform') -_LISTTUPLEFIELDS = ('Project-URL',) - -_ELEMENTSFIELD = ('Keywords',) - -_UNICODEFIELDS = ('Author', 'Maintainer', 'Summary', 'Description') - -_MISSING = object() - - -class NoDefault: - """Marker object used for clean representation""" - def __repr__(self): - return '' - -_MISSING = NoDefault() - - -class Metadata: - """The metadata of a release. - - Supports versions 1.0, 1.1 and 1.2 (auto-detected). You can - instantiate the class with one of these arguments (or none): - - *path*, the path to a METADATA file - - *fileobj* give a file-like object with METADATA as content - - *mapping* is a dict-like object - """ - # TODO document that execution_context and platform_dependent are used - # to filter on query, not when setting a key - # also document the mapping API and UNKNOWN default key - - def __init__(self, path=None, platform_dependent=False, - execution_context=None, fileobj=None, mapping=None): - self._fields = {} - self.requires_files = [] - self.docutils_support = _HAS_DOCUTILS - self.platform_dependent = platform_dependent - self.execution_context = execution_context - if [path, fileobj, mapping].count(None) < 2: - raise TypeError('path, fileobj and mapping are exclusive') - if path is not None: - self.read(path) - elif fileobj is not None: - self.read_file(fileobj) - elif mapping is not None: - self.update(mapping) - - def _set_best_version(self): - self._fields['Metadata-Version'] = _best_version(self._fields) - - def _write_field(self, file, name, value): - file.write('%s: %s\n' % (name, value)) - - def __getitem__(self, name): - return self.get(name) - - def __setitem__(self, name, value): - return self.set(name, value) - - def __delitem__(self, name): - field_name = self._convert_name(name) - try: - del self._fields[field_name] - except KeyError: - raise KeyError(name) - self._set_best_version() - - def __contains__(self, name): - return (name in self._fields or - self._convert_name(name) in self._fields) - - def _convert_name(self, name): - if name in _ALL_FIELDS: - return name - name = name.replace('-', '_').lower() - return _ATTR2FIELD.get(name, name) - - def _default_value(self, name): - if name in _LISTFIELDS or name in _ELEMENTSFIELD: - return [] - return 'UNKNOWN' - - def _check_rst_data(self, data): - """Return warnings when the provided data has syntax errors.""" - source_path = StringIO() - parser = Parser() - settings = frontend.OptionParser().get_default_values() - settings.tab_width = 4 - settings.pep_references = None - settings.rfc_references = None - reporter = SilentReporter(source_path, - settings.report_level, - settings.halt_level, - stream=settings.warning_stream, - debug=settings.debug, - encoding=settings.error_encoding, - error_handler=settings.error_encoding_error_handler) - - document = nodes.document(settings, reporter, source=source_path) - document.note_source(source_path, -1) - try: - parser.parse(data, document) - except AttributeError: - reporter.messages.append((-1, 'Could not finish the parsing.', - '', {})) - - return reporter.messages - - def _platform(self, value): - if not self.platform_dependent or ';' not in value: - return True, value - value, marker = value.split(';') - return interpret(marker, self.execution_context), value - - def _remove_line_prefix(self, value): - return _LINE_PREFIX.sub('\n', value) - - # - # Public API - # - def get_fullname(self): - """Return the distribution name with version""" - return '%s-%s' % (self['Name'], self['Version']) - - def is_metadata_field(self, name): - """return True if name is a valid metadata key""" - name = self._convert_name(name) - return name in _ALL_FIELDS - - def is_multi_field(self, name): - name = self._convert_name(name) - return name in _LISTFIELDS - - def read(self, filepath): - """Read the metadata values from a file path.""" - with open(filepath, 'r', encoding='utf-8') as fp: - self.read_file(fp) - - def read_file(self, fileob): - """Read the metadata values from a file object.""" - msg = message_from_file(fileob) - self._fields['Metadata-Version'] = msg['metadata-version'] - - for field in _version2fieldlist(self['Metadata-Version']): - if field in _LISTFIELDS: - # we can have multiple lines - values = msg.get_all(field) - if field in _LISTTUPLEFIELDS and values is not None: - values = [tuple(value.split(',')) for value in values] - self.set(field, values) - else: - # single line - value = msg[field] - if value is not None and value != 'UNKNOWN': - self.set(field, value) - - def write(self, filepath): - """Write the metadata fields to filepath.""" - with open(filepath, 'w', encoding='utf-8') as fp: - self.write_file(fp) - - def write_file(self, fileobject): - """Write the PKG-INFO format data to a file object.""" - self._set_best_version() - for field in _version2fieldlist(self['Metadata-Version']): - values = self.get(field) - if field in _ELEMENTSFIELD: - self._write_field(fileobject, field, ','.join(values)) - continue - if field not in _LISTFIELDS: - if field == 'Description': - values = values.replace('\n', '\n |') - values = [values] - - if field in _LISTTUPLEFIELDS: - values = [','.join(value) for value in values] - - for value in values: - self._write_field(fileobject, field, value) - - def update(self, other=None, **kwargs): - """Set metadata values from the given iterable `other` and kwargs. - - Behavior is like `dict.update`: If `other` has a ``keys`` method, - they are looped over and ``self[key]`` is assigned ``other[key]``. - Else, ``other`` is an iterable of ``(key, value)`` iterables. - - Keys that don't match a metadata field or that have an empty value are - dropped. - """ - def _set(key, value): - if key in _ATTR2FIELD and value: - self.set(self._convert_name(key), value) - - if other is None: - pass - elif hasattr(other, 'keys'): - for k in other.keys(): - _set(k, other[k]) - else: - for k, v in other: - _set(k, v) - - if kwargs: - self.update(kwargs) - - def set(self, name, value): - """Control then set a metadata field.""" - name = self._convert_name(name) - - if ((name in _ELEMENTSFIELD or name == 'Platform') and - not isinstance(value, (list, tuple))): - if isinstance(value, str): - value = [v.strip() for v in value.split(',')] - else: - value = [] - elif (name in _LISTFIELDS and - not isinstance(value, (list, tuple))): - if isinstance(value, str): - value = [value] - else: - value = [] - - if logger.isEnabledFor(logging.WARNING): - project_name = self['Name'] - - if name in _PREDICATE_FIELDS and value is not None: - for v in value: - # check that the values are valid predicates - if not is_valid_predicate(v.split(';')[0]): - logger.warning( - '%r: %r is not a valid predicate (field %r)', - project_name, v, name) - # FIXME this rejects UNKNOWN, is that right? - elif name in _VERSIONS_FIELDS and value is not None: - if not is_valid_versions(value): - logger.warning('%r: %r is not a valid version (field %r)', - project_name, value, name) - elif name in _VERSION_FIELDS and value is not None: - if not is_valid_version(value): - logger.warning('%r: %r is not a valid version (field %r)', - project_name, value, name) - - if name in _UNICODEFIELDS: - if name == 'Description': - value = self._remove_line_prefix(value) - - self._fields[name] = value - self._set_best_version() - - def get(self, name, default=_MISSING): - """Get a metadata field.""" - name = self._convert_name(name) - if name not in self._fields: - if default is _MISSING: - default = self._default_value(name) - return default - if name in _UNICODEFIELDS: - value = self._fields[name] - return value - elif name in _LISTFIELDS: - value = self._fields[name] - if value is None: - return [] - res = [] - for val in value: - valid, val = self._platform(val) - if not valid: - continue - if name not in _LISTTUPLEFIELDS: - res.append(val) - else: - # That's for Project-URL - res.append((val[0], val[1])) - return res - - elif name in _ELEMENTSFIELD: - valid, value = self._platform(self._fields[name]) - if not valid: - return [] - if isinstance(value, str): - return value.split(',') - valid, value = self._platform(self._fields[name]) - if not valid: - return None - return value - - def check(self, strict=False, restructuredtext=False): - """Check if the metadata is compliant. If strict is False then raise if - no Name or Version are provided""" - # XXX should check the versions (if the file was loaded) - missing, warnings = [], [] - - for attr in ('Name', 'Version'): # required by PEP 345 - if attr not in self: - missing.append(attr) - - if strict and missing != []: - msg = 'missing required metadata: %s' % ', '.join(missing) - raise MetadataMissingError(msg) - - for attr in ('Home-page', 'Author'): - if attr not in self: - missing.append(attr) - - if _HAS_DOCUTILS and restructuredtext: - warnings.extend(self._check_rst_data(self['Description'])) - - # checking metadata 1.2 (XXX needs to check 1.1, 1.0) - if self['Metadata-Version'] != '1.2': - return missing, warnings - - def is_valid_predicates(value): - for v in value: - if not is_valid_predicate(v.split(';')[0]): - return False - return True - - for fields, controller in ((_PREDICATE_FIELDS, is_valid_predicates), - (_VERSIONS_FIELDS, is_valid_versions), - (_VERSION_FIELDS, is_valid_version)): - for field in fields: - value = self.get(field, None) - if value is not None and not controller(value): - warnings.append('Wrong value for %r: %s' % (field, value)) - - return missing, warnings - - def todict(self): - """Return fields as a dict. - - Field names will be converted to use the underscore-lowercase style - instead of hyphen-mixed case (i.e. home_page instead of Home-page). - """ - data = { - 'metadata_version': self['Metadata-Version'], - 'name': self['Name'], - 'version': self['Version'], - 'summary': self['Summary'], - 'home_page': self['Home-page'], - 'author': self['Author'], - 'author_email': self['Author-email'], - 'license': self['License'], - 'description': self['Description'], - 'keywords': self['Keywords'], - 'platform': self['Platform'], - 'classifier': self['Classifier'], - 'download_url': self['Download-URL'], - } - - if self['Metadata-Version'] == '1.2': - data['requires_dist'] = self['Requires-Dist'] - data['requires_python'] = self['Requires-Python'] - data['requires_external'] = self['Requires-External'] - data['provides_dist'] = self['Provides-Dist'] - data['obsoletes_dist'] = self['Obsoletes-Dist'] - data['project_url'] = [','.join(url) for url in - self['Project-URL']] - - elif self['Metadata-Version'] == '1.1': - data['provides'] = self['Provides'] - data['requires'] = self['Requires'] - data['obsoletes'] = self['Obsoletes'] - - return data - - # Mapping API - - def keys(self): - return _version2fieldlist(self['Metadata-Version']) - - def __iter__(self): - for key in self.keys(): - yield key - - def values(self): - return [self[key] for key in list(self.keys())] - - def items(self): - return [(key, self[key]) for key in list(self.keys())] diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/pypi/__init__.py --- a/Lib/packaging/pypi/__init__.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -"""Low-level and high-level APIs to interact with project indexes.""" - -__all__ = ['simple', - 'xmlrpc', - 'dist', - 'errors', - 'mirrors'] - -from packaging.pypi.dist import ReleaseInfo, ReleasesList, DistInfo diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/pypi/base.py --- a/Lib/packaging/pypi/base.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -"""Base class for index crawlers.""" - -from packaging.pypi.dist import ReleasesList - - -class BaseClient: - """Base class containing common methods for the index crawlers/clients""" - - def __init__(self, prefer_final, prefer_source): - self._prefer_final = prefer_final - self._prefer_source = prefer_source - self._index = self - - def _get_prefer_final(self, prefer_final=None): - """Return the prefer_final internal parameter or the specified one if - provided""" - if prefer_final: - return prefer_final - else: - return self._prefer_final - - def _get_prefer_source(self, prefer_source=None): - """Return the prefer_source internal parameter or the specified one if - provided""" - if prefer_source: - return prefer_source - else: - return self._prefer_source - - def _get_project(self, project_name): - """Return an project instance, create it if necessary""" - return self._projects.setdefault(project_name.lower(), - ReleasesList(project_name, index=self._index)) - - def download_distribution(self, requirements, temp_path=None, - prefer_source=None, prefer_final=None): - """Download a distribution from the last release according to the - requirements. - - If temp_path is provided, download to this path, otherwise, create a - temporary location for the download and return it. - """ - prefer_final = self._get_prefer_final(prefer_final) - prefer_source = self._get_prefer_source(prefer_source) - release = self.get_release(requirements, prefer_final) - if release: - dist = release.get_distribution(prefer_source=prefer_source) - return dist.download(temp_path) diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/pypi/dist.py --- a/Lib/packaging/pypi/dist.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,547 +0,0 @@ -"""Classes representing releases and distributions retrieved from indexes. - -A project (= unique name) can have several releases (= versions) and -each release can have several distributions (= sdist and bdists). - -Release objects contain metadata-related information (see PEP 376); -distribution objects contain download-related information. -""" - -import sys -import mimetypes -import re -import tempfile -import urllib.request -import urllib.parse -import urllib.error -import urllib.parse -import hashlib -from shutil import unpack_archive - -from packaging.errors import IrrationalVersionError -from packaging.version import (suggest_normalized_version, NormalizedVersion, - get_version_predicate) -from packaging.metadata import Metadata -from packaging.pypi.errors import (HashDoesNotMatch, UnsupportedHashName, - CantParseArchiveName) - - -__all__ = ['ReleaseInfo', 'DistInfo', 'ReleasesList', 'get_infos_from_url'] - -EXTENSIONS = ".tar.gz .tar.bz2 .tar .zip .tgz .egg".split() -MD5_HASH = re.compile(r'^.*#md5=([a-f0-9]+)$') -DIST_TYPES = ['bdist', 'sdist'] - - -class IndexReference: - """Mixin used to store the index reference""" - def set_index(self, index=None): - self._index = index - - -class ReleaseInfo(IndexReference): - """Represent a release of a project (a project with a specific version). - The release contain the _metadata informations related to this specific - version, and is also a container for distribution related informations. - - See the DistInfo class for more information about distributions. - """ - - def __init__(self, name, version, metadata=None, hidden=False, - index=None, **kwargs): - """ - :param name: the name of the distribution - :param version: the version of the distribution - :param metadata: the metadata fields of the release. - :type metadata: dict - :param kwargs: optional arguments for a new distribution. - """ - self.set_index(index) - self.name = name - self._version = None - self.version = version - if metadata: - self.metadata = Metadata(mapping=metadata) - else: - self.metadata = None - self.dists = {} - self.hidden = hidden - - if 'dist_type' in kwargs: - dist_type = kwargs.pop('dist_type') - self.add_distribution(dist_type, **kwargs) - - def set_version(self, version): - try: - self._version = NormalizedVersion(version) - except IrrationalVersionError: - suggestion = suggest_normalized_version(version) - if suggestion: - self.version = suggestion - else: - raise IrrationalVersionError(version) - - def get_version(self): - return self._version - - version = property(get_version, set_version) - - def fetch_metadata(self): - """If the metadata is not set, use the indexes to get it""" - if not self.metadata: - self._index.get_metadata(self.name, str(self.version)) - return self.metadata - - @property - def is_final(self): - """proxy to version.is_final""" - return self.version.is_final - - def fetch_distributions(self): - if self.dists is None: - self._index.get_distributions(self.name, str(self.version)) - if self.dists is None: - self.dists = {} - return self.dists - - def add_distribution(self, dist_type='sdist', python_version=None, - **params): - """Add distribution informations to this release. - If distribution information is already set for this distribution type, - add the given url paths to the distribution. This can be useful while - some of them fails to download. - - :param dist_type: the distribution type (eg. "sdist", "bdist", etc.) - :param params: the fields to be passed to the distribution object - (see the :class:DistInfo constructor). - """ - if dist_type not in DIST_TYPES: - raise ValueError(dist_type) - if dist_type in self.dists: - self.dists[dist_type].add_url(**params) - else: - self.dists[dist_type] = DistInfo(self, dist_type, - index=self._index, **params) - if python_version: - self.dists[dist_type].python_version = python_version - - def get_distribution(self, dist_type=None, prefer_source=True): - """Return a distribution. - - If dist_type is set, find first for this distribution type, and just - act as an alias of __get_item__. - - If prefer_source is True, search first for source distribution, and if - not return one existing distribution. - """ - if len(self.dists) == 0: - raise LookupError - if dist_type: - return self[dist_type] - if prefer_source: - if "sdist" in self.dists: - dist = self["sdist"] - else: - dist = next(self.dists.values()) - return dist - - def unpack(self, path=None, prefer_source=True): - """Unpack the distribution to the given path. - - If not destination is given, creates a temporary location. - - Returns the location of the extracted files (root). - """ - return self.get_distribution(prefer_source=prefer_source)\ - .unpack(path=path) - - def download(self, temp_path=None, prefer_source=True): - """Download the distribution, using the requirements. - - If more than one distribution match the requirements, use the last - version. - Download the distribution, and put it in the temp_path. If no temp_path - is given, creates and return one. - - Returns the complete absolute path to the downloaded archive. - """ - return self.get_distribution(prefer_source=prefer_source)\ - .download(path=temp_path) - - def set_metadata(self, metadata): - if not self.metadata: - self.metadata = Metadata() - self.metadata.update(metadata) - - def __getitem__(self, item): - """distributions are available using release["sdist"]""" - return self.dists[item] - - def _check_is_comparable(self, other): - if not isinstance(other, ReleaseInfo): - raise TypeError("cannot compare %s and %s" - % (type(self).__name__, type(other).__name__)) - elif self.name != other.name: - raise TypeError("cannot compare %s and %s" - % (self.name, other.name)) - - def __repr__(self): - return "<%s %s>" % (self.name, self.version) - - def __eq__(self, other): - self._check_is_comparable(other) - return self.version == other.version - - def __lt__(self, other): - self._check_is_comparable(other) - return self.version < other.version - - def __ne__(self, other): - return not self.__eq__(other) - - def __gt__(self, other): - return not (self.__lt__(other) or self.__eq__(other)) - - def __le__(self, other): - return self.__eq__(other) or self.__lt__(other) - - def __ge__(self, other): - return self.__eq__(other) or self.__gt__(other) - - # See http://docs.python.org/reference/datamodel#object.__hash__ - __hash__ = object.__hash__ - - -class DistInfo(IndexReference): - """Represents a distribution retrieved from an index (sdist, bdist, ...) - """ - - def __init__(self, release, dist_type=None, url=None, hashname=None, - hashval=None, is_external=True, python_version=None, - index=None): - """Create a new instance of DistInfo. - - :param release: a DistInfo class is relative to a release. - :param dist_type: the type of the dist (eg. source, bin-*, etc.) - :param url: URL where we found this distribution - :param hashname: the name of the hash we want to use. Refer to the - hashlib.new documentation for more information. - :param hashval: the hash value. - :param is_external: we need to know if the provided url comes from - an index browsing, or from an external resource. - - """ - self.set_index(index) - self.release = release - self.dist_type = dist_type - self.python_version = python_version - self._unpacked_dir = None - # set the downloaded path to None by default. The goal here - # is to not download distributions multiple times - self.downloaded_location = None - # We store urls in dict, because we need to have a bit more infos - # than the simple URL. It will be used later to find the good url to - # use. - # We have two _url* attributes: _url and urls. urls contains a list - # of dict for the different urls, and _url contains the choosen url, in - # order to dont make the selection process multiple times. - self.urls = [] - self._url = None - self.add_url(url, hashname, hashval, is_external) - - def add_url(self, url=None, hashname=None, hashval=None, is_external=True): - """Add a new url to the list of urls""" - if hashname is not None: - try: - hashlib.new(hashname) - except ValueError: - raise UnsupportedHashName(hashname) - if url not in [u['url'] for u in self.urls]: - self.urls.append({ - 'url': url, - 'hashname': hashname, - 'hashval': hashval, - 'is_external': is_external, - }) - # reset the url selection process - self._url = None - - @property - def url(self): - """Pick up the right url for the list of urls in self.urls""" - # We return internal urls over externals. - # If there is more than one internal or external, return the first - # one. - if self._url is None: - if len(self.urls) > 1: - internals_urls = [u for u in self.urls \ - if u['is_external'] == False] - if len(internals_urls) >= 1: - self._url = internals_urls[0] - if self._url is None: - self._url = self.urls[0] - return self._url - - @property - def is_source(self): - """return if the distribution is a source one or not""" - return self.dist_type == 'sdist' - - def download(self, path=None): - """Download the distribution to a path, and return it. - - If the path is given in path, use this, otherwise, generates a new one - Return the download location. - """ - if path is None: - path = tempfile.mkdtemp() - - # if we do not have downloaded it yet, do it. - if self.downloaded_location is None: - url = self.url['url'] - archive_name = urllib.parse.urlparse(url)[2].split('/')[-1] - filename, headers = urllib.request.urlretrieve(url, - path + "/" + archive_name) - self.downloaded_location = filename - self._check_md5(filename) - return self.downloaded_location - - def unpack(self, path=None): - """Unpack the distribution to the given path. - - If not destination is given, creates a temporary location. - - Returns the location of the extracted files (root). - """ - if not self._unpacked_dir: - if path is None: - path = tempfile.mkdtemp() - - filename = self.download(path) - content_type = mimetypes.guess_type(filename)[0] - unpack_archive(filename, path) - self._unpacked_dir = path - - return path - - def _check_md5(self, filename): - """Check that the md5 checksum of the given file matches the one in - url param""" - hashname = self.url['hashname'] - expected_hashval = self.url['hashval'] - if None not in (expected_hashval, hashname): - with open(filename, 'rb') as f: - hashval = hashlib.new(hashname) - hashval.update(f.read()) - - if hashval.hexdigest() != expected_hashval: - raise HashDoesNotMatch("got %s instead of %s" - % (hashval.hexdigest(), expected_hashval)) - - def __repr__(self): - if self.release is None: - return "" % self.dist_type - - return "<%s %s %s>" % ( - self.release.name, self.release.version, self.dist_type or "") - - -class ReleasesList(IndexReference): - """A container of Release. - - Provides useful methods and facilities to sort and filter releases. - """ - def __init__(self, name, releases=None, contains_hidden=False, index=None): - self.set_index(index) - self.releases = [] - self.name = name - self.contains_hidden = contains_hidden - if releases: - self.add_releases(releases) - - def fetch_releases(self): - self._index.get_releases(self.name) - return self.releases - - def filter(self, predicate): - """Filter and return a subset of releases matching the given predicate. - """ - return ReleasesList(self.name, [release for release in self.releases - if predicate.match(release.version)], - index=self._index) - - def get_last(self, requirements, prefer_final=None): - """Return the "last" release, that satisfy the given predicates. - - "last" is defined by the version number of the releases, you also could - set prefer_final parameter to True or False to change the order results - """ - predicate = get_version_predicate(requirements) - releases = self.filter(predicate) - if len(releases) == 0: - return None - releases.sort_releases(prefer_final, reverse=True) - return releases[0] - - def add_releases(self, releases): - """Add releases in the release list. - - :param: releases is a list of ReleaseInfo objects. - """ - for r in releases: - self.add_release(release=r) - - def add_release(self, version=None, dist_type='sdist', release=None, - **dist_args): - """Add a release to the list. - - The release can be passed in the `release` parameter, and in this case, - it will be crawled to extract the useful informations if necessary, or - the release informations can be directly passed in the `version` and - `dist_type` arguments. - - Other keywords arguments can be provided, and will be forwarded to the - distribution creation (eg. the arguments of the DistInfo constructor). - """ - if release: - if release.name.lower() != self.name.lower(): - raise ValueError("%s is not the same project as %s" % - (release.name, self.name)) - version = str(release.version) - - if version not in self.get_versions(): - # append only if not already exists - self.releases.append(release) - for dist in release.dists.values(): - for url in dist.urls: - self.add_release(version, dist.dist_type, **url) - else: - matches = [r for r in self.releases - if str(r.version) == version and r.name == self.name] - if not matches: - release = ReleaseInfo(self.name, version, index=self._index) - self.releases.append(release) - else: - release = matches[0] - - release.add_distribution(dist_type=dist_type, **dist_args) - - def sort_releases(self, prefer_final=False, reverse=True, *args, **kwargs): - """Sort the results with the given properties. - - The `prefer_final` argument can be used to specify if final - distributions (eg. not dev, bet or alpha) would be prefered or not. - - Results can be inverted by using `reverse`. - - Any other parameter provided will be forwarded to the sorted call. You - cannot redefine the key argument of "sorted" here, as it is used - internally to sort the releases. - """ - - sort_by = [] - if prefer_final: - sort_by.append("is_final") - sort_by.append("version") - - self.releases.sort( - key=lambda i: tuple(getattr(i, arg) for arg in sort_by), - reverse=reverse, *args, **kwargs) - - def get_release(self, version): - """Return a release from its version.""" - matches = [r for r in self.releases if str(r.version) == version] - if len(matches) != 1: - raise KeyError(version) - return matches[0] - - def get_versions(self): - """Return a list of releases versions contained""" - return [str(r.version) for r in self.releases] - - def __getitem__(self, key): - return self.releases[key] - - def __len__(self): - return len(self.releases) - - def __repr__(self): - string = 'Project "%s"' % self.name - if self.get_versions(): - string += ' versions: %s' % ', '.join(self.get_versions()) - return '<%s>' % string - - -def get_infos_from_url(url, probable_dist_name=None, is_external=True): - """Get useful informations from an URL. - - Return a dict of (name, version, url, hashtype, hash, is_external) - - :param url: complete url of the distribution - :param probable_dist_name: A probable name of the project. - :param is_external: Tell if the url commes from an index or from - an external URL. - """ - # if the url contains a md5 hash, get it. - md5_hash = None - match = MD5_HASH.match(url) - if match is not None: - md5_hash = match.group(1) - # remove the hash - url = url.replace("#md5=%s" % md5_hash, "") - - # parse the archive name to find dist name and version - archive_name = urllib.parse.urlparse(url)[2].split('/')[-1] - extension_matched = False - # remove the extension from the name - for ext in EXTENSIONS: - if archive_name.endswith(ext): - archive_name = archive_name[:-len(ext)] - extension_matched = True - - name, version = split_archive_name(archive_name) - if extension_matched is True: - return {'name': name, - 'version': version, - 'url': url, - 'hashname': "md5", - 'hashval': md5_hash, - 'is_external': is_external, - 'dist_type': 'sdist'} - - -def split_archive_name(archive_name, probable_name=None): - """Split an archive name into two parts: name and version. - - Return the tuple (name, version) - """ - # Try to determine wich part is the name and wich is the version using the - # "-" separator. Take the larger part to be the version number then reduce - # if this not works. - def eager_split(str, maxsplit=2): - # split using the "-" separator - splits = str.rsplit("-", maxsplit) - name = splits[0] - version = "-".join(splits[1:]) - if version.startswith("-"): - version = version[1:] - if suggest_normalized_version(version) is None and maxsplit >= 0: - # we dont get a good version number: recurse ! - return eager_split(str, maxsplit - 1) - else: - return name, version - if probable_name is not None: - probable_name = probable_name.lower() - name = None - if probable_name is not None and probable_name in archive_name: - # we get the name from probable_name, if given. - name = probable_name - version = archive_name.lstrip(name) - else: - name, version = eager_split(archive_name) - - version = suggest_normalized_version(version) - if version is not None and name != "": - return name.lower(), version - else: - raise CantParseArchiveName(archive_name) diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/pypi/errors.py --- a/Lib/packaging/pypi/errors.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -"""Exceptions raised by packaging.pypi code.""" - -from packaging.errors import PackagingPyPIError - - -class ProjectNotFound(PackagingPyPIError): - """Project has not been found""" - - -class DistributionNotFound(PackagingPyPIError): - """The release has not been found""" - - -class ReleaseNotFound(PackagingPyPIError): - """The release has not been found""" - - -class CantParseArchiveName(PackagingPyPIError): - """An archive name can't be parsed to find distribution name and version""" - - -class DownloadError(PackagingPyPIError): - """An error has occurs while downloading""" - - -class HashDoesNotMatch(DownloadError): - """Compared hashes does not match""" - - -class UnsupportedHashName(PackagingPyPIError): - """A unsupported hashname has been used""" - - -class UnableToDownload(PackagingPyPIError): - """All mirrors have been tried, without success""" - - -class InvalidSearchField(PackagingPyPIError): - """An invalid search field has been used""" diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/pypi/mirrors.py --- a/Lib/packaging/pypi/mirrors.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -"""Utilities related to the mirror infrastructure defined in PEP 381.""" - -from string import ascii_lowercase -import socket - -DEFAULT_MIRROR_URL = "last.pypi.python.org" - - -def get_mirrors(hostname=None): - """Return the list of mirrors from the last record found on the DNS - entry:: - - >>> from packaging.pypi.mirrors import get_mirrors - >>> get_mirrors() - ['a.pypi.python.org', 'b.pypi.python.org', 'c.pypi.python.org', - 'd.pypi.python.org'] - - """ - if hostname is None: - hostname = DEFAULT_MIRROR_URL - - # return the last mirror registered on PyPI. - try: - hostname = socket.gethostbyname_ex(hostname)[0] - except socket.gaierror: - return [] - end_letter = hostname.split(".", 1) - - # determine the list from the last one. - return ["%s.%s" % (s, end_letter[1]) for s in string_range(end_letter[0])] - - -def string_range(last): - """Compute the range of string between "a" and last. - - This works for simple "a to z" lists, but also for "a to zz" lists. - """ - for k in range(len(last)): - for x in product(ascii_lowercase, repeat=(k + 1)): - result = ''.join(x) - yield result - if result == last: - return - - -def product(*args, **kwds): - pools = [tuple(arg) for arg in args] * kwds.get('repeat', 1) - result = [[]] - for pool in pools: - result = [x + [y] for x in result for y in pool] - for prod in result: - yield tuple(prod) diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/pypi/simple.py --- a/Lib/packaging/pypi/simple.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,465 +0,0 @@ -"""Spider using the screen-scraping "simple" PyPI API. - -This module contains the class Crawler, a simple spider that -can be used to find and retrieve distributions from a project index -(like the Python Package Index), using its so-called simple API (see -reference implementation available at http://pypi.python.org/simple/). -""" - -import http.client -import re -import socket -import sys -import urllib.request -import urllib.parse -import urllib.error -import os - - -from fnmatch import translate -from packaging import logger -from packaging.metadata import Metadata -from packaging.version import get_version_predicate -from packaging import __version__ as packaging_version -from packaging.pypi.base import BaseClient -from packaging.pypi.dist import (ReleasesList, EXTENSIONS, - get_infos_from_url, MD5_HASH) -from packaging.pypi.errors import (PackagingPyPIError, DownloadError, - UnableToDownload, CantParseArchiveName, - ReleaseNotFound, ProjectNotFound) -from packaging.pypi.mirrors import get_mirrors -from packaging.metadata import Metadata - -__all__ = ['Crawler', 'DEFAULT_SIMPLE_INDEX_URL'] - -# -- Constants ----------------------------------------------- -DEFAULT_SIMPLE_INDEX_URL = "http://a.pypi.python.org/simple/" -DEFAULT_HOSTS = ("*",) -SOCKET_TIMEOUT = 15 -USER_AGENT = "Python-urllib/%s packaging/%s" % ( - sys.version[:3], packaging_version) - -# -- Regexps ------------------------------------------------- -EGG_FRAGMENT = re.compile(r'^egg=([-A-Za-z0-9_.]+)$') -HREF = re.compile("""href\\s*=\\s*['"]?([^'"> ]+)""", re.I) -URL_SCHEME = re.compile('([-+.a-z0-9]{2,}):', re.I).match - -# This pattern matches a character entity reference (a decimal numeric -# references, a hexadecimal numeric reference, or a named reference). -ENTITY_SUB = re.compile(r'&(#(\d+|x[\da-fA-F]+)|[\w.:-]+);?').sub -REL = re.compile("""<([^>]*\srel\s*=\s*['"]?([^'">]+)[^>]*)>""", re.I) - - -def socket_timeout(timeout=SOCKET_TIMEOUT): - """Decorator to add a socket timeout when requesting pages on PyPI. - """ - def _socket_timeout(func): - def _socket_timeout(self, *args, **kwargs): - old_timeout = socket.getdefaulttimeout() - if hasattr(self, "_timeout"): - timeout = self._timeout - socket.setdefaulttimeout(timeout) - try: - return func(self, *args, **kwargs) - finally: - socket.setdefaulttimeout(old_timeout) - return _socket_timeout - return _socket_timeout - - -def with_mirror_support(): - """Decorator that makes the mirroring support easier""" - def wrapper(func): - def wrapped(self, *args, **kwargs): - try: - return func(self, *args, **kwargs) - except DownloadError: - # if an error occurs, try with the next index_url - if self._mirrors_tries >= self._mirrors_max_tries: - try: - self._switch_to_next_mirror() - except KeyError: - raise UnableToDownload("Tried all mirrors") - else: - self._mirrors_tries += 1 - self._projects.clear() - return wrapped(self, *args, **kwargs) - return wrapped - return wrapper - - -class Crawler(BaseClient): - """Provides useful tools to request the Python Package Index simple API. - - You can specify both mirrors and mirrors_url, but mirrors_url will only be - used if mirrors is set to None. - - :param index_url: the url of the simple index to search on. - :param prefer_final: if the version is not mentioned, and the last - version is not a "final" one (alpha, beta, etc.), - pick up the last final version. - :param prefer_source: if the distribution type is not mentioned, pick up - the source one if available. - :param follow_externals: tell if following external links is needed or - not. Default is False. - :param hosts: a list of hosts allowed to be processed while using - follow_externals=True. Default behavior is to follow all - hosts. - :param follow_externals: tell if following external links is needed or - not. Default is False. - :param mirrors_url: the url to look on for DNS records giving mirror - adresses. - :param mirrors: a list of mirrors (see PEP 381). - :param timeout: time in seconds to consider a url has timeouted. - :param mirrors_max_tries": number of times to try requesting informations - on mirrors before switching. - """ - - def __init__(self, index_url=DEFAULT_SIMPLE_INDEX_URL, prefer_final=False, - prefer_source=True, hosts=DEFAULT_HOSTS, - follow_externals=False, mirrors_url=None, mirrors=None, - timeout=SOCKET_TIMEOUT, mirrors_max_tries=0, verbose=False): - super(Crawler, self).__init__(prefer_final, prefer_source) - self.follow_externals = follow_externals - self.verbose = verbose - - # mirroring attributes. - parsed = urllib.parse.urlparse(index_url) - self.scheme = parsed[0] - if self.scheme == 'file': - ender = os.path.sep - else: - ender = '/' - if not index_url.endswith(ender): - index_url += ender - # if no mirrors are defined, use the method described in PEP 381. - if mirrors is None: - mirrors = get_mirrors(mirrors_url) - self._mirrors = set(mirrors) - self._mirrors_used = set() - self.index_url = index_url - self._mirrors_max_tries = mirrors_max_tries - self._mirrors_tries = 0 - self._timeout = timeout - - # create a regexp to match all given hosts - self._allowed_hosts = re.compile('|'.join(map(translate, hosts))).match - - # we keep an index of pages we have processed, in order to avoid - # scanning them multple time (eg. if there is multiple pages pointing - # on one) - self._processed_urls = [] - self._projects = {} - - @with_mirror_support() - def search_projects(self, name=None, **kwargs): - """Search the index for projects containing the given name. - - Return a list of names. - """ - with self._open_url(self.index_url) as index: - if '*' in name: - name.replace('*', '.*') - else: - name = "%s%s%s" % ('*.?', name, '*.?') - name = name.replace('*', '[^<]*') # avoid matching end tag - projectname = re.compile(']*>(%s)' % name, re.I) - matching_projects = [] - - index_content = index.read() - - # FIXME should use bytes I/O and regexes instead of decoding - index_content = index_content.decode() - - for match in projectname.finditer(index_content): - project_name = match.group(1) - matching_projects.append(self._get_project(project_name)) - return matching_projects - - def get_releases(self, requirements, prefer_final=None, - force_update=False): - """Search for releases and return a ReleasesList object containing - the results. - """ - predicate = get_version_predicate(requirements) - if predicate.name.lower() in self._projects and not force_update: - return self._projects.get(predicate.name.lower()) - prefer_final = self._get_prefer_final(prefer_final) - logger.debug('Reading info on PyPI about %s', predicate.name) - self._process_index_page(predicate.name) - - if predicate.name.lower() not in self._projects: - raise ProjectNotFound - - releases = self._projects.get(predicate.name.lower()) - releases.sort_releases(prefer_final=prefer_final) - return releases - - def get_release(self, requirements, prefer_final=None): - """Return only one release that fulfill the given requirements""" - predicate = get_version_predicate(requirements) - release = self.get_releases(predicate, prefer_final)\ - .get_last(predicate) - if not release: - raise ReleaseNotFound("No release matches the given criterias") - return release - - def get_distributions(self, project_name, version): - """Return the distributions found on the index for the specific given - release""" - # as the default behavior of get_release is to return a release - # containing the distributions, just alias it. - return self.get_release("%s (%s)" % (project_name, version)) - - def get_metadata(self, project_name, version): - """Return the metadatas from the simple index. - - Currently, download one archive, extract it and use the PKG-INFO file. - """ - release = self.get_distributions(project_name, version) - if not release.metadata: - location = release.get_distribution().unpack() - pkg_info = os.path.join(location, 'PKG-INFO') - release.metadata = Metadata(pkg_info) - return release - - def _switch_to_next_mirror(self): - """Switch to the next mirror (eg. point self.index_url to the next - mirror url. - - Raise a KeyError if all mirrors have been tried. - """ - self._mirrors_used.add(self.index_url) - index_url = self._mirrors.pop() - # XXX use urllib.parse for a real check of missing scheme part - if not index_url.startswith(("http://", "https://", "file://")): - index_url = "http://%s" % index_url - - if not index_url.endswith("/simple"): - index_url = "%s/simple/" % index_url - - self.index_url = index_url - - def _is_browsable(self, url): - """Tell if the given URL can be browsed or not. - - It uses the follow_externals and the hosts list to tell if the given - url is browsable or not. - """ - # if _index_url is contained in the given URL, we are browsing the - # index, and it's always "browsable". - # local files are always considered browable resources - if self.index_url in url or urllib.parse.urlparse(url)[0] == "file": - return True - elif self.follow_externals: - if self._allowed_hosts(urllib.parse.urlparse(url)[1]): # 1 is netloc - return True - else: - return False - return False - - def _is_distribution(self, link): - """Tell if the given URL matches to a distribution name or not. - """ - #XXX find a better way to check that links are distributions - # Using a regexp ? - for ext in EXTENSIONS: - if ext in link: - return True - return False - - def _register_release(self, release=None, release_info={}): - """Register a new release. - - Both a release or a dict of release_info can be provided, the prefered - way (eg. the quicker) is the dict one. - - Return the list of existing releases for the given project. - """ - # Check if the project already has a list of releases (refering to - # the project name). If not, create a new release list. - # Then, add the release to the list. - if release: - name = release.name - else: - name = release_info['name'] - if name.lower() not in self._projects: - self._projects[name.lower()] = ReleasesList(name, index=self._index) - - if release: - self._projects[name.lower()].add_release(release=release) - else: - name = release_info.pop('name') - version = release_info.pop('version') - dist_type = release_info.pop('dist_type') - self._projects[name.lower()].add_release(version, dist_type, - **release_info) - return self._projects[name.lower()] - - def _process_url(self, url, project_name=None, follow_links=True): - """Process an url and search for distributions packages. - - For each URL found, if it's a download, creates a PyPIdistribution - object. If it's a homepage and we can follow links, process it too. - - :param url: the url to process - :param project_name: the project name we are searching for. - :param follow_links: Do not want to follow links more than from one - level. This parameter tells if we want to follow - the links we find (eg. run recursively this - method on it) - """ - with self._open_url(url) as f: - base_url = f.url - if url not in self._processed_urls: - self._processed_urls.append(url) - link_matcher = self._get_link_matcher(url) - for link, is_download in link_matcher(f.read().decode(), base_url): - if link not in self._processed_urls: - if self._is_distribution(link) or is_download: - self._processed_urls.append(link) - # it's a distribution, so create a dist object - try: - infos = get_infos_from_url(link, project_name, - is_external=self.index_url not in url) - except CantParseArchiveName as e: - if self.verbose: - logger.warning( - "version has not been parsed: %s", e) - else: - self._register_release(release_info=infos) - else: - if self._is_browsable(link) and follow_links: - self._process_url(link, project_name, - follow_links=False) - - def _get_link_matcher(self, url): - """Returns the right link matcher function of the given url - """ - if self.index_url in url: - return self._simple_link_matcher - else: - return self._default_link_matcher - - def _get_full_url(self, url, base_url): - return urllib.parse.urljoin(base_url, self._htmldecode(url)) - - def _simple_link_matcher(self, content, base_url): - """Yield all links with a rel="download" or rel="homepage". - - This matches the simple index requirements for matching links. - If follow_externals is set to False, dont yeld the external - urls. - - :param content: the content of the page we want to parse - :param base_url: the url of this page. - """ - for match in HREF.finditer(content): - url = self._get_full_url(match.group(1), base_url) - if MD5_HASH.match(url): - yield (url, True) - - for match in REL.finditer(content): - # search for rel links. - tag, rel = match.groups() - rels = [s.strip() for s in rel.lower().split(',')] - if 'homepage' in rels or 'download' in rels: - for match in HREF.finditer(tag): - url = self._get_full_url(match.group(1), base_url) - if 'download' in rels or self._is_browsable(url): - # yield a list of (url, is_download) - yield (url, 'download' in rels) - - def _default_link_matcher(self, content, base_url): - """Yield all links found on the page. - """ - for match in HREF.finditer(content): - url = self._get_full_url(match.group(1), base_url) - if self._is_browsable(url): - yield (url, False) - - @with_mirror_support() - def _process_index_page(self, name): - """Find and process a PyPI page for the given project name. - - :param name: the name of the project to find the page - """ - # Browse and index the content of the given PyPI page. - if self.scheme == 'file': - ender = os.path.sep - else: - ender = '/' - url = self.index_url + name + ender - self._process_url(url, name) - - @socket_timeout() - def _open_url(self, url): - """Open a urllib2 request, handling HTTP authentication, and local - files support. - - """ - scheme, netloc, path, params, query, frag = urllib.parse.urlparse(url) - - # authentication stuff - if scheme in ('http', 'https'): - auth, host = urllib.parse.splituser(netloc) - else: - auth = None - - # add index.html automatically for filesystem paths - if scheme == 'file': - if url.endswith(os.path.sep): - url += "index.html" - - # add authorization headers if auth is provided - if auth: - auth = "Basic " + \ - urllib.parse.unquote(auth).encode('base64').strip() - new_url = urllib.parse.urlunparse(( - scheme, host, path, params, query, frag)) - request = urllib.request.Request(new_url) - request.add_header("Authorization", auth) - else: - request = urllib.request.Request(url) - request.add_header('User-Agent', USER_AGENT) - try: - fp = urllib.request.urlopen(request) - except (ValueError, http.client.InvalidURL) as v: - msg = ' '.join([str(arg) for arg in v.args]) - raise PackagingPyPIError('%s %s' % (url, msg)) - except urllib.error.HTTPError as v: - return v - except urllib.error.URLError as v: - raise DownloadError("Download error for %s: %s" % (url, v.reason)) - except http.client.BadStatusLine as v: - raise DownloadError('%s returned a bad status line. ' - 'The server might be down, %s' % (url, v.line)) - except http.client.HTTPException as v: - raise DownloadError("Download error for %s: %s" % (url, v)) - except socket.timeout: - raise DownloadError("The server timeouted") - - if auth: - # Put authentication info back into request URL if same host, - # so that links found on the page will work - s2, h2, path2, param2, query2, frag2 = \ - urllib.parse.urlparse(fp.url) - if s2 == scheme and h2 == host: - fp.url = urllib.parse.urlunparse( - (s2, netloc, path2, param2, query2, frag2)) - return fp - - def _decode_entity(self, match): - what = match.group(1) - if what.startswith('#x'): - what = int(what[2:], 16) - elif what.startswith('#'): - what = int(what[1:]) - else: - from html.entities import name2codepoint - what = name2codepoint.get(what, match.group(0)) - return chr(what) - - def _htmldecode(self, text): - """Decode HTML entities in the given text.""" - return ENTITY_SUB(self._decode_entity, text) diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/pypi/wrapper.py --- a/Lib/packaging/pypi/wrapper.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -"""Convenient client for all PyPI APIs. - -This module provides a ClientWrapper class which will use the "simple" -or XML-RPC API to request information or files from an index. -""" - -from packaging.pypi import simple, xmlrpc - -_WRAPPER_MAPPINGS = {'get_release': 'simple', - 'get_releases': 'simple', - 'search_projects': 'simple', - 'get_metadata': 'xmlrpc', - 'get_distributions': 'simple'} - -_WRAPPER_INDEXES = {'xmlrpc': xmlrpc.Client, - 'simple': simple.Crawler} - - -def switch_index_if_fails(func, wrapper): - """Decorator that switch of index (for instance from xmlrpc to simple) - if the first mirror return an empty list or raises an exception. - """ - def decorator(*args, **kwargs): - retry = True - exception = None - methods = [func] - for f in wrapper._indexes.values(): - if f != func.__self__ and hasattr(f, func.__name__): - methods.append(getattr(f, func.__name__)) - for method in methods: - try: - response = method(*args, **kwargs) - retry = False - except Exception as e: - exception = e - if not retry: - break - if retry and exception: - raise exception - else: - return response - return decorator - - -class ClientWrapper: - """Wrapper around simple and xmlrpc clients, - - Choose the best implementation to use depending the needs, using the given - mappings. - If one of the indexes returns an error, tries to use others indexes. - - :param index: tell which index to rely on by default. - :param index_classes: a dict of name:class to use as indexes. - :param indexes: a dict of name:index already instantiated - :param mappings: the mappings to use for this wrapper - """ - - def __init__(self, default_index='simple', index_classes=_WRAPPER_INDEXES, - indexes={}, mappings=_WRAPPER_MAPPINGS): - self._projects = {} - self._mappings = mappings - self._indexes = indexes - self._default_index = default_index - - # instantiate the classes and set their _project attribute to the one - # of the wrapper. - for name, cls in index_classes.items(): - obj = self._indexes.setdefault(name, cls()) - obj._projects = self._projects - obj._index = self - - def __getattr__(self, method_name): - """When asking for methods of the wrapper, return the implementation of - the wrapped classes, depending the mapping. - - Decorate the methods to switch of implementation if an error occurs - """ - real_method = None - if method_name in _WRAPPER_MAPPINGS: - obj = self._indexes[_WRAPPER_MAPPINGS[method_name]] - real_method = getattr(obj, method_name) - else: - # the method is not defined in the mappings, so we try first to get - # it via the default index, and rely on others if needed. - try: - real_method = getattr(self._indexes[self._default_index], - method_name) - except AttributeError: - other_indexes = [i for i in self._indexes - if i != self._default_index] - for index in other_indexes: - real_method = getattr(self._indexes[index], method_name, - None) - if real_method: - break - if real_method: - return switch_index_if_fails(real_method, self) - else: - raise AttributeError("No index have attribute '%s'" % method_name) diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/pypi/xmlrpc.py --- a/Lib/packaging/pypi/xmlrpc.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,200 +0,0 @@ -"""Spider using the XML-RPC PyPI API. - -This module contains the class Client, a spider that can be used to find -and retrieve distributions from a project index (like the Python Package -Index), using its XML-RPC API (see documentation of the reference -implementation at http://wiki.python.org/moin/PyPiXmlRpc). -""" - -import xmlrpc.client - -from packaging import logger -from packaging.errors import IrrationalVersionError -from packaging.version import get_version_predicate -from packaging.pypi.base import BaseClient -from packaging.pypi.errors import (ProjectNotFound, InvalidSearchField, - ReleaseNotFound) -from packaging.pypi.dist import ReleaseInfo - -__all__ = ['Client', 'DEFAULT_XMLRPC_INDEX_URL'] - -DEFAULT_XMLRPC_INDEX_URL = 'http://python.org/pypi' - -_SEARCH_FIELDS = ['name', 'version', 'author', 'author_email', 'maintainer', - 'maintainer_email', 'home_page', 'license', 'summary', - 'description', 'keywords', 'platform', 'download_url'] - - -class Client(BaseClient): - """Client to query indexes using XML-RPC method calls. - - If no server_url is specified, use the default PyPI XML-RPC URL, - defined in the DEFAULT_XMLRPC_INDEX_URL constant:: - - >>> client = Client() - >>> client.server_url == DEFAULT_XMLRPC_INDEX_URL - True - - >>> client = Client("http://someurl/") - >>> client.server_url - 'http://someurl/' - """ - - def __init__(self, server_url=DEFAULT_XMLRPC_INDEX_URL, prefer_final=False, - prefer_source=True): - super(Client, self).__init__(prefer_final, prefer_source) - self.server_url = server_url - self._projects = {} - - def get_release(self, requirements, prefer_final=False): - """Return a release with all complete metadata and distribution - related informations. - """ - prefer_final = self._get_prefer_final(prefer_final) - predicate = get_version_predicate(requirements) - releases = self.get_releases(predicate.name) - release = releases.get_last(predicate, prefer_final) - self.get_metadata(release.name, str(release.version)) - self.get_distributions(release.name, str(release.version)) - return release - - def get_releases(self, requirements, prefer_final=None, show_hidden=True, - force_update=False): - """Return the list of existing releases for a specific project. - - Cache the results from one call to another. - - If show_hidden is True, return the hidden releases too. - If force_update is True, reprocess the index to update the - informations (eg. make a new XML-RPC call). - :: - - >>> client = Client() - >>> client.get_releases('Foo') - ['1.1', '1.2', '1.3'] - - If no such project exists, raise a ProjectNotFound exception:: - - >>> client.get_project_versions('UnexistingProject') - ProjectNotFound: UnexistingProject - - """ - def get_versions(project_name, show_hidden): - return self.proxy.package_releases(project_name, show_hidden) - - predicate = get_version_predicate(requirements) - prefer_final = self._get_prefer_final(prefer_final) - project_name = predicate.name - if not force_update and (project_name.lower() in self._projects): - project = self._projects[project_name.lower()] - if not project.contains_hidden and show_hidden: - # if hidden releases are requested, and have an existing - # list of releases that does not contains hidden ones - all_versions = get_versions(project_name, show_hidden) - existing_versions = project.get_versions() - hidden_versions = set(all_versions) - set(existing_versions) - for version in hidden_versions: - project.add_release(release=ReleaseInfo(project_name, - version, index=self._index)) - else: - versions = get_versions(project_name, show_hidden) - if not versions: - raise ProjectNotFound(project_name) - project = self._get_project(project_name) - project.add_releases([ReleaseInfo(project_name, version, - index=self._index) - for version in versions]) - project = project.filter(predicate) - if len(project) == 0: - raise ReleaseNotFound("%s" % predicate) - project.sort_releases(prefer_final) - return project - - - def get_distributions(self, project_name, version): - """Grab informations about distributions from XML-RPC. - - Return a ReleaseInfo object, with distribution-related informations - filled in. - """ - url_infos = self.proxy.release_urls(project_name, version) - project = self._get_project(project_name) - if version not in project.get_versions(): - project.add_release(release=ReleaseInfo(project_name, version, - index=self._index)) - release = project.get_release(version) - for info in url_infos: - packagetype = info['packagetype'] - dist_infos = {'url': info['url'], - 'hashval': info['md5_digest'], - 'hashname': 'md5', - 'is_external': False, - 'python_version': info['python_version']} - release.add_distribution(packagetype, **dist_infos) - return release - - def get_metadata(self, project_name, version): - """Retrieve project metadata. - - Return a ReleaseInfo object, with metadata informations filled in. - """ - # to be case-insensitive, get the informations from the XMLRPC API - projects = [d['name'] for d in - self.proxy.search({'name': project_name}) - if d['name'].lower() == project_name] - if len(projects) > 0: - project_name = projects[0] - - metadata = self.proxy.release_data(project_name, version) - project = self._get_project(project_name) - if version not in project.get_versions(): - project.add_release(release=ReleaseInfo(project_name, version, - index=self._index)) - release = project.get_release(version) - release.set_metadata(metadata) - return release - - def search_projects(self, name=None, operator="or", **kwargs): - """Find using the keys provided in kwargs. - - You can set operator to "and" or "or". - """ - for key in kwargs: - if key not in _SEARCH_FIELDS: - raise InvalidSearchField(key) - if name: - kwargs["name"] = name - projects = self.proxy.search(kwargs, operator) - for p in projects: - project = self._get_project(p['name']) - try: - project.add_release(release=ReleaseInfo(p['name'], - p['version'], metadata={'summary': p['summary']}, - index=self._index)) - except IrrationalVersionError as e: - logger.warning("Irrational version error found: %s", e) - return [self._projects[p['name'].lower()] for p in projects] - - def get_all_projects(self): - """Return the list of all projects registered in the package index""" - projects = self.proxy.list_packages() - for name in projects: - self.get_releases(name, show_hidden=True) - - return [self._projects[name.lower()] for name in set(projects)] - - @property - def proxy(self): - """Property used to return the XMLRPC server proxy. - - If no server proxy is defined yet, creates a new one:: - - >>> client = Client() - >>> client.proxy() - - - """ - if not hasattr(self, '_server_proxy'): - self._server_proxy = xmlrpc.client.ServerProxy(self.server_url) - - return self._server_proxy diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/run.py --- a/Lib/packaging/run.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,685 +0,0 @@ -"""Main command line parser. Implements the pysetup script.""" - -import os -import re -import sys -import getopt -import logging - -from packaging import logger -from packaging.dist import Distribution -from packaging.util import _is_archive_file, generate_setup_py -from packaging.command import get_command_class, STANDARD_COMMANDS -from packaging.install import install, install_local_project, remove -from packaging.database import get_distribution, get_distributions -from packaging.depgraph import generate_graph -from packaging.fancy_getopt import FancyGetopt -from packaging.errors import (PackagingArgError, PackagingError, - PackagingModuleError, PackagingClassError, - CCompilerError) - - -command_re = re.compile(r'^[a-zA-Z]([a-zA-Z0-9_]*)$') - -common_usage = """\ -Actions: -%(actions)s - -To get more help on an action, use: - - pysetup action --help -""" - -create_usage = """\ -Usage: pysetup create - or: pysetup create --help - -Create a new Python project. -""" - -generate_usage = """\ -Usage: pysetup generate-setup - or: pysetup generate-setup --help - -Generate a setup.py script for backward-compatibility purposes. -""" - - -graph_usage = """\ -Usage: pysetup graph dist - or: pysetup graph --help - -Print dependency graph for the distribution. - -positional arguments: - dist installed distribution name -""" - -install_usage = """\ -Usage: pysetup install [dist] - or: pysetup install [archive] - or: pysetup install [src_dir] - or: pysetup install --help - -Install a Python distribution from the indexes, source directory, or sdist. - -positional arguments: - archive path to source distribution (zip, tar.gz) - dist distribution name to install from the indexes - scr_dir path to source directory - -""" - -metadata_usage = """\ -Usage: pysetup metadata [dist] [-f field ...] - or: pysetup metadata [dist] [--all] - or: pysetup metadata --help - -Print metadata for the distribution. - -positional arguments: - dist installed distribution name - -optional arguments: - -f metadata field to print - --all print all metadata fields -""" - -remove_usage = """\ -Usage: pysetup remove dist [-y] - or: pysetup remove --help - -Uninstall a Python distribution. - -positional arguments: - dist installed distribution name - -optional arguments: - -y auto confirm distribution removal -""" - -run_usage = """\ -Usage: pysetup run [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...] - or: pysetup run --help - or: pysetup run --list-commands - or: pysetup run cmd --help -""" - -list_usage = """\ -Usage: pysetup list dist [dist ...] - or: pysetup list --help - or: pysetup list --all - -Print name, version and location for the matching installed distributions. - -positional arguments: - dist installed distribution name - -optional arguments: - --all list all installed distributions -""" - -search_usage = """\ -Usage: pysetup search [project] [--simple [url]] [--xmlrpc [url] [--fieldname value ...] --operator or|and] - or: pysetup search --help - -Search the indexes for the matching projects. - -positional arguments: - project the project pattern to search for - -optional arguments: - --xmlrpc [url] wether to use the xmlrpc index or not. If an url is - specified, it will be used rather than the default one. - - --simple [url] wether to use the simple index or not. If an url is - specified, it will be used rather than the default one. - - --fieldname value Make a search on this field. Can only be used if - --xmlrpc has been selected or is the default index. - - --operator or|and Defines what is the operator to use when doing xmlrpc - searchs with multiple fieldnames. Can only be used if - --xmlrpc has been selected or is the default index. -""" - -global_options = [ - # The fourth entry for verbose means that it can be repeated. - ('verbose', 'v', "run verbosely (default)", True), - ('quiet', 'q', "run quietly (turns verbosity off)"), - ('dry-run', 'n', "don't actually do anything"), - ('help', 'h', "show detailed help message"), - ('no-user-cfg', None, 'ignore pydistutils.cfg in your home directory'), - ('version', None, 'Display the version'), -] - -negative_opt = {'quiet': 'verbose'} - -display_options = [ - ('help-commands', None, "list all available commands"), -] - -display_option_names = [x[0].replace('-', '_') for x in display_options] - - -def _parse_args(args, options, long_options): - """Transform sys.argv input into a dict. - - :param args: the args to parse (i.e sys.argv) - :param options: the list of options to pass to getopt - :param long_options: the list of string with the names of the long options - to be passed to getopt. - - The function returns a dict with options/long_options as keys and matching - values as values. - """ - optlist, args = getopt.gnu_getopt(args, options, long_options) - optdict = {} - optdict['args'] = args - for k, v in optlist: - k = k.lstrip('-') - if k not in optdict: - optdict[k] = [] - if v: - optdict[k].append(v) - else: - optdict[k].append(v) - return optdict - - -class action_help: - """Prints a help message when the standard help flags: -h and --help - are used on the commandline. - """ - - def __init__(self, help_msg): - self.help_msg = help_msg - - def __call__(self, f): - def wrapper(*args, **kwargs): - f_args = args[1] - if '--help' in f_args or '-h' in f_args: - print(self.help_msg) - return - return f(*args, **kwargs) - return wrapper - - -@action_help(create_usage) -def _create(distpatcher, args, **kw): - from packaging.create import main - return main() - - -@action_help(generate_usage) -def _generate(distpatcher, args, **kw): - generate_setup_py() - print('The setup.py was generated') - - -@action_help(graph_usage) -def _graph(dispatcher, args, **kw): - name = args[1] - dist = get_distribution(name, use_egg_info=True) - if dist is None: - print('Distribution not found.') - else: - dists = get_distributions(use_egg_info=True) - graph = generate_graph(dists) - print(graph.repr_node(dist)) - - -@action_help(install_usage) -def _install(dispatcher, args, **kw): - # first check if we are in a source directory - if len(args) < 2: - # are we inside a project dir? - listing = os.listdir(os.getcwd()) - if 'setup.py' in listing or 'setup.cfg' in listing: - args.insert(1, os.getcwd()) - else: - logger.warning('No project to install.') - return 1 - - target = args[1] - # installing from a source dir or archive file? - if os.path.isdir(target) or _is_archive_file(target): - if install_local_project(target): - return 0 - else: - return 1 - else: - # download from PyPI - if install(target): - return 0 - else: - return 1 - - -@action_help(metadata_usage) -def _metadata(dispatcher, args, **kw): - opts = _parse_args(args[1:], 'f:', ['all']) - if opts['args']: - name = opts['args'][0] - dist = get_distribution(name, use_egg_info=True) - if dist is None: - logger.warning('%s not installed', name) - return - else: - logger.info('searching local dir for metadata') - dist = Distribution() - dist.parse_config_files() - - metadata = dist.metadata - - if 'all' in opts: - keys = metadata.keys() - else: - if 'f' in opts: - keys = (k for k in opts['f'] if k in metadata) - else: - keys = () - - for key in keys: - if key in metadata: - print(metadata._convert_name(key) + ':') - value = metadata[key] - if isinstance(value, list): - for v in value: - print(' ', v) - else: - print(' ', value.replace('\n', '\n ')) - - -@action_help(remove_usage) -def _remove(distpatcher, args, **kw): - opts = _parse_args(args[1:], 'y', []) - if 'y' in opts: - auto_confirm = True - else: - auto_confirm = False - - for dist in set(opts['args']): - try: - remove(dist, auto_confirm=auto_confirm) - except PackagingError: - logger.warning('%s not installed', dist) - - -@action_help(run_usage) -def _run(dispatcher, args, **kw): - parser = dispatcher.parser - args = args[1:] - - commands = STANDARD_COMMANDS # + extra commands - - if args == ['--list-commands']: - print('List of available commands:') - cmds = sorted(commands) - - for cmd in cmds: - cls = dispatcher.cmdclass.get(cmd) or get_command_class(cmd) - desc = getattr(cls, 'description', - '(no description available)') - print(' %s: %s' % (cmd, desc)) - return - - while args: - args = dispatcher._parse_command_opts(parser, args) - if args is None: - return - - # create the Distribution class - # need to feed setup.cfg here ! - dist = Distribution() - - # Find and parse the config file(s): they will override options from - # the setup script, but be overridden by the command line. - - # XXX still need to be extracted from Distribution - dist.parse_config_files() - - try: - for cmd in dispatcher.commands: - dist.run_command(cmd, dispatcher.command_options[cmd]) - - except KeyboardInterrupt: - raise SystemExit("interrupted") - except (IOError, os.error, PackagingError, CCompilerError) as msg: - raise SystemExit("error: " + str(msg)) - - # XXX this is crappy - return dist - - -@action_help(list_usage) -def _list(dispatcher, args, **kw): - opts = _parse_args(args[1:], '', ['all']) - dists = get_distributions(use_egg_info=True) - if 'all' in opts or opts['args'] == []: - results = dists - else: - results = [d for d in dists if d.name.lower() in opts['args']] - - number = 0 - for dist in results: - print('%s %s at %s' % (dist.name, dist.metadata['version'], dist.path)) - number += 1 - - print() - if number == 0: - print('Nothing seems to be installed.') - else: - print('Found %d projects installed.' % number) - - -@action_help(search_usage) -def _search(dispatcher, args, **kw): - """The search action. - - It is able to search for a specific index (specified with --index), using - the simple or xmlrpc index types (with --type xmlrpc / --type simple) - """ - #opts = _parse_args(args[1:], '', ['simple', 'xmlrpc']) - # 1. what kind of index is requested ? (xmlrpc / simple) - raise NotImplementedError - - -actions = [ - ('run', 'Run one or several commands', _run), - ('metadata', 'Display the metadata of a project', _metadata), - ('install', 'Install a project', _install), - ('remove', 'Remove a project', _remove), - ('search', 'Search for a project in the indexes', _search), - ('list', 'List installed releases', _list), - ('graph', 'Display a graph', _graph), - ('create', 'Create a project', _create), - ('generate-setup', 'Generate a backward-comptatible setup.py', _generate), -] - - -class Dispatcher: - """Reads the command-line options - """ - def __init__(self, args=None): - self.verbose = 1 - self.dry_run = False - self.help = False - self.cmdclass = {} - self.commands = [] - self.command_options = {} - - for attr in display_option_names: - setattr(self, attr, False) - - self.parser = FancyGetopt(global_options + display_options) - self.parser.set_negative_aliases(negative_opt) - # FIXME this parses everything, including command options (e.g. "run - # build -i" errors with "option -i not recognized") - args = self.parser.getopt(args=args, object=self) - - # if first arg is "run", we have some commands - if len(args) == 0: - self.action = None - else: - self.action = args[0] - - allowed = [action[0] for action in actions] + [None] - if self.action not in allowed: - msg = 'Unrecognized action "%s"' % self.action - raise PackagingArgError(msg) - - self._set_logger() - self.args = args - - # for display options we return immediately - if self.help or self.action is None: - self._show_help(self.parser, display_options_=False) - - def _set_logger(self): - # setting up the logging level from the command-line options - # -q gets warning, error and critical - if self.verbose == 0: - level = logging.WARNING - # default level or -v gets info too - # XXX there's a bug somewhere: the help text says that -v is default - # (and verbose is set to 1 above), but when the user explicitly gives - # -v on the command line, self.verbose is incremented to 2! Here we - # compensate for that (I tested manually). On a related note, I think - # it's a good thing to use -q/nothing/-v/-vv on the command line - # instead of logging constants; it will be easy to add support for - # logging configuration in setup.cfg for advanced users. --merwok - elif self.verbose in (1, 2): - level = logging.INFO - else: # -vv and more for debug - level = logging.DEBUG - - # setting up the stream handler - handler = logging.StreamHandler(sys.stderr) - handler.setLevel(level) - logger.addHandler(handler) - logger.setLevel(level) - - def _parse_command_opts(self, parser, args): - # Pull the current command from the head of the command line - command = args[0] - if not command_re.match(command): - raise SystemExit("invalid command name %r" % (command,)) - self.commands.append(command) - - # Dig up the command class that implements this command, so we - # 1) know that it's a valid command, and 2) know which options - # it takes. - try: - cmd_class = get_command_class(command) - except PackagingModuleError as msg: - raise PackagingArgError(msg) - - # XXX We want to push this in packaging.command - # - # Require that the command class be derived from Command -- want - # to be sure that the basic "command" interface is implemented. - for meth in ('initialize_options', 'finalize_options', 'run'): - if hasattr(cmd_class, meth): - continue - raise PackagingClassError( - 'command %r must implement %r' % (cmd_class, meth)) - - # Also make sure that the command object provides a list of its - # known options. - if not (hasattr(cmd_class, 'user_options') and - isinstance(cmd_class.user_options, list)): - raise PackagingClassError( - "command class %s must provide " - "'user_options' attribute (a list of tuples)" % cmd_class) - - # If the command class has a list of negative alias options, - # merge it in with the global negative aliases. - _negative_opt = negative_opt.copy() - - if hasattr(cmd_class, 'negative_opt'): - _negative_opt.update(cmd_class.negative_opt) - - # Check for help_options in command class. They have a different - # format (tuple of four) so we need to preprocess them here. - if (hasattr(cmd_class, 'help_options') and - isinstance(cmd_class.help_options, list)): - help_options = cmd_class.help_options[:] - else: - help_options = [] - - # All commands support the global options too, just by adding - # in 'global_options'. - parser.set_option_table(global_options + - cmd_class.user_options + - help_options) - parser.set_negative_aliases(_negative_opt) - args, opts = parser.getopt(args[1:]) - - if hasattr(opts, 'help') and opts.help: - self._show_command_help(cmd_class) - return - - if (hasattr(cmd_class, 'help_options') and - isinstance(cmd_class.help_options, list)): - help_option_found = False - for help_option, short, desc, func in cmd_class.help_options: - if hasattr(opts, help_option.replace('-', '_')): - help_option_found = True - if hasattr(func, '__call__'): - func() - else: - raise PackagingClassError( - "invalid help function %r for help option %r: " - "must be a callable object (function, etc.)" - % (func, help_option)) - - if help_option_found: - return - - # Put the options from the command line into their official - # holding pen, the 'command_options' dictionary. - opt_dict = self.get_option_dict(command) - for name, value in vars(opts).items(): - opt_dict[name] = ("command line", value) - - return args - - def get_option_dict(self, command): - """Get the option dictionary for a given command. If that - command's option dictionary hasn't been created yet, then create it - and return the new dictionary; otherwise, return the existing - option dictionary. - """ - d = self.command_options.get(command) - if d is None: - d = self.command_options[command] = {} - return d - - def show_help(self): - self._show_help(self.parser) - - def print_usage(self, parser): - parser.set_option_table(global_options) - - actions_ = [' %s: %s' % (name, desc) for name, desc, __ in actions] - usage = common_usage % {'actions': '\n'.join(actions_)} - - parser.print_help(usage + "\nGlobal options:") - - def _show_help(self, parser, global_options_=True, display_options_=True, - commands=[]): - # late import because of mutual dependence between these modules - from packaging.command.cmd import Command - - print('Usage: pysetup [options] action [action_options]') - print() - if global_options_: - self.print_usage(self.parser) - print() - - if display_options_: - parser.set_option_table(display_options) - parser.print_help( - "Information display options (just display " + - "information, ignore any commands)") - print() - - for command in commands: - if isinstance(command, type) and issubclass(command, Command): - cls = command - else: - cls = get_command_class(command) - if (hasattr(cls, 'help_options') and - isinstance(cls.help_options, list)): - parser.set_option_table(cls.user_options + cls.help_options) - else: - parser.set_option_table(cls.user_options) - - parser.print_help("Options for %r command:" % cls.__name__) - print() - - def _show_command_help(self, command): - if isinstance(command, str): - command = get_command_class(command) - - desc = getattr(command, 'description', '(no description available)') - print('Description:', desc) - print() - - if (hasattr(command, 'help_options') and - isinstance(command.help_options, list)): - self.parser.set_option_table(command.user_options + - command.help_options) - else: - self.parser.set_option_table(command.user_options) - - self.parser.print_help("Options:") - print() - - def _get_command_groups(self): - """Helper function to retrieve all the command class names divided - into standard commands (listed in - packaging.command.STANDARD_COMMANDS) and extra commands (given in - self.cmdclass and not standard commands). - """ - extra_commands = [cmd for cmd in self.cmdclass - if cmd not in STANDARD_COMMANDS] - return STANDARD_COMMANDS, extra_commands - - def print_commands(self): - """Print out a help message listing all available commands with a - description of each. The list is divided into standard commands - (listed in packaging.command.STANDARD_COMMANDS) and extra commands - (given in self.cmdclass and not standard commands). The - descriptions come from the command class attribute - 'description'. - """ - std_commands, extra_commands = self._get_command_groups() - max_length = max(len(command) - for commands in (std_commands, extra_commands) - for command in commands) - - self.print_command_list(std_commands, "Standard commands", max_length) - if extra_commands: - print() - self.print_command_list(extra_commands, "Extra commands", - max_length) - - def print_command_list(self, commands, header, max_length): - """Print a subset of the list of all commands -- used by - 'print_commands()'. - """ - print(header + ":") - - for cmd in commands: - cls = self.cmdclass.get(cmd) or get_command_class(cmd) - description = getattr(cls, 'description', - '(no description available)') - - print(" %-*s %s" % (max_length, cmd, description)) - - def __call__(self): - if self.action is None: - return - for action, desc, func in actions: - if action == self.action: - return func(self, self.args) - return -1 - - -def main(args=None): - old_level = logger.level - old_handlers = list(logger.handlers) - try: - dispatcher = Dispatcher(args) - if dispatcher.action is None: - return - return dispatcher() - finally: - logger.setLevel(old_level) - logger.handlers[:] = old_handlers - - -if __name__ == '__main__': - sys.exit(main()) diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/LONG_DESC.txt --- a/Lib/packaging/tests/LONG_DESC.txt Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -CLVault -======= - -CLVault uses Keyring to provide a command-line utility to safely store -and retrieve passwords. - -Install it using pip or the setup.py script:: - - $ python setup.py install - - $ pip install clvault - -Once it's installed, you will have three scripts installed in your -Python scripts folder, you can use to list, store and retrieve passwords:: - - $ clvault-set blog - Set your password: - Set the associated username (can be blank): tarek - Set a description (can be blank): My blog password - Password set. - - $ clvault-get blog - The username is "tarek" - The password has been copied in your clipboard - - $ clvault-list - Registered services: - blog My blog password - - -*clvault-set* takes a service name then prompt you for a password, and some -optional information about your service. The password is safely stored in -a keyring while the description is saved in a ``.clvault`` file in your -home directory. This file is created automatically the first time the command -is used. - -*clvault-get* copies the password for a given service in your clipboard, and -displays the associated user if any. - -*clvault-list* lists all registered services, with their description when -given. - - -Project page: http://bitbucket.org/tarek/clvault diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/PKG-INFO --- a/Lib/packaging/tests/PKG-INFO Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -Metadata-Version: 1.2 -Name: CLVault -Version: 0.5 -Summary: Command-Line utility to store and retrieve passwords -Home-page: http://bitbucket.org/tarek/clvault -Author: Tarek Ziade -Author-email: tarek@ziade.org -License: PSF -Keywords: keyring,password,crypt -Requires-Dist: foo; sys.platform == 'okook' -Requires-Dist: bar; sys.platform == '%s' -Platform: UNKNOWN -Description: CLVault - |======= - | - |CLVault uses Keyring to provide a command-line utility to safely store - |and retrieve passwords. - | - |Install it using pip or the setup.py script:: - | - | $ python setup.py install - | - | $ pip install clvault - | - |Once it's installed, you will have three scripts installed in your - |Python scripts folder, you can use to list, store and retrieve passwords:: - | - | $ clvault-set blog - | Set your password: - | Set the associated username (can be blank): tarek - | Set a description (can be blank): My blog password - | Password set. - | - | $ clvault-get blog - | The username is "tarek" - | The password has been copied in your clipboard - | - | $ clvault-list - | Registered services: - | blog My blog password - | - | - |*clvault-set* takes a service name then prompt you for a password, and some - |optional information about your service. The password is safely stored in - |a keyring while the description is saved in a ``.clvault`` file in your - |home directory. This file is created automatically the first time the command - |is used. - | - |*clvault-get* copies the password for a given service in your clipboard, and - |displays the associated user if any. - | - |*clvault-list* lists all registered services, with their description when - |given. - | - | - |Project page: http://bitbucket.org/tarek/clvault - | diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/SETUPTOOLS-PKG-INFO --- a/Lib/packaging/tests/SETUPTOOLS-PKG-INFO Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,182 +0,0 @@ -Metadata-Version: 1.0 -Name: setuptools -Version: 0.6c9 -Summary: Download, build, install, upgrade, and uninstall Python packages -- easily! -Home-page: http://pypi.python.org/pypi/setuptools -Author: Phillip J. Eby -Author-email: distutils-sig@python.org -License: PSF or ZPL -Description: =============================== - Installing and Using Setuptools - =============================== - - .. contents:: **Table of Contents** - - - ------------------------- - Installation Instructions - ------------------------- - - Windows - ======= - - Install setuptools using the provided ``.exe`` installer. If you've previously - installed older versions of setuptools, please delete all ``setuptools*.egg`` - and ``setuptools.pth`` files from your system's ``site-packages`` directory - (and any other ``sys.path`` directories) FIRST. - - If you are upgrading a previous version of setuptools that was installed using - an ``.exe`` installer, please be sure to also *uninstall that older version* - via your system's "Add/Remove Programs" feature, BEFORE installing the newer - version. - - Once installation is complete, you will find an ``easy_install.exe`` program in - your Python ``Scripts`` subdirectory. Be sure to add this directory to your - ``PATH`` environment variable, if you haven't already done so. - - - RPM-Based Systems - ================= - - Install setuptools using the provided source RPM. The included ``.spec`` file - assumes you are installing using the default ``python`` executable, and is not - specific to a particular Python version. The ``easy_install`` executable will - be installed to a system ``bin`` directory such as ``/usr/bin``. - - If you wish to install to a location other than the default Python - installation's default ``site-packages`` directory (and ``$prefix/bin`` for - scripts), please use the ``.egg``-based installation approach described in the - following section. - - - Cygwin, Mac OS X, Linux, Other - ============================== - - 1. Download the appropriate egg for your version of Python (e.g. - ``setuptools-0.6c9-py2.4.egg``). Do NOT rename it. - - 2. Run it as if it were a shell script, e.g. ``sh setuptools-0.6c9-py2.4.egg``. - Setuptools will install itself using the matching version of Python (e.g. - ``python2.4``), and will place the ``easy_install`` executable in the - default location for installing Python scripts (as determined by the - standard distutils configuration files, or by the Python installation). - - If you want to install setuptools to somewhere other than ``site-packages`` or - your default distutils installation locations for libraries and scripts, you - may include EasyInstall command-line options such as ``--prefix``, - ``--install-dir``, and so on, following the ``.egg`` filename on the same - command line. For example:: - - sh setuptools-0.6c9-py2.4.egg --prefix=~ - - You can use ``--help`` to get a full options list, but we recommend consulting - the `EasyInstall manual`_ for detailed instructions, especially `the section - on custom installation locations`_. - - .. _EasyInstall manual: http://peak.telecommunity.com/DevCenter/EasyInstall - .. _the section on custom installation locations: http://peak.telecommunity.com/DevCenter/EasyInstall#custom-installation-locations - - - Cygwin Note - ----------- - - If you are trying to install setuptools for the **Windows** version of Python - (as opposed to the Cygwin version that lives in ``/usr/bin``), you must make - sure that an appropriate executable (``python2.3``, ``python2.4``, or - ``python2.5``) is on your **Cygwin** ``PATH`` when invoking the egg. For - example, doing the following at a Cygwin bash prompt will install setuptools - for the **Windows** Python found at ``C:\\Python24``:: - - ln -s /cygdrive/c/Python24/python.exe python2.4 - PATH=.:$PATH sh setuptools-0.6c9-py2.4.egg - rm python2.4 - - - Downloads - ========= - - All setuptools downloads can be found at `the project's home page in the Python - Package Index`_. Scroll to the very bottom of the page to find the links. - - .. _the project's home page in the Python Package Index: http://pypi.python.org/pypi/setuptools - - In addition to the PyPI downloads, the development version of ``setuptools`` - is available from the `Python SVN sandbox`_, and in-development versions of the - `0.6 branch`_ are available as well. - - .. _0.6 branch: http://svn.python.org/projects/sandbox/branches/setuptools-0.6/#egg=setuptools-dev06 - - .. _Python SVN sandbox: http://svn.python.org/projects/sandbox/trunk/setuptools/#egg=setuptools-dev - - -------------------------------- - Using Setuptools and EasyInstall - -------------------------------- - - Here are some of the available manuals, tutorials, and other resources for - learning about Setuptools, Python Eggs, and EasyInstall: - - * `The EasyInstall user's guide and reference manual`_ - * `The setuptools Developer's Guide`_ - * `The pkg_resources API reference`_ - * `Package Compatibility Notes`_ (user-maintained) - * `The Internal Structure of Python Eggs`_ - - Questions, comments, and bug reports should be directed to the `distutils-sig - mailing list`_. If you have written (or know of) any tutorials, documentation, - plug-ins, or other resources for setuptools users, please let us know about - them there, so this reference list can be updated. If you have working, - *tested* patches to correct problems or add features, you may submit them to - the `setuptools bug tracker`_. - - .. _setuptools bug tracker: http://bugs.python.org/setuptools/ - .. _Package Compatibility Notes: http://peak.telecommunity.com/DevCenter/PackageNotes - .. _The Internal Structure of Python Eggs: http://peak.telecommunity.com/DevCenter/EggFormats - .. _The setuptools Developer's Guide: http://peak.telecommunity.com/DevCenter/setuptools - .. _The pkg_resources API reference: http://peak.telecommunity.com/DevCenter/PkgResources - .. _The EasyInstall user's guide and reference manual: http://peak.telecommunity.com/DevCenter/EasyInstall - .. _distutils-sig mailing list: http://mail.python.org/pipermail/distutils-sig/ - - - ------- - Credits - ------- - - * The original design for the ``.egg`` format and the ``pkg_resources`` API was - co-created by Phillip Eby and Bob Ippolito. Bob also implemented the first - version of ``pkg_resources``, and supplied the OS X operating system version - compatibility algorithm. - - * Ian Bicking implemented many early "creature comfort" features of - easy_install, including support for downloading via Sourceforge and - Subversion repositories. Ian's comments on the Web-SIG about WSGI - application deployment also inspired the concept of "entry points" in eggs, - and he has given talks at PyCon and elsewhere to inform and educate the - community about eggs and setuptools. - - * Jim Fulton contributed time and effort to build automated tests of various - aspects of ``easy_install``, and supplied the doctests for the command-line - ``.exe`` wrappers on Windows. - - * Phillip J. Eby is the principal author and maintainer of setuptools, and - first proposed the idea of an importable binary distribution format for - Python application plug-ins. - - * Significant parts of the implementation of setuptools were funded by the Open - Source Applications Foundation, to provide a plug-in infrastructure for the - Chandler PIM application. In addition, many OSAF staffers (such as Mike - "Code Bear" Taylor) contributed their time and stress as guinea pigs for the - use of eggs and setuptools, even before eggs were "cool". (Thanks, guys!) - - -Keywords: CPAN PyPI distutils eggs package management -Platform: UNKNOWN -Classifier: Development Status :: 3 - Alpha -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: Python Software Foundation License -Classifier: License :: OSI Approved :: Zope Public License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: System :: Archiving :: Packaging -Classifier: Topic :: System :: Systems Administration -Classifier: Topic :: Utilities diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/SETUPTOOLS-PKG-INFO2 --- a/Lib/packaging/tests/SETUPTOOLS-PKG-INFO2 Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,183 +0,0 @@ -Metadata-Version: 1.1 -Name: setuptools -Version: 0.6c9 -Summary: Download, build, install, upgrade, and uninstall Python packages -- easily! -Home-page: http://pypi.python.org/pypi/setuptools -Author: Phillip J. Eby -Author-email: distutils-sig@python.org -License: PSF or ZPL -Description: =============================== - Installing and Using Setuptools - =============================== - - .. contents:: **Table of Contents** - - - ------------------------- - Installation Instructions - ------------------------- - - Windows - ======= - - Install setuptools using the provided ``.exe`` installer. If you've previously - installed older versions of setuptools, please delete all ``setuptools*.egg`` - and ``setuptools.pth`` files from your system's ``site-packages`` directory - (and any other ``sys.path`` directories) FIRST. - - If you are upgrading a previous version of setuptools that was installed using - an ``.exe`` installer, please be sure to also *uninstall that older version* - via your system's "Add/Remove Programs" feature, BEFORE installing the newer - version. - - Once installation is complete, you will find an ``easy_install.exe`` program in - your Python ``Scripts`` subdirectory. Be sure to add this directory to your - ``PATH`` environment variable, if you haven't already done so. - - - RPM-Based Systems - ================= - - Install setuptools using the provided source RPM. The included ``.spec`` file - assumes you are installing using the default ``python`` executable, and is not - specific to a particular Python version. The ``easy_install`` executable will - be installed to a system ``bin`` directory such as ``/usr/bin``. - - If you wish to install to a location other than the default Python - installation's default ``site-packages`` directory (and ``$prefix/bin`` for - scripts), please use the ``.egg``-based installation approach described in the - following section. - - - Cygwin, Mac OS X, Linux, Other - ============================== - - 1. Download the appropriate egg for your version of Python (e.g. - ``setuptools-0.6c9-py2.4.egg``). Do NOT rename it. - - 2. Run it as if it were a shell script, e.g. ``sh setuptools-0.6c9-py2.4.egg``. - Setuptools will install itself using the matching version of Python (e.g. - ``python2.4``), and will place the ``easy_install`` executable in the - default location for installing Python scripts (as determined by the - standard distutils configuration files, or by the Python installation). - - If you want to install setuptools to somewhere other than ``site-packages`` or - your default distutils installation locations for libraries and scripts, you - may include EasyInstall command-line options such as ``--prefix``, - ``--install-dir``, and so on, following the ``.egg`` filename on the same - command line. For example:: - - sh setuptools-0.6c9-py2.4.egg --prefix=~ - - You can use ``--help`` to get a full options list, but we recommend consulting - the `EasyInstall manual`_ for detailed instructions, especially `the section - on custom installation locations`_. - - .. _EasyInstall manual: http://peak.telecommunity.com/DevCenter/EasyInstall - .. _the section on custom installation locations: http://peak.telecommunity.com/DevCenter/EasyInstall#custom-installation-locations - - - Cygwin Note - ----------- - - If you are trying to install setuptools for the **Windows** version of Python - (as opposed to the Cygwin version that lives in ``/usr/bin``), you must make - sure that an appropriate executable (``python2.3``, ``python2.4``, or - ``python2.5``) is on your **Cygwin** ``PATH`` when invoking the egg. For - example, doing the following at a Cygwin bash prompt will install setuptools - for the **Windows** Python found at ``C:\\Python24``:: - - ln -s /cygdrive/c/Python24/python.exe python2.4 - PATH=.:$PATH sh setuptools-0.6c9-py2.4.egg - rm python2.4 - - - Downloads - ========= - - All setuptools downloads can be found at `the project's home page in the Python - Package Index`_. Scroll to the very bottom of the page to find the links. - - .. _the project's home page in the Python Package Index: http://pypi.python.org/pypi/setuptools - - In addition to the PyPI downloads, the development version of ``setuptools`` - is available from the `Python SVN sandbox`_, and in-development versions of the - `0.6 branch`_ are available as well. - - .. _0.6 branch: http://svn.python.org/projects/sandbox/branches/setuptools-0.6/#egg=setuptools-dev06 - - .. _Python SVN sandbox: http://svn.python.org/projects/sandbox/trunk/setuptools/#egg=setuptools-dev - - -------------------------------- - Using Setuptools and EasyInstall - -------------------------------- - - Here are some of the available manuals, tutorials, and other resources for - learning about Setuptools, Python Eggs, and EasyInstall: - - * `The EasyInstall user's guide and reference manual`_ - * `The setuptools Developer's Guide`_ - * `The pkg_resources API reference`_ - * `Package Compatibility Notes`_ (user-maintained) - * `The Internal Structure of Python Eggs`_ - - Questions, comments, and bug reports should be directed to the `distutils-sig - mailing list`_. If you have written (or know of) any tutorials, documentation, - plug-ins, or other resources for setuptools users, please let us know about - them there, so this reference list can be updated. If you have working, - *tested* patches to correct problems or add features, you may submit them to - the `setuptools bug tracker`_. - - .. _setuptools bug tracker: http://bugs.python.org/setuptools/ - .. _Package Compatibility Notes: http://peak.telecommunity.com/DevCenter/PackageNotes - .. _The Internal Structure of Python Eggs: http://peak.telecommunity.com/DevCenter/EggFormats - .. _The setuptools Developer's Guide: http://peak.telecommunity.com/DevCenter/setuptools - .. _The pkg_resources API reference: http://peak.telecommunity.com/DevCenter/PkgResources - .. _The EasyInstall user's guide and reference manual: http://peak.telecommunity.com/DevCenter/EasyInstall - .. _distutils-sig mailing list: http://mail.python.org/pipermail/distutils-sig/ - - - ------- - Credits - ------- - - * The original design for the ``.egg`` format and the ``pkg_resources`` API was - co-created by Phillip Eby and Bob Ippolito. Bob also implemented the first - version of ``pkg_resources``, and supplied the OS X operating system version - compatibility algorithm. - - * Ian Bicking implemented many early "creature comfort" features of - easy_install, including support for downloading via Sourceforge and - Subversion repositories. Ian's comments on the Web-SIG about WSGI - application deployment also inspired the concept of "entry points" in eggs, - and he has given talks at PyCon and elsewhere to inform and educate the - community about eggs and setuptools. - - * Jim Fulton contributed time and effort to build automated tests of various - aspects of ``easy_install``, and supplied the doctests for the command-line - ``.exe`` wrappers on Windows. - - * Phillip J. Eby is the principal author and maintainer of setuptools, and - first proposed the idea of an importable binary distribution format for - Python application plug-ins. - - * Significant parts of the implementation of setuptools were funded by the Open - Source Applications Foundation, to provide a plug-in infrastructure for the - Chandler PIM application. In addition, many OSAF staffers (such as Mike - "Code Bear" Taylor) contributed their time and stress as guinea pigs for the - use of eggs and setuptools, even before eggs were "cool". (Thanks, guys!) - - -Keywords: CPAN PyPI distutils eggs package management -Platform: UNKNOWN -Classifier: Development Status :: 3 - Alpha -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: Python Software Foundation License -Classifier: License :: OSI Approved :: Zope Public License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: System :: Archiving :: Packaging -Classifier: Topic :: System :: Systems Administration -Classifier: Topic :: Utilities -Requires: Foo diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/__init__.py --- a/Lib/packaging/tests/__init__.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -"""Test suite for packaging. - -This test suite consists of a collection of test modules in the -packaging.tests package. Each test module has a name starting with -'test' and contains a function test_suite(). The function is expected -to return an initialized unittest.TestSuite instance. - -Utility code is included in packaging.tests.support. -""" - -# Put this text back for the backport -#Always import unittest from this module, it will be the right version -#(standard library unittest for 3.2 and higher, third-party unittest2 -#elease for older versions). - -import os -import sys -import unittest -from test.support import TESTFN - -# XXX move helpers to support, add tests for them, remove things that -# duplicate test.support (or keep them for the backport; needs thinking) - -here = os.path.dirname(__file__) or os.curdir -verbose = 1 - -def test_suite(): - suite = unittest.TestSuite() - for fn in os.listdir(here): - if fn.startswith("test") and fn.endswith(".py"): - modname = "packaging.tests." + fn[:-3] - __import__(modname) - module = sys.modules[modname] - suite.addTest(module.test_suite()) - return suite - - -class Error(Exception): - """Base class for regression test exceptions.""" - - -class TestFailed(Error): - """Test failed.""" - - -class BasicTestRunner: - def run(self, test): - result = unittest.TestResult() - test(result) - return result - - -def _run_suite(suite, verbose_=1): - """Run tests from a unittest.TestSuite-derived class.""" - global verbose - verbose = verbose_ - if verbose_: - runner = unittest.TextTestRunner(sys.stdout, verbosity=2) - else: - runner = BasicTestRunner() - - result = runner.run(suite) - if not result.wasSuccessful(): - if len(result.errors) == 1 and not result.failures: - err = result.errors[0][1] - elif len(result.failures) == 1 and not result.errors: - err = result.failures[0][1] - else: - err = "errors occurred; run in verbose mode for details" - raise TestFailed(err) - - -def run_unittest(classes, verbose_=1): - """Run tests from unittest.TestCase-derived classes. - - Originally extracted from stdlib test.test_support and modified to - support unittest2. - """ - valid_types = (unittest.TestSuite, unittest.TestCase) - suite = unittest.TestSuite() - for cls in classes: - if isinstance(cls, str): - if cls in sys.modules: - suite.addTest(unittest.findTestCases(sys.modules[cls])) - else: - raise ValueError("str arguments must be keys in sys.modules") - elif isinstance(cls, valid_types): - suite.addTest(cls) - else: - suite.addTest(unittest.makeSuite(cls)) - _run_suite(suite, verbose_) - - -def reap_children(): - """Use this function at the end of test_main() whenever sub-processes - are started. This will help ensure that no extra children (zombies) - stick around to hog resources and create problems when looking - for refleaks. - - Extracted from stdlib test.support. - """ - - # Reap all our dead child processes so we don't leave zombies around. - # These hog resources and might be causing some of the buildbots to die. - if hasattr(os, 'waitpid'): - any_process = -1 - while True: - try: - # This will raise an exception on Windows. That's ok. - pid, status = os.waitpid(any_process, os.WNOHANG) - if pid == 0: - break - except: - break - - -def captured_stdout(func, *args, **kw): - import io - orig_stdout = getattr(sys, 'stdout') - setattr(sys, 'stdout', io.StringIO()) - try: - res = func(*args, **kw) - sys.stdout.seek(0) - return res, sys.stdout.read() - finally: - setattr(sys, 'stdout', orig_stdout) - - -def unload(name): - try: - del sys.modules[name] - except KeyError: - pass diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/__main__.py --- a/Lib/packaging/tests/__main__.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -"""Packaging test suite runner.""" - -# Ripped from importlib tests, thanks Brett! - -import os -import sys -import unittest -from test.support import run_unittest, reap_children - - -def test_main(): - start_dir = os.path.dirname(__file__) - top_dir = os.path.dirname(os.path.dirname(start_dir)) - test_loader = unittest.TestLoader() - run_unittest(test_loader.discover(start_dir, top_level_dir=top_dir)) - reap_children() - - -if __name__ == '__main__': - test_main() diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/babar-0.1.dist-info/METADATA --- a/Lib/packaging/tests/fake_dists/babar-0.1.dist-info/METADATA Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -Metadata-version: 1.2 -Name: babar -Version: 0.1 -Author: FELD Boris \ No newline at end of file diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/babar-0.1.dist-info/RESOURCES --- a/Lib/packaging/tests/fake_dists/babar-0.1.dist-info/RESOURCES Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -babar.png,babar.png -babar.cfg,babar.cfg \ No newline at end of file diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/babar.cfg --- a/Lib/packaging/tests/fake_dists/babar.cfg Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Config \ No newline at end of file diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/bacon-0.1.egg-info/PKG-INFO --- a/Lib/packaging/tests/fake_dists/bacon-0.1.egg-info/PKG-INFO Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Metadata-Version: 1.2 -Name: bacon -Version: 0.1 -Provides-Dist: truffles (2.0) -Provides-Dist: bacon (0.1) -Obsoletes-Dist: truffles (>=0.9,<=1.5) diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/banana-0.4.egg/EGG-INFO/PKG-INFO --- a/Lib/packaging/tests/fake_dists/banana-0.4.egg/EGG-INFO/PKG-INFO Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -Metadata-Version: 1.0 -Name: banana -Version: 0.4 -Summary: A yellow fruit -Home-page: http://en.wikipedia.org/wiki/Banana -Author: Josip Djolonga -Author-email: foo@nbar.com -License: BSD -Description: A fruit -Keywords: foo bar -Platform: UNKNOWN -Classifier: Development Status :: 4 - Beta -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: Science/Research -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: OS Independent -Classifier: Programming Language :: Python -Classifier: Topic :: Scientific/Engineering :: GIS diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/banana-0.4.egg/EGG-INFO/dependency_links.txt --- a/Lib/packaging/tests/fake_dists/banana-0.4.egg/EGG-INFO/dependency_links.txt Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ - diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/banana-0.4.egg/EGG-INFO/entry_points.txt --- a/Lib/packaging/tests/fake_dists/banana-0.4.egg/EGG-INFO/entry_points.txt Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - - # -*- Entry points: -*- - \ No newline at end of file diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/banana-0.4.egg/EGG-INFO/not-zip-safe --- a/Lib/packaging/tests/fake_dists/banana-0.4.egg/EGG-INFO/not-zip-safe Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ - diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/banana-0.4.egg/EGG-INFO/requires.txt --- a/Lib/packaging/tests/fake_dists/banana-0.4.egg/EGG-INFO/requires.txt Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -# this should be ignored - -strawberry >=0.5 - -[section ignored] -foo ==0.5 diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/cheese-2.0.2.egg-info --- a/Lib/packaging/tests/fake_dists/cheese-2.0.2.egg-info Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -Metadata-Version: 1.2 -Name: cheese -Version: 2.0.2 -Provides-Dist: truffles (1.0.2) -Obsoletes-Dist: truffles (!=1.2,<=2.0) diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/choxie-2.0.0.9.dist-info/METADATA --- a/Lib/packaging/tests/fake_dists/choxie-2.0.0.9.dist-info/METADATA Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,9 +0,0 @@ -Metadata-Version: 1.2 -Name: choxie -Version: 2.0.0.9 -Summary: Chocolate with a kick! -Requires-Dist: towel-stuff (0.1) -Requires-Dist: nut -Provides-Dist: truffles (1.0) -Obsoletes-Dist: truffles (<=0.8,>=0.5) -Obsoletes-Dist: truffles (<=0.9,>=0.6) diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/choxie-2.0.0.9/choxie/__init__.py --- a/Lib/packaging/tests/fake_dists/choxie-2.0.0.9/choxie/__init__.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -# -*- coding: utf-8 -*- diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/choxie-2.0.0.9/choxie/chocolate.py --- a/Lib/packaging/tests/fake_dists/choxie-2.0.0.9/choxie/chocolate.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -from towel_stuff import Towel - -class Chocolate(object): - """A piece of chocolate.""" - - def wrap_with_towel(self): - towel = Towel() - towel.wrap(self) - return towel diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/choxie-2.0.0.9/truffles.py --- a/Lib/packaging/tests/fake_dists/choxie-2.0.0.9/truffles.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -# -*- coding: utf-8 -*- -from choxie.chocolate import Chocolate - -class Truffle(Chocolate): - """A truffle.""" diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/coconuts-aster-10.3.egg-info/PKG-INFO --- a/Lib/packaging/tests/fake_dists/coconuts-aster-10.3.egg-info/PKG-INFO Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -Metadata-Version: 1.2 -Name: coconuts-aster -Version: 10.3 -Provides-Dist: strawberry (0.6) -Provides-Dist: banana (0.4) diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/grammar-1.0a4.dist-info/METADATA --- a/Lib/packaging/tests/fake_dists/grammar-1.0a4.dist-info/METADATA Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -Metadata-Version: 1.2 -Name: grammar -Version: 1.0a4 -Requires-Dist: truffles (>=1.2) -Author: Sherlock Holmes diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/grammar-1.0a4/grammar/__init__.py --- a/Lib/packaging/tests/fake_dists/grammar-1.0a4/grammar/__init__.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -# -*- coding: utf-8 -*- diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/grammar-1.0a4/grammar/utils.py --- a/Lib/packaging/tests/fake_dists/grammar-1.0a4/grammar/utils.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ -# -*- coding: utf-8 -*- -from random import randint - -def is_valid_grammar(sentence): - if randint(0, 10) < 2: - return False - else: - return True diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/nut-funkyversion.egg-info --- a/Lib/packaging/tests/fake_dists/nut-funkyversion.egg-info Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -Metadata-Version: 1.2 -Name: nut -Version: funkyversion diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/strawberry-0.6.egg Binary file Lib/packaging/tests/fake_dists/strawberry-0.6.egg has changed diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/towel_stuff-0.1.dist-info/METADATA --- a/Lib/packaging/tests/fake_dists/towel_stuff-0.1.dist-info/METADATA Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -Metadata-Version: 1.2 -Name: towel-stuff -Version: 0.1 -Provides-Dist: truffles (1.1.2) -Provides-Dist: towel-stuff (0.1) -Obsoletes-Dist: truffles (!=0.8,<1.0) -Requires-Dist: bacon (<=0.2) diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/towel_stuff-0.1/towel_stuff/__init__.py --- a/Lib/packaging/tests/fake_dists/towel_stuff-0.1/towel_stuff/__init__.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- - -class Towel(object): - """A towel, that one should never be without.""" - - def __init__(self, color='tie-dye'): - self.color = color - self.wrapped_obj = None - - def wrap(self, obj): - """Wrap an object up in our towel.""" - self.wrapped_obj = obj - - def unwrap(self): - """Unwrap whatever is in our towel and return whatever it is.""" - obj = self.wrapped_obj - self.wrapped_obj = None - return obj diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fake_dists/truffles-5.0.egg-info --- a/Lib/packaging/tests/fake_dists/truffles-5.0.egg-info Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -Metadata-Version: 1.2 -Name: truffles -Version: 5.0 diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/fixer/fix_idioms.py --- a/Lib/packaging/tests/fixer/fix_idioms.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -"""Adjust some old Python 2 idioms to their modern counterparts. - -* Change some type comparisons to isinstance() calls: - type(x) == T -> isinstance(x, T) - type(x) is T -> isinstance(x, T) - type(x) != T -> not isinstance(x, T) - type(x) is not T -> not isinstance(x, T) - -* Change "while 1:" into "while True:". - -* Change both - - v = list(EXPR) - v.sort() - foo(v) - -and the more general - - v = EXPR - v.sort() - foo(v) - -into - - v = sorted(EXPR) - foo(v) -""" -# Author: Jacques Frechet, Collin Winter - -# Local imports -from lib2to3 import fixer_base -from lib2to3.fixer_util import Call, Comma, Name, Node, syms - -CMP = "(n='!=' | '==' | 'is' | n=comp_op< 'is' 'not' >)" -TYPE = "power< 'type' trailer< '(' x=any ')' > >" - -class FixIdioms(fixer_base.BaseFix): - - explicit = False # The user must ask for this fixer - - PATTERN = r""" - isinstance=comparison< %s %s T=any > - | - isinstance=comparison< T=any %s %s > - | - while_stmt< 'while' while='1' ':' any+ > - | - sorted=any< - any* - simple_stmt< - expr_stmt< id1=any '=' - power< list='list' trailer< '(' (not arglist) any ')' > > - > - '\n' - > - sort= - simple_stmt< - power< id2=any - trailer< '.' 'sort' > trailer< '(' ')' > - > - '\n' - > - next=any* - > - | - sorted=any< - any* - simple_stmt< expr_stmt< id1=any '=' expr=any > '\n' > - sort= - simple_stmt< - power< id2=any - trailer< '.' 'sort' > trailer< '(' ')' > - > - '\n' - > - next=any* - > - """ % (TYPE, CMP, CMP, TYPE) - - def match(self, node): - r = super(FixIdioms, self).match(node) - # If we've matched one of the sort/sorted subpatterns above, we - # want to reject matches where the initial assignment and the - # subsequent .sort() call involve different identifiers. - if r and "sorted" in r: - if r["id1"] == r["id2"]: - return r - return None - return r - - def transform(self, node, results): - if "isinstance" in results: - return self.transform_isinstance(node, results) - elif "while" in results: - return self.transform_while(node, results) - elif "sorted" in results: - return self.transform_sort(node, results) - else: - raise RuntimeError("Invalid match") - - def transform_isinstance(self, node, results): - x = results["x"].clone() # The thing inside of type() - T = results["T"].clone() # The type being compared against - x.prefix = "" - T.prefix = " " - test = Call(Name("isinstance"), [x, Comma(), T]) - if "n" in results: - test.prefix = " " - test = Node(syms.not_test, [Name("not"), test]) - test.prefix = node.prefix - return test - - def transform_while(self, node, results): - one = results["while"] - one.replace(Name("True", prefix=one.prefix)) - - def transform_sort(self, node, results): - sort_stmt = results["sort"] - next_stmt = results["next"] - list_call = results.get("list") - simple_expr = results.get("expr") - - if list_call: - list_call.replace(Name("sorted", prefix=list_call.prefix)) - elif simple_expr: - new = simple_expr.clone() - new.prefix = "" - simple_expr.replace(Call(Name("sorted"), [new], - prefix=simple_expr.prefix)) - else: - raise RuntimeError("should not have reached here") - sort_stmt.remove() - if next_stmt: - next_stmt[0].prefix = sort_stmt._prefix diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypi_server.py --- a/Lib/packaging/tests/pypi_server.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,446 +0,0 @@ -"""Mock PyPI Server implementation, to use in tests. - -This module also provides a simple test case to extend if you need to use -the PyPIServer all along your test case. Be sure to read the documentation -before any use. - -XXX TODO: - -The mock server can handle simple HTTP request (to simulate a simple index) or -XMLRPC requests, over HTTP. Both does not have the same intergface to deal -with, and I think it's a pain. - -A good idea could be to re-think a bit the way dstributions are handled in the -mock server. As it should return malformed HTML pages, we need to keep the -static behavior. - -I think of something like that: - - >>> server = PyPIMockServer() - >>> server.startHTTP() - >>> server.startXMLRPC() - -Then, the server must have only one port to rely on, eg. - - >>> server.fulladress() - "http://ip:port/" - -It could be simple to have one HTTP server, relaying the requests to the two -implementations (static HTTP and XMLRPC over HTTP). -""" - -import os -import queue -import select -import threading -import socketserver -from functools import wraps -from http.server import HTTPServer, SimpleHTTPRequestHandler -from xmlrpc.server import SimpleXMLRPCServer - -from packaging.tests import unittest - -PYPI_DEFAULT_STATIC_PATH = os.path.join( - os.path.dirname(os.path.abspath(__file__)), 'pypiserver') - - -def use_xmlrpc_server(*server_args, **server_kwargs): - server_kwargs['serve_xmlrpc'] = True - return use_pypi_server(*server_args, **server_kwargs) - - -def use_http_server(*server_args, **server_kwargs): - server_kwargs['serve_xmlrpc'] = False - return use_pypi_server(*server_args, **server_kwargs) - - -def use_pypi_server(*server_args, **server_kwargs): - """Decorator to make use of the PyPIServer for test methods, - just when needed, and not for the entire duration of the testcase. - """ - def wrapper(func): - @wraps(func) - def wrapped(*args, **kwargs): - server = PyPIServer(*server_args, **server_kwargs) - server.start() - try: - func(server=server, *args, **kwargs) - finally: - server.stop() - return wrapped - return wrapper - - -class PyPIServerTestCase(unittest.TestCase): - - def setUp(self): - super(PyPIServerTestCase, self).setUp() - self.pypi = PyPIServer() - self.pypi.start() - self.addCleanup(self.pypi.stop) - - -class PyPIServer(threading.Thread): - """PyPI Mocked server. - Provides a mocked version of the PyPI API's, to ease tests. - - Support serving static content and serving previously given text. - """ - - def __init__(self, test_static_path=None, - static_filesystem_paths=["default"], - static_uri_paths=["simple", "packages"], serve_xmlrpc=False): - """Initialize the server. - - Default behavior is to start the HTTP server. You can either start the - xmlrpc server by setting xmlrpc to True. Caution: Only one server will - be started. - - static_uri_paths and static_base_path are parameters used to provides - respectively the http_paths to serve statically, and where to find the - matching files on the filesystem. - """ - # we want to launch the server in a new dedicated thread, to not freeze - # tests. - threading.Thread.__init__(self) - self._run = True - self._serve_xmlrpc = serve_xmlrpc - - #TODO allow to serve XMLRPC and HTTP static files at the same time. - if not self._serve_xmlrpc: - self.server = HTTPServer(('127.0.0.1', 0), PyPIRequestHandler) - self.server.RequestHandlerClass.pypi_server = self - - self.request_queue = queue.Queue() - self._requests = [] - self.default_response_status = 404 - self.default_response_headers = [('Content-type', 'text/plain')] - self.default_response_data = "The page does not exists" - - # initialize static paths / filesystems - self.static_uri_paths = static_uri_paths - - # append the static paths defined locally - if test_static_path is not None: - static_filesystem_paths.append(test_static_path) - self.static_filesystem_paths = [ - PYPI_DEFAULT_STATIC_PATH + "/" + path - for path in static_filesystem_paths] - else: - # XMLRPC server - self.server = PyPIXMLRPCServer(('127.0.0.1', 0)) - self.xmlrpc = XMLRPCMockIndex() - # register the xmlrpc methods - self.server.register_introspection_functions() - self.server.register_instance(self.xmlrpc) - - self.address = ('127.0.0.1', self.server.server_port) - # to not have unwanted outputs. - self.server.RequestHandlerClass.log_request = lambda *_: None - - def run(self): - # loop because we can't stop it otherwise, for python < 2.6 - while self._run: - r, w, e = select.select([self.server], [], [], 0.5) - if r: - self.server.handle_request() - - def stop(self): - """self shutdown is not supported for python < 2.6""" - self._run = False - if self.is_alive(): - self.join() - self.server.server_close() - - def get_next_response(self): - return (self.default_response_status, - self.default_response_headers, - self.default_response_data) - - @property - def requests(self): - """Use this property to get all requests that have been made - to the server - """ - while True: - try: - self._requests.append(self.request_queue.get_nowait()) - except queue.Empty: - break - return self._requests - - @property - def full_address(self): - return "http://%s:%s" % self.address - - -class PyPIRequestHandler(SimpleHTTPRequestHandler): - # we need to access the pypi server while serving the content - pypi_server = None - - def serve_request(self): - """Serve the content. - - Also record the requests to be accessed later. If trying to access an - url matching a static uri, serve static content, otherwise serve - what is provided by the `get_next_response` method. - - If nothing is defined there, return a 404 header. - """ - # record the request. Read the input only on PUT or POST requests - if self.command in ("PUT", "POST"): - if 'content-length' in self.headers: - request_data = self.rfile.read( - int(self.headers['content-length'])) - else: - request_data = self.rfile.read() - - elif self.command in ("GET", "DELETE"): - request_data = '' - - self.pypi_server.request_queue.put((self, request_data)) - - # serve the content from local disc if we request an URL beginning - # by a pattern defined in `static_paths` - url_parts = self.path.split("/") - if (len(url_parts) > 1 and - url_parts[1] in self.pypi_server.static_uri_paths): - data = None - # always take the last first. - fs_paths = [] - fs_paths.extend(self.pypi_server.static_filesystem_paths) - fs_paths.reverse() - relative_path = self.path - for fs_path in fs_paths: - try: - if self.path.endswith("/"): - relative_path += "index.html" - - if relative_path.endswith('.tar.gz'): - with open(fs_path + relative_path, 'br') as file: - data = file.read() - headers = [('Content-type', 'application/x-gtar')] - else: - with open(fs_path + relative_path) as file: - data = file.read().encode() - headers = [('Content-type', 'text/html')] - - headers.append(('Content-Length', len(data))) - self.make_response(data, headers=headers) - - except IOError: - pass - - if data is None: - self.make_response("Not found", 404) - - # otherwise serve the content from get_next_response - else: - # send back a response - status, headers, data = self.pypi_server.get_next_response() - self.make_response(data, status, headers) - - do_POST = do_GET = do_DELETE = do_PUT = serve_request - - def make_response(self, data, status=200, - headers=[('Content-type', 'text/html')]): - """Send the response to the HTTP client""" - if not isinstance(status, int): - try: - status = int(status) - except ValueError: - # we probably got something like YYY Codename. - # Just get the first 3 digits - status = int(status[:3]) - - self.send_response(status) - for header, value in headers: - self.send_header(header, value) - self.end_headers() - - if type(data) is str: - data = data.encode() - - self.wfile.write(data) - - -class PyPIXMLRPCServer(SimpleXMLRPCServer): - def server_bind(self): - """Override server_bind to store the server name.""" - socketserver.TCPServer.server_bind(self) - host, port = self.socket.getsockname()[:2] - self.server_port = port - - -class MockDist: - """Fake distribution, used in the Mock PyPI Server""" - - def __init__(self, name, version="1.0", hidden=False, url="http://url/", - type="sdist", filename="", size=10000, - digest="123456", downloads=7, has_sig=False, - python_version="source", comment="comment", - author="John Doe", author_email="john@doe.name", - maintainer="Main Tayner", maintainer_email="maintainer_mail", - project_url="http://project_url/", homepage="http://homepage/", - keywords="", platform="UNKNOWN", classifiers=[], licence="", - description="Description", summary="Summary", stable_version="", - ordering="", documentation_id="", code_kwalitee_id="", - installability_id="", obsoletes=[], obsoletes_dist=[], - provides=[], provides_dist=[], requires=[], requires_dist=[], - requires_external=[], requires_python=""): - - # basic fields - self.name = name - self.version = version - self.hidden = hidden - - # URL infos - self.url = url - self.digest = digest - self.downloads = downloads - self.has_sig = has_sig - self.python_version = python_version - self.comment = comment - self.type = type - - # metadata - self.author = author - self.author_email = author_email - self.maintainer = maintainer - self.maintainer_email = maintainer_email - self.project_url = project_url - self.homepage = homepage - self.keywords = keywords - self.platform = platform - self.classifiers = classifiers - self.licence = licence - self.description = description - self.summary = summary - self.stable_version = stable_version - self.ordering = ordering - self.cheesecake_documentation_id = documentation_id - self.cheesecake_code_kwalitee_id = code_kwalitee_id - self.cheesecake_installability_id = installability_id - - self.obsoletes = obsoletes - self.obsoletes_dist = obsoletes_dist - self.provides = provides - self.provides_dist = provides_dist - self.requires = requires - self.requires_dist = requires_dist - self.requires_external = requires_external - self.requires_python = requires_python - - def url_infos(self): - return { - 'url': self.url, - 'packagetype': self.type, - 'filename': 'filename.tar.gz', - 'size': '6000', - 'md5_digest': self.digest, - 'downloads': self.downloads, - 'has_sig': self.has_sig, - 'python_version': self.python_version, - 'comment_text': self.comment, - } - - def metadata(self): - return { - 'maintainer': self.maintainer, - 'project_url': [self.project_url], - 'maintainer_email': self.maintainer_email, - 'cheesecake_code_kwalitee_id': self.cheesecake_code_kwalitee_id, - 'keywords': self.keywords, - 'obsoletes_dist': self.obsoletes_dist, - 'requires_external': self.requires_external, - 'author': self.author, - 'author_email': self.author_email, - 'download_url': self.url, - 'platform': self.platform, - 'version': self.version, - 'obsoletes': self.obsoletes, - 'provides': self.provides, - 'cheesecake_documentation_id': self.cheesecake_documentation_id, - '_pypi_hidden': self.hidden, - 'description': self.description, - '_pypi_ordering': 19, - 'requires_dist': self.requires_dist, - 'requires_python': self.requires_python, - 'classifiers': [], - 'name': self.name, - 'licence': self.licence, - 'summary': self.summary, - 'home_page': self.homepage, - 'stable_version': self.stable_version, - 'provides_dist': self.provides_dist or "%s (%s)" % (self.name, - self.version), - 'requires': self.requires, - 'cheesecake_installability_id': self.cheesecake_installability_id, - } - - def search_result(self): - return { - '_pypi_ordering': 0, - 'version': self.version, - 'name': self.name, - 'summary': self.summary, - } - - -class XMLRPCMockIndex: - """Mock XMLRPC server""" - - def __init__(self, dists=[]): - self._dists = dists - self._search_result = [] - - def add_distributions(self, dists): - for dist in dists: - self._dists.append(MockDist(**dist)) - - def set_distributions(self, dists): - self._dists = [] - self.add_distributions(dists) - - def set_search_result(self, result): - """set a predefined search result""" - self._search_result = result - - def _get_search_results(self): - results = [] - for name in self._search_result: - found_dist = [d for d in self._dists if d.name == name] - if found_dist: - results.append(found_dist[0]) - else: - dist = MockDist(name) - results.append(dist) - self._dists.append(dist) - return [r.search_result() for r in results] - - def list_packages(self): - return [d.name for d in self._dists] - - def package_releases(self, package_name, show_hidden=False): - if show_hidden: - # return all - return [d.version for d in self._dists if d.name == package_name] - else: - # return only un-hidden - return [d.version for d in self._dists if d.name == package_name - and not d.hidden] - - def release_urls(self, package_name, version): - return [d.url_infos() for d in self._dists - if d.name == package_name and d.version == version] - - def release_data(self, package_name, version): - release = [d for d in self._dists - if d.name == package_name and d.version == version] - if release: - return release[0].metadata() - else: - return {} - - def search(self, spec, operator="and"): - return self._get_search_results() diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypi_test_server.py --- a/Lib/packaging/tests/pypi_test_server.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -"""Test PyPI Server implementation at testpypi.python.org, to use in tests. - -This is a drop-in replacement for the mock pypi server for testing against a -real pypi server hosted by python.org especially for testing against. -""" - -import unittest - -PYPI_DEFAULT_STATIC_PATH = None - - -def use_xmlrpc_server(*server_args, **server_kwargs): - server_kwargs['serve_xmlrpc'] = True - return use_pypi_server(*server_args, **server_kwargs) - - -def use_http_server(*server_args, **server_kwargs): - server_kwargs['serve_xmlrpc'] = False - return use_pypi_server(*server_args, **server_kwargs) - - -def use_pypi_server(*server_args, **server_kwargs): - """Decorator to make use of the PyPIServer for test methods, - just when needed, and not for the entire duration of the testcase. - """ - def wrapper(func): - def wrapped(*args, **kwargs): - server = PyPIServer(*server_args, **server_kwargs) - func(server=server, *args, **kwargs) - return wrapped - return wrapper - - -class PyPIServerTestCase(unittest.TestCase): - - def setUp(self): - super(PyPIServerTestCase, self).setUp() - self.pypi = PyPIServer() - self.pypi.start() - self.addCleanup(self.pypi.stop) - - -class PyPIServer: - """Shim to access testpypi.python.org, for testing a real server.""" - - def __init__(self, test_static_path=None, - static_filesystem_paths=["default"], - static_uri_paths=["simple"], serve_xmlrpc=False): - self.address = ('testpypi.python.org', '80') - - def start(self): - pass - - def stop(self): - pass - - @property - def full_address(self): - return "http://%s:%s" % self.address diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/downloads_with_md5/packages/source/f/foobar/foobar-0.1.tar.gz Binary file Lib/packaging/tests/pypiserver/downloads_with_md5/packages/source/f/foobar/foobar-0.1.tar.gz has changed diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/downloads_with_md5/simple/badmd5/index.html --- a/Lib/packaging/tests/pypiserver/downloads_with_md5/simple/badmd5/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - -badmd5-0.1.tar.gz
- diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/downloads_with_md5/simple/foobar/index.html --- a/Lib/packaging/tests/pypiserver/downloads_with_md5/simple/foobar/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - -foobar-0.1.tar.gz
- diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/downloads_with_md5/simple/index.html --- a/Lib/packaging/tests/pypiserver/downloads_with_md5/simple/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2 +0,0 @@ -foobar/ -badmd5/ diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/foo_bar_baz/simple/bar/index.html --- a/Lib/packaging/tests/pypiserver/foo_bar_baz/simple/bar/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Links for bar

Links for bar

-bar-1.0.tar.gz
-bar-1.0.1.tar.gz
-bar-2.0.tar.gz
-bar-2.0.1.tar.gz
- diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/foo_bar_baz/simple/baz/index.html --- a/Lib/packaging/tests/pypiserver/foo_bar_baz/simple/baz/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Links for baz

Links for baz

-baz-1.0.tar.gz
-baz-1.0.1.tar.gz
-baz-2.0.tar.gz
-baz-2.0.1.tar.gz
- diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/foo_bar_baz/simple/foo/index.html --- a/Lib/packaging/tests/pypiserver/foo_bar_baz/simple/foo/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Links for foo

Links for foo

-foo-1.0.tar.gz
-foo-1.0.1.tar.gz
-foo-2.0.tar.gz
-foo-2.0.1.tar.gz
- diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/foo_bar_baz/simple/index.html --- a/Lib/packaging/tests/pypiserver/foo_bar_baz/simple/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -foo/ -bar/ -baz/ diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/project_list/simple/index.html --- a/Lib/packaging/tests/pypiserver/project_list/simple/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -FooBar-bar -Foobar-baz -Baz-FooBar -Baz -Foo diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/test_found_links/simple/foobar/index.html --- a/Lib/packaging/tests/pypiserver/test_found_links/simple/foobar/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ -Links for Foobar

Links for Foobar

-Foobar-1.0.tar.gz
-Foobar-1.0.1.tar.gz
-Foobar-2.0.tar.gz
-Foobar-2.0.1.tar.gz
- diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/test_found_links/simple/index.html --- a/Lib/packaging/tests/pypiserver/test_found_links/simple/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -foobar/ diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/test_pypi_server/external/index.html --- a/Lib/packaging/tests/pypiserver/test_pypi_server/external/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -index.html from external server diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/test_pypi_server/simple/index.html --- a/Lib/packaging/tests/pypiserver/test_pypi_server/simple/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -Yeah diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/with_externals/external/external.html --- a/Lib/packaging/tests/pypiserver/with_externals/external/external.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - -bad old link - diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/with_externals/simple/foobar/index.html --- a/Lib/packaging/tests/pypiserver/with_externals/simple/foobar/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ - -foobar-0.1.tar.gz
-external homepage
- diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/with_externals/simple/index.html --- a/Lib/packaging/tests/pypiserver/with_externals/simple/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -foobar/ diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/with_norel_links/external/homepage.html --- a/Lib/packaging/tests/pypiserver/with_norel_links/external/homepage.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ - - -

a rel=homepage HTML page

-foobar 2.0 - - - diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/with_norel_links/external/nonrel.html --- a/Lib/packaging/tests/pypiserver/with_norel_links/external/nonrel.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -A page linked without rel="download" or rel="homepage" link. diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/with_norel_links/simple/foobar/index.html --- a/Lib/packaging/tests/pypiserver/with_norel_links/simple/foobar/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ - -foobar-0.1.tar.gz
-external homepage
-unrelated link
-unrelated download
- diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/with_norel_links/simple/index.html --- a/Lib/packaging/tests/pypiserver/with_norel_links/simple/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -foobar/ diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/with_real_externals/simple/foobar/index.html --- a/Lib/packaging/tests/pypiserver/with_real_externals/simple/foobar/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ - -foobar-0.1.tar.gz
-external homepage
- diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/pypiserver/with_real_externals/simple/index.html --- a/Lib/packaging/tests/pypiserver/with_real_externals/simple/index.html Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -foobar/ diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/support.py --- a/Lib/packaging/tests/support.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,278 +0,0 @@ -"""Support code for packaging test cases. - -A few helper classes are provided: LoggingCatcher, TempdirManager and -EnvironRestorer. They are written to be used as mixins:: - - from packaging.tests import unittest - from packaging.tests.support import LoggingCatcher - - class SomeTestCase(LoggingCatcher, unittest.TestCase): - -If you need to define a setUp method on your test class, you have to -call the mixin class' setUp method or it won't work (same thing for -tearDown): - - def setUp(self): - super(SomeTestCase, self).setUp() - ... # other setup code - -Also provided is a DummyCommand class, useful to mock commands in the -tests of another command that needs them, a create_distribution function -and a skip_unless_symlink decorator. - -Also provided is a DummyCommand class, useful to mock commands in the -tests of another command that needs them, a create_distribution function -and a skip_unless_symlink decorator. - -Each class or function has a docstring to explain its purpose and usage. -""" - -import os -import errno -import shutil -import logging -import weakref -import tempfile - -from packaging import logger -from packaging.dist import Distribution -from packaging.tests import unittest -from test.support import requires_zlib - -__all__ = ['LoggingCatcher', 'TempdirManager', 'EnvironRestorer', - 'DummyCommand', 'unittest', 'create_distribution', - 'skip_unless_symlink', 'requires_zlib'] - - -class _TestHandler(logging.handlers.BufferingHandler): - # stolen and adapted from test.support - - def __init__(self): - logging.handlers.BufferingHandler.__init__(self, 0) - self.setLevel(logging.DEBUG) - - def shouldFlush(self): - return False - - def emit(self, record): - self.buffer.append(record) - - -class LoggingCatcher: - """TestCase-compatible mixin to receive logging calls. - - Upon setUp, instances of this classes get a BufferingHandler that's - configured to record all messages logged to the 'packaging' logger. - - Use get_logs to retrieve messages and self.loghandler.flush to discard - them. get_logs automatically flushes the logs; if you test code that - generates logging messages but don't use get_logs, you have to flush - manually before doing other checks on logging message, otherwise you - will get irrelevant results. See example in test_command_check. - """ - - def setUp(self): - super(LoggingCatcher, self).setUp() - self.loghandler = handler = _TestHandler() - self.old_level = logger.level - logger.addHandler(handler) - logger.setLevel(logging.DEBUG) # we want all messages - - def tearDown(self): - handler = self.loghandler - # All this is necessary to properly shut down the logging system and - # avoid a regrtest complaint. Thanks to Vinay Sajip for the help. - handler.close() - logger.removeHandler(handler) - for ref in weakref.getweakrefs(handler): - logging._removeHandlerRef(ref) - del self.loghandler - logger.setLevel(self.old_level) - super(LoggingCatcher, self).tearDown() - - def get_logs(self, *levels): - """Return all log messages with level in *levels*. - - Without explicit levels given, returns all messages. *levels* defaults - to all levels. For log calls with arguments (i.e. - logger.info('bla bla %r', arg)), the messages will be formatted before - being returned (e.g. "bla bla 'thing'"). - - Returns a list. Automatically flushes the loghandler after being - called. - - Example: self.get_logs(logging.WARN, logging.DEBUG). - """ - if not levels: - messages = [log.getMessage() for log in self.loghandler.buffer] - else: - messages = [log.getMessage() for log in self.loghandler.buffer - if log.levelno in levels] - self.loghandler.flush() - return messages - - -class TempdirManager: - """TestCase-compatible mixin to create temporary directories and files. - - Directories and files created in a test_* method will be removed after it - has run. - """ - - def setUp(self): - super(TempdirManager, self).setUp() - self._basetempdir = tempfile.mkdtemp() - self._files = [] - - def tearDown(self): - shutil.rmtree(self._basetempdir, os.name in ('nt', 'cygwin')) - - for handle, name in self._files: - handle.close() - if os.path.exists(name): - try: - os.remove(name) - except OSError as exc: - if exc.errno != errno.ENOENT: - raise - - super(TempdirManager, self).tearDown() - - def mktempfile(self): - """Create a read-write temporary file and return it.""" - fd, fn = tempfile.mkstemp(dir=self._basetempdir) - os.close(fd) - fp = open(fn, 'w+') - self._files.append((fp, fn)) - return fp - - def mkdtemp(self): - """Create a temporary directory and return its path.""" - d = tempfile.mkdtemp(dir=self._basetempdir) - return d - - def write_file(self, path, content='xxx', encoding=None): - """Write a file at the given path. - - path can be a string, a tuple or a list; if it's a tuple or list, - os.path.join will be used to produce a path. - """ - if isinstance(path, (list, tuple)): - path = os.path.join(*path) - with open(path, 'w', encoding=encoding) as f: - f.write(content) - - def create_dist(self, **kw): - """Create a stub distribution object and files. - - This function creates a Distribution instance (use keyword arguments - to customize it) and a temporary directory with a project structure - (currently an empty directory). - - It returns the path to the directory and the Distribution instance. - You can use self.write_file to write any file in that - directory, e.g. setup scripts or Python modules. - """ - if 'name' not in kw: - kw['name'] = 'foo' - tmp_dir = self.mkdtemp() - project_dir = os.path.join(tmp_dir, kw['name']) - os.mkdir(project_dir) - dist = Distribution(attrs=kw) - return project_dir, dist - - def assertIsFile(self, *args): - path = os.path.join(*args) - dirname = os.path.dirname(path) - file = os.path.basename(path) - if os.path.isdir(dirname): - files = os.listdir(dirname) - msg = "%s not found in %s: %s" % (file, dirname, files) - assert os.path.isfile(path), msg - else: - raise AssertionError( - '%s not found. %s does not exist' % (file, dirname)) - - def assertIsNotFile(self, *args): - path = os.path.join(*args) - self.assertFalse(os.path.isfile(path), "%r exists" % path) - - -class EnvironRestorer: - """TestCase-compatible mixin to restore or delete environment variables. - - The variables to restore (or delete if they were not originally present) - must be explicitly listed in self.restore_environ. It's better to be - aware of what we're modifying instead of saving and restoring the whole - environment. - """ - - def setUp(self): - super(EnvironRestorer, self).setUp() - self._saved = [] - self._added = [] - for key in self.restore_environ: - if key in os.environ: - self._saved.append((key, os.environ[key])) - else: - self._added.append(key) - - def tearDown(self): - for key, value in self._saved: - os.environ[key] = value - for key in self._added: - os.environ.pop(key, None) - super(EnvironRestorer, self).tearDown() - - -class DummyCommand: - """Class to store options for retrieval via set_undefined_options(). - - Useful for mocking one dependency command in the tests for another - command, see e.g. the dummy build command in test_build_scripts. - """ - - def __init__(self, **kwargs): - for kw, val in kwargs.items(): - setattr(self, kw, val) - - def ensure_finalized(self): - pass - - -class TestDistribution(Distribution): - """Distribution subclasses that avoids the default search for - configuration files. - - The ._config_files attribute must be set before - .parse_config_files() is called. - """ - - def find_config_files(self): - return self._config_files - - -def create_distribution(configfiles=()): - """Prepares a distribution with given config files parsed.""" - d = TestDistribution() - d.config.find_config_files = d.find_config_files - d._config_files = configfiles - d.parse_config_files() - d.parse_command_line() - return d - - -def fake_dec(*args, **kw): - """Fake decorator""" - def _wrap(func): - def __wrap(*args, **kw): - return func(*args, **kw) - return __wrap - return _wrap - - -try: - from test.support import skip_unless_symlink -except ImportError: - skip_unless_symlink = unittest.skip( - 'requires test.support.skip_unless_symlink') diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_ccompiler.py --- a/Lib/packaging/tests/test_ccompiler.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -"""Tests for distutils.compiler.ccompiler.""" - -from packaging.compiler import ccompiler -from packaging.tests import unittest, support - - -class CCompilerTestCase(unittest.TestCase): - pass # XXX need some tests on CCompiler - - -def test_suite(): - return unittest.makeSuite(CCompilerTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_bdist.py --- a/Lib/packaging/tests/test_command_bdist.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -"""Tests for distutils.command.bdist.""" - -from packaging import util -from packaging.command.bdist import bdist, show_formats - -from packaging.tests import unittest, support, captured_stdout - - -class BuildTestCase(support.TempdirManager, - support.LoggingCatcher, - unittest.TestCase): - - def _mock_get_platform(self): - self._get_platform_called = True - return self._get_platform() - - def setUp(self): - super(BuildTestCase, self).setUp() - - # mock util.get_platform - self._get_platform_called = False - self._get_platform = util.get_platform - util.get_platform = self._mock_get_platform - - def tearDown(self): - super(BuildTestCase, self).tearDown() - util.get_platform = self._get_platform - - def test_formats(self): - - # let's create a command and make sure - # we can fix the format - pkg_pth, dist = self.create_dist() - cmd = bdist(dist) - cmd.formats = ['msi'] - cmd.ensure_finalized() - self.assertEqual(cmd.formats, ['msi']) - - # what format bdist offers ? - # XXX an explicit list in bdist is - # not the best way to bdist_* commands - # we should add a registry - formats = sorted(('zip', 'gztar', 'bztar', 'ztar', - 'tar', 'wininst', 'msi')) - found = sorted(cmd.format_command) - self.assertEqual(found, formats) - - def test_skip_build(self): - pkg_pth, dist = self.create_dist() - cmd = bdist(dist) - cmd.skip_build = False - cmd.formats = ['ztar'] - cmd.ensure_finalized() - self.assertFalse(self._get_platform_called) - - pkg_pth, dist = self.create_dist() - cmd = bdist(dist) - cmd.skip_build = True - cmd.formats = ['ztar'] - cmd.ensure_finalized() - self.assertTrue(self._get_platform_called) - - def test_show_formats(self): - __, stdout = captured_stdout(show_formats) - - # the output should be a header line + one line per format - num_formats = len(bdist.format_commands) - output = [line for line in stdout.split('\n') - if line.strip().startswith('--formats=')] - self.assertEqual(len(output), num_formats) - - -def test_suite(): - return unittest.makeSuite(BuildTestCase) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_bdist_dumb.py --- a/Lib/packaging/tests/test_command_bdist_dumb.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,96 +0,0 @@ -"""Tests for distutils.command.bdist_dumb.""" - -import sys -import os - -from packaging.dist import Distribution -from packaging.command.bdist_dumb import bdist_dumb -from packaging.tests import unittest, support -from packaging.tests.support import requires_zlib - - -SETUP_PY = """\ -from distutils.run import setup -import foo - -setup(name='foo', version='0.1', py_modules=['foo'], - url='xxx', author='xxx', author_email='xxx') -""" - - -class BuildDumbTestCase(support.TempdirManager, - support.LoggingCatcher, - unittest.TestCase): - - def setUp(self): - super(BuildDumbTestCase, self).setUp() - self.old_location = os.getcwd() - self.old_sys_argv = sys.argv, sys.argv[:] - - def tearDown(self): - os.chdir(self.old_location) - sys.argv = self.old_sys_argv[0] - sys.argv[:] = self.old_sys_argv[1] - super(BuildDumbTestCase, self).tearDown() - - @requires_zlib - def test_simple_built(self): - - # let's create a simple package - tmp_dir = self.mkdtemp() - pkg_dir = os.path.join(tmp_dir, 'foo') - os.mkdir(pkg_dir) - self.write_file((pkg_dir, 'setup.py'), SETUP_PY) - self.write_file((pkg_dir, 'foo.py'), '#') - self.write_file((pkg_dir, 'MANIFEST.in'), 'include foo.py') - self.write_file((pkg_dir, 'README'), '') - - dist = Distribution({'name': 'foo', 'version': '0.1', - 'py_modules': ['foo'], - 'url': 'xxx', 'author': 'xxx', - 'author_email': 'xxx'}) - os.chdir(pkg_dir) - - sys.argv[:] = ['setup.py'] - cmd = bdist_dumb(dist) - - # so the output is the same no matter - # what is the platform - cmd.format = 'zip' - - cmd.ensure_finalized() - cmd.run() - - # see what we have - dist_created = os.listdir(os.path.join(pkg_dir, 'dist')) - base = "%s.%s" % (dist.get_fullname(), cmd.plat_name) - if os.name == 'os2': - base = base.replace(':', '-') - - wanted = ['%s.zip' % base] - self.assertEqual(dist_created, wanted) - - # now let's check what we have in the zip file - # XXX to be done - - def test_finalize_options(self): - pkg_dir, dist = self.create_dist() - os.chdir(pkg_dir) - cmd = bdist_dumb(dist) - self.assertEqual(cmd.bdist_dir, None) - cmd.finalize_options() - - # bdist_dir is initialized to bdist_base/dumb if not set - base = cmd.get_finalized_command('bdist').bdist_base - self.assertEqual(cmd.bdist_dir, os.path.join(base, 'dumb')) - - # the format is set to a default value depending on the os.name - default = cmd.default_format[os.name] - self.assertEqual(cmd.format, default) - - -def test_suite(): - return unittest.makeSuite(BuildDumbTestCase) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_bdist_msi.py --- a/Lib/packaging/tests/test_command_bdist_msi.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -"""Tests for distutils.command.bdist_msi.""" -import sys - -from packaging.tests import unittest, support - - -class BDistMSITestCase(support.TempdirManager, - support.LoggingCatcher, - unittest.TestCase): - - @unittest.skipUnless(sys.platform == "win32", "runs only on win32") - def test_minimal(self): - # minimal test XXX need more tests - from packaging.command.bdist_msi import bdist_msi - pkg_pth, dist = self.create_dist() - cmd = bdist_msi(dist) - cmd.ensure_finalized() - - -def test_suite(): - return unittest.makeSuite(BDistMSITestCase) - - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_bdist_wininst.py --- a/Lib/packaging/tests/test_command_bdist_wininst.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -"""Tests for distutils.command.bdist_wininst.""" - -from packaging.command.bdist_wininst import bdist_wininst -from packaging.tests import unittest, support - - -class BuildWinInstTestCase(support.TempdirManager, - support.LoggingCatcher, - unittest.TestCase): - - def test_get_exe_bytes(self): - - # issue5731: command was broken on non-windows platforms - # this test makes sure it works now for every platform - # let's create a command - pkg_pth, dist = self.create_dist() - cmd = bdist_wininst(dist) - cmd.ensure_finalized() - - # let's run the code that finds the right wininst*.exe file - # and make sure it finds it and returns its content - # no matter what platform we have - exe_file = cmd.get_exe_bytes() - self.assertGreater(len(exe_file), 10) - - -def test_suite(): - return unittest.makeSuite(BuildWinInstTestCase) - - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_build.py --- a/Lib/packaging/tests/test_command_build.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -"""Tests for distutils.command.build.""" -import os -import sys - -from packaging.command.build import build -from sysconfig import get_platform -from packaging.tests import unittest, support - - -class BuildTestCase(support.TempdirManager, - support.LoggingCatcher, - unittest.TestCase): - - def test_finalize_options(self): - pkg_dir, dist = self.create_dist() - cmd = build(dist) - cmd.finalize_options() - - # if not specified, plat_name gets the current platform - self.assertEqual(cmd.plat_name, get_platform()) - - # build_purelib is build + lib - wanted = os.path.join(cmd.build_base, 'lib') - self.assertEqual(cmd.build_purelib, wanted) - - # build_platlib is 'build/lib.platform-x.x[-pydebug]' - # examples: - # build/lib.macosx-10.3-i386-2.7 - plat_spec = '.%s-%s' % (cmd.plat_name, sys.version[0:3]) - if hasattr(sys, 'gettotalrefcount'): - self.assertTrue(cmd.build_platlib.endswith('-pydebug')) - plat_spec += '-pydebug' - wanted = os.path.join(cmd.build_base, 'lib' + plat_spec) - self.assertEqual(cmd.build_platlib, wanted) - - # by default, build_lib = build_purelib - self.assertEqual(cmd.build_lib, cmd.build_purelib) - - # build_temp is build/temp. - wanted = os.path.join(cmd.build_base, 'temp' + plat_spec) - self.assertEqual(cmd.build_temp, wanted) - - # build_scripts is build/scripts-x.x - wanted = os.path.join(cmd.build_base, 'scripts-' + sys.version[0:3]) - self.assertEqual(cmd.build_scripts, wanted) - - # executable is os.path.normpath(sys.executable) - self.assertEqual(cmd.executable, os.path.normpath(sys.executable)) - - -def test_suite(): - return unittest.makeSuite(BuildTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_build_clib.py --- a/Lib/packaging/tests/test_command_build_clib.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,141 +0,0 @@ -"""Tests for distutils.command.build_clib.""" -import os -import sys - -from packaging.util import find_executable -from packaging.command.build_clib import build_clib -from packaging.errors import PackagingSetupError -from packaging.tests import unittest, support - - -class BuildCLibTestCase(support.TempdirManager, - support.LoggingCatcher, - unittest.TestCase): - - def test_check_library_dist(self): - pkg_dir, dist = self.create_dist() - cmd = build_clib(dist) - - # 'libraries' option must be a list - self.assertRaises(PackagingSetupError, cmd.check_library_list, 'foo') - - # each element of 'libraries' must a 2-tuple - self.assertRaises(PackagingSetupError, cmd.check_library_list, - ['foo1', 'foo2']) - - # first element of each tuple in 'libraries' - # must be a string (the library name) - self.assertRaises(PackagingSetupError, cmd.check_library_list, - [(1, 'foo1'), ('name', 'foo2')]) - - # library name may not contain directory separators - self.assertRaises(PackagingSetupError, cmd.check_library_list, - [('name', 'foo1'), - ('another/name', 'foo2')]) - - # second element of each tuple must be a dictionary (build info) - self.assertRaises(PackagingSetupError, cmd.check_library_list, - [('name', {}), - ('another', 'foo2')]) - - # those work - libs = [('name', {}), ('name', {'ok': 'good'})] - cmd.check_library_list(libs) - - def test_get_source_files(self): - pkg_dir, dist = self.create_dist() - cmd = build_clib(dist) - - # "in 'libraries' option 'sources' must be present and must be - # a list of source filenames - cmd.libraries = [('name', {})] - self.assertRaises(PackagingSetupError, cmd.get_source_files) - - cmd.libraries = [('name', {'sources': 1})] - self.assertRaises(PackagingSetupError, cmd.get_source_files) - - cmd.libraries = [('name', {'sources': ['a', 'b']})] - self.assertEqual(cmd.get_source_files(), ['a', 'b']) - - cmd.libraries = [('name', {'sources': ('a', 'b')})] - self.assertEqual(cmd.get_source_files(), ['a', 'b']) - - cmd.libraries = [('name', {'sources': ('a', 'b')}), - ('name2', {'sources': ['c', 'd']})] - self.assertEqual(cmd.get_source_files(), ['a', 'b', 'c', 'd']) - - def test_build_libraries(self): - pkg_dir, dist = self.create_dist() - cmd = build_clib(dist) - - class FakeCompiler: - def compile(*args, **kw): - pass - create_static_lib = compile - - cmd.compiler = FakeCompiler() - - # build_libraries is also doing a bit of type checking - lib = [('name', {'sources': 'notvalid'})] - self.assertRaises(PackagingSetupError, cmd.build_libraries, lib) - - lib = [('name', {'sources': []})] - cmd.build_libraries(lib) - - lib = [('name', {'sources': ()})] - cmd.build_libraries(lib) - - def test_finalize_options(self): - pkg_dir, dist = self.create_dist() - cmd = build_clib(dist) - - cmd.include_dirs = 'one-dir' - cmd.finalize_options() - self.assertEqual(cmd.include_dirs, ['one-dir']) - - cmd.include_dirs = None - cmd.finalize_options() - self.assertEqual(cmd.include_dirs, []) - - cmd.distribution.libraries = 'WONTWORK' - self.assertRaises(PackagingSetupError, cmd.finalize_options) - - @unittest.skipIf(sys.platform == 'win32', 'disabled on win32') - def test_run(self): - pkg_dir, dist = self.create_dist() - cmd = build_clib(dist) - - foo_c = os.path.join(pkg_dir, 'foo.c') - self.write_file(foo_c, 'int main(void) { return 1;}\n') - cmd.libraries = [('foo', {'sources': [foo_c]})] - - build_temp = os.path.join(pkg_dir, 'build') - os.mkdir(build_temp) - cmd.build_temp = build_temp - cmd.build_clib = build_temp - - # before we run the command, we want to make sure - # all commands are present on the system - # by creating a compiler and checking its executables - from packaging.compiler import new_compiler, customize_compiler - - compiler = new_compiler() - customize_compiler(compiler) - for ccmd in compiler.executables.values(): - if ccmd is None: - continue - if find_executable(ccmd[0]) is None: - raise unittest.SkipTest("can't test") - - # this should work - cmd.run() - - # let's check the result - self.assertIn('libfoo.a', os.listdir(build_temp)) - - -def test_suite(): - return unittest.makeSuite(BuildCLibTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_build_ext.py --- a/Lib/packaging/tests/test_command_build_ext.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,380 +0,0 @@ -import os -import sys -import site -import shutil -import sysconfig -from io import StringIO -from packaging.dist import Distribution -from packaging.errors import UnknownFileError, CompileError -from packaging.command.build_ext import build_ext -from packaging.compiler.extension import Extension - -from packaging.tests import support, unittest, verbose, unload - -# http://bugs.python.org/issue4373 -# Don't load the xx module more than once. -ALREADY_TESTED = False - - -def _get_source_filename(): - srcdir = sysconfig.get_config_var('srcdir') - return os.path.join(srcdir, 'Modules', 'xxmodule.c') - - -class BuildExtTestCase(support.TempdirManager, - support.LoggingCatcher, - unittest.TestCase): - def setUp(self): - # Create a simple test environment - # Note that we're making changes to sys.path - super(BuildExtTestCase, self).setUp() - self.tmp_dir = self.mkdtemp() - self.sys_path = sys.path, sys.path[:] - sys.path.append(self.tmp_dir) - filename = _get_source_filename() - if os.path.exists(filename): - shutil.copy(filename, self.tmp_dir) - self.old_user_base = site.USER_BASE - site.USER_BASE = self.mkdtemp() - build_ext.USER_BASE = site.USER_BASE - - def _fixup_command(self, cmd): - # When Python was build with --enable-shared, -L. is not good enough - # to find the libpython.so. This is because regrtest runs it - # under a tempdir, not in the top level where the .so lives. By the - # time we've gotten here, Python's already been chdir'd to the - # tempdir. - # - # To further add to the fun, we can't just add library_dirs to the - # Extension() instance because that doesn't get plumbed through to the - # final compiler command. - if (sysconfig.get_config_var('Py_ENABLE_SHARED') and - not sys.platform.startswith('win')): - runshared = sysconfig.get_config_var('RUNSHARED') - if runshared is None: - cmd.library_dirs = ['.'] - else: - name, equals, value = runshared.partition('=') - cmd.library_dirs = value.split(os.pathsep) - - def test_build_ext(self): - global ALREADY_TESTED - xx_c = os.path.join(self.tmp_dir, 'xxmodule.c') - if not os.path.exists(xx_c): - # skipping if we cannot find it - return - xx_ext = Extension('xx', [xx_c]) - dist = Distribution({'name': 'xx', 'ext_modules': [xx_ext]}) - dist.package_dir = self.tmp_dir - cmd = build_ext(dist) - self._fixup_command(cmd) - - if os.name == "nt": - # On Windows, we must build a debug version iff running - # a debug build of Python - cmd.debug = sys.executable.endswith("_d.exe") - cmd.build_lib = self.tmp_dir - cmd.build_temp = self.tmp_dir - - old_stdout = sys.stdout - if not verbose: - # silence compiler output - sys.stdout = StringIO() - try: - cmd.ensure_finalized() - cmd.run() - finally: - sys.stdout = old_stdout - - if ALREADY_TESTED: - return - else: - ALREADY_TESTED = True - - import xx - - for attr in ('error', 'foo', 'new', 'roj'): - self.assertTrue(hasattr(xx, attr)) - - self.assertEqual(xx.foo(2, 5), 7) - self.assertEqual(xx.foo(13, 15), 28) - self.assertEqual(xx.new().demo(), None) - doc = 'This is a template module just for instruction.' - self.assertEqual(xx.__doc__, doc) - self.assertTrue(isinstance(xx.Null(), xx.Null)) - self.assertTrue(isinstance(xx.Str(), xx.Str)) - - def tearDown(self): - # Get everything back to normal - unload('xx') - sys.path = self.sys_path[0] - sys.path[:] = self.sys_path[1] - if sys.version > "2.6": - site.USER_BASE = self.old_user_base - build_ext.USER_BASE = self.old_user_base - - super(BuildExtTestCase, self).tearDown() - - def test_solaris_enable_shared(self): - dist = Distribution({'name': 'xx'}) - cmd = build_ext(dist) - old = sys.platform - - sys.platform = 'sunos' # fooling finalize_options - from sysconfig import _CONFIG_VARS - - old_var = _CONFIG_VARS.get('Py_ENABLE_SHARED') - _CONFIG_VARS['Py_ENABLE_SHARED'] = 1 - try: - cmd.ensure_finalized() - finally: - sys.platform = old - if old_var is None: - del _CONFIG_VARS['Py_ENABLE_SHARED'] - else: - _CONFIG_VARS['Py_ENABLE_SHARED'] = old_var - - # make sure we get some library dirs under solaris - self.assertGreater(len(cmd.library_dirs), 0) - - @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher') - def test_user_site(self): - dist = Distribution({'name': 'xx'}) - cmd = build_ext(dist) - - # making sure the user option is there - options = [name for name, short, label in - cmd.user_options] - self.assertIn('user', options) - - # setting a value - cmd.user = True - - # setting user based lib and include - lib = os.path.join(site.USER_BASE, 'lib') - incl = os.path.join(site.USER_BASE, 'include') - os.mkdir(lib) - os.mkdir(incl) - - # let's run finalize - cmd.ensure_finalized() - - # see if include_dirs and library_dirs - # were set - self.assertIn(lib, cmd.library_dirs) - self.assertIn(lib, cmd.rpath) - self.assertIn(incl, cmd.include_dirs) - - def test_optional_extension(self): - - # this extension will fail, but let's ignore this failure - # with the optional argument. - modules = [Extension('foo', ['xxx'], optional=False)] - dist = Distribution({'name': 'xx', 'ext_modules': modules}) - cmd = build_ext(dist) - cmd.ensure_finalized() - self.assertRaises((UnknownFileError, CompileError), - cmd.run) # should raise an error - - modules = [Extension('foo', ['xxx'], optional=True)] - dist = Distribution({'name': 'xx', 'ext_modules': modules}) - cmd = build_ext(dist) - cmd.ensure_finalized() - cmd.run() # should pass - - def test_finalize_options(self): - # Make sure Python's include directories (for Python.h, pyconfig.h, - # etc.) are in the include search path. - modules = [Extension('foo', ['xxx'], optional=False)] - dist = Distribution({'name': 'xx', 'ext_modules': modules}) - cmd = build_ext(dist) - cmd.finalize_options() - - py_include = sysconfig.get_path('include') - self.assertIn(py_include, cmd.include_dirs) - - plat_py_include = sysconfig.get_path('platinclude') - self.assertIn(plat_py_include, cmd.include_dirs) - - # make sure cmd.libraries is turned into a list - # if it's a string - cmd = build_ext(dist) - cmd.libraries = 'my_lib' - cmd.finalize_options() - self.assertEqual(cmd.libraries, ['my_lib']) - - # make sure cmd.library_dirs is turned into a list - # if it's a string - cmd = build_ext(dist) - cmd.library_dirs = 'my_lib_dir' - cmd.finalize_options() - self.assertIn('my_lib_dir', cmd.library_dirs) - - # make sure rpath is turned into a list - # if it's a list of os.pathsep's paths - cmd = build_ext(dist) - cmd.rpath = os.pathsep.join(['one', 'two']) - cmd.finalize_options() - self.assertEqual(cmd.rpath, ['one', 'two']) - - # XXX more tests to perform for win32 - - # make sure define is turned into 2-tuples - # strings if they are ','-separated strings - cmd = build_ext(dist) - cmd.define = 'one,two' - cmd.finalize_options() - self.assertEqual(cmd.define, [('one', '1'), ('two', '1')]) - - # make sure undef is turned into a list of - # strings if they are ','-separated strings - cmd = build_ext(dist) - cmd.undef = 'one,two' - cmd.finalize_options() - self.assertEqual(cmd.undef, ['one', 'two']) - - # make sure swig_opts is turned into a list - cmd = build_ext(dist) - cmd.swig_opts = None - cmd.finalize_options() - self.assertEqual(cmd.swig_opts, []) - - cmd = build_ext(dist) - cmd.swig_opts = '1 2' - cmd.finalize_options() - self.assertEqual(cmd.swig_opts, ['1', '2']) - - def test_get_source_files(self): - modules = [Extension('foo', ['xxx'], optional=False)] - dist = Distribution({'name': 'xx', 'ext_modules': modules}) - cmd = build_ext(dist) - cmd.ensure_finalized() - self.assertEqual(cmd.get_source_files(), ['xxx']) - - def test_compiler_option(self): - # cmd.compiler is an option and - # should not be overriden by a compiler instance - # when the command is run - dist = Distribution() - cmd = build_ext(dist) - cmd.compiler = 'unix' - cmd.ensure_finalized() - cmd.run() - self.assertEqual(cmd.compiler, 'unix') - - def test_get_outputs(self): - tmp_dir = self.mkdtemp() - c_file = os.path.join(tmp_dir, 'foo.c') - self.write_file(c_file, 'void PyInit_foo(void) {}\n') - ext = Extension('foo', [c_file], optional=False) - dist = Distribution({'name': 'xx', - 'ext_modules': [ext]}) - cmd = build_ext(dist) - self._fixup_command(cmd) - cmd.ensure_finalized() - self.assertEqual(len(cmd.get_outputs()), 1) - - if os.name == "nt": - cmd.debug = sys.executable.endswith("_d.exe") - - cmd.build_lib = os.path.join(self.tmp_dir, 'build') - cmd.build_temp = os.path.join(self.tmp_dir, 'tempt') - - # issue #5977 : distutils build_ext.get_outputs - # returns wrong result with --inplace - other_tmp_dir = os.path.realpath(self.mkdtemp()) - old_wd = os.getcwd() - os.chdir(other_tmp_dir) - try: - cmd.inplace = True - cmd.run() - so_file = cmd.get_outputs()[0] - finally: - os.chdir(old_wd) - self.assertTrue(os.path.exists(so_file)) - so_ext = sysconfig.get_config_var('SO') - self.assertTrue(so_file.endswith(so_ext)) - so_dir = os.path.dirname(so_file) - self.assertEqual(so_dir, other_tmp_dir) - - cmd.inplace = False - cmd.run() - so_file = cmd.get_outputs()[0] - self.assertTrue(os.path.exists(so_file)) - self.assertTrue(so_file.endswith(so_ext)) - so_dir = os.path.dirname(so_file) - self.assertEqual(so_dir, cmd.build_lib) - - # inplace = False, cmd.package = 'bar' - build_py = cmd.get_finalized_command('build_py') - build_py.package_dir = 'bar' - path = cmd.get_ext_fullpath('foo') - # checking that the last directory is the build_dir - path = os.path.split(path)[0] - self.assertEqual(path, cmd.build_lib) - - # inplace = True, cmd.package = 'bar' - cmd.inplace = True - other_tmp_dir = os.path.realpath(self.mkdtemp()) - old_wd = os.getcwd() - os.chdir(other_tmp_dir) - try: - path = cmd.get_ext_fullpath('foo') - finally: - os.chdir(old_wd) - # checking that the last directory is bar - path = os.path.split(path)[0] - lastdir = os.path.split(path)[-1] - self.assertEqual(lastdir, 'bar') - - def test_ext_fullpath(self): - ext = sysconfig.get_config_vars()['SO'] - # building lxml.etree inplace - #etree_c = os.path.join(self.tmp_dir, 'lxml.etree.c') - #etree_ext = Extension('lxml.etree', [etree_c]) - #dist = Distribution({'name': 'lxml', 'ext_modules': [etree_ext]}) - dist = Distribution() - cmd = build_ext(dist) - cmd.inplace = True - cmd.distribution.package_dir = 'src' - cmd.distribution.packages = ['lxml', 'lxml.html'] - curdir = os.getcwd() - wanted = os.path.join(curdir, 'src', 'lxml', 'etree' + ext) - path = cmd.get_ext_fullpath('lxml.etree') - self.assertEqual(wanted, path) - - # building lxml.etree not inplace - cmd.inplace = False - cmd.build_lib = os.path.join(curdir, 'tmpdir') - wanted = os.path.join(curdir, 'tmpdir', 'lxml', 'etree' + ext) - path = cmd.get_ext_fullpath('lxml.etree') - self.assertEqual(wanted, path) - - # building twisted.runner.portmap not inplace - build_py = cmd.get_finalized_command('build_py') - build_py.package_dir = None - cmd.distribution.packages = ['twisted', 'twisted.runner.portmap'] - path = cmd.get_ext_fullpath('twisted.runner.portmap') - wanted = os.path.join(curdir, 'tmpdir', 'twisted', 'runner', - 'portmap' + ext) - self.assertEqual(wanted, path) - - # building twisted.runner.portmap inplace - cmd.inplace = True - path = cmd.get_ext_fullpath('twisted.runner.portmap') - wanted = os.path.join(curdir, 'twisted', 'runner', 'portmap' + ext) - self.assertEqual(wanted, path) - - -def test_suite(): - src = _get_source_filename() - if not os.path.exists(src): - if verbose: - print('test_command_build_ext: Cannot find source code (test' - ' must run in python build dir)') - return unittest.TestSuite() - else: - return unittest.makeSuite(BuildExtTestCase) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_build_py.py --- a/Lib/packaging/tests/test_command_build_py.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -"""Tests for distutils.command.build_py.""" - -import os -import sys - -from packaging.command.build_py import build_py -from packaging.dist import Distribution -from packaging.errors import PackagingFileError - -from packaging.tests import unittest, support - - -class BuildPyTestCase(support.TempdirManager, - support.LoggingCatcher, - unittest.TestCase): - - def test_package_data(self): - sources = self.mkdtemp() - pkg_dir = os.path.join(sources, 'pkg') - os.mkdir(pkg_dir) - f = open(os.path.join(pkg_dir, "__init__.py"), "w") - try: - f.write("# Pretend this is a package.") - finally: - f.close() - f = open(os.path.join(pkg_dir, "README.txt"), "w") - try: - f.write("Info about this package") - finally: - f.close() - - destination = self.mkdtemp() - - dist = Distribution({"packages": ["pkg"], - "package_dir": sources}) - - dist.command_obj["build"] = support.DummyCommand( - force=False, - build_lib=destination, - use_2to3_fixers=None, - convert_2to3_doctests=None, - use_2to3=False) - dist.packages = ["pkg"] - dist.package_data = {"pkg": ["README.txt"]} - dist.package_dir = sources - - cmd = build_py(dist) - cmd.compile = True - cmd.ensure_finalized() - self.assertEqual(cmd.package_data, dist.package_data) - - cmd.run() - - # This makes sure the list of outputs includes byte-compiled - # files for Python modules but not for package data files - # (there shouldn't *be* byte-code files for those!). - # - self.assertEqual(len(cmd.get_outputs()), 3) - pkgdest = os.path.join(destination, "pkg") - files = os.listdir(pkgdest) - self.assertIn("__init__.py", files) - self.assertIn("README.txt", files) - # XXX even with -O, distutils writes pyc, not pyo; bug? - if sys.dont_write_bytecode: - self.assertNotIn("__init__.pyc", files) - else: - self.assertIn("__init__.pyc", files) - - def test_empty_package_dir(self): - # See SF 1668596/1720897. - cwd = os.getcwd() - - # create the distribution files. - sources = self.mkdtemp() - pkg = os.path.join(sources, 'pkg') - os.mkdir(pkg) - open(os.path.join(pkg, "__init__.py"), "wb").close() - testdir = os.path.join(pkg, "doc") - os.mkdir(testdir) - open(os.path.join(testdir, "testfile"), "wb").close() - - os.chdir(sources) - old_stdout = sys.stdout - #sys.stdout = StringIO.StringIO() - - try: - dist = Distribution({"packages": ["pkg"], - "package_dir": sources, - "package_data": {"pkg": ["doc/*"]}}) - dist.script_args = ["build"] - dist.parse_command_line() - - try: - dist.run_commands() - except PackagingFileError: - self.fail("failed package_data test when package_dir is ''") - finally: - # Restore state. - os.chdir(cwd) - sys.stdout = old_stdout - - @unittest.skipUnless(hasattr(sys, 'dont_write_bytecode'), - 'sys.dont_write_bytecode not supported') - def test_dont_write_bytecode(self): - # makes sure byte_compile is not used - pkg_dir, dist = self.create_dist() - cmd = build_py(dist) - cmd.compile = True - cmd.optimize = 1 - - old_dont_write_bytecode = sys.dont_write_bytecode - sys.dont_write_bytecode = True - try: - cmd.byte_compile([]) - finally: - sys.dont_write_bytecode = old_dont_write_bytecode - - self.assertIn('byte-compiling is disabled', self.get_logs()[0]) - -def test_suite(): - return unittest.makeSuite(BuildPyTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_build_scripts.py --- a/Lib/packaging/tests/test_command_build_scripts.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -"""Tests for distutils.command.build_scripts.""" - -import os -import sys -import sysconfig -from packaging.dist import Distribution -from packaging.command.build_scripts import build_scripts - -from packaging.tests import unittest, support - - -class BuildScriptsTestCase(support.TempdirManager, - support.LoggingCatcher, - unittest.TestCase): - - def test_default_settings(self): - cmd = self.get_build_scripts_cmd("/foo/bar", []) - self.assertFalse(cmd.force) - self.assertIs(cmd.build_dir, None) - - cmd.finalize_options() - - self.assertTrue(cmd.force) - self.assertEqual(cmd.build_dir, "/foo/bar") - - def test_build(self): - source = self.mkdtemp() - target = self.mkdtemp() - expected = self.write_sample_scripts(source) - - cmd = self.get_build_scripts_cmd(target, - [os.path.join(source, fn) - for fn in expected]) - cmd.finalize_options() - cmd.run() - - built = os.listdir(target) - for name in expected: - self.assertIn(name, built) - - def get_build_scripts_cmd(self, target, scripts): - dist = Distribution() - dist.scripts = scripts - dist.command_obj["build"] = support.DummyCommand( - build_scripts=target, - force=True, - executable=sys.executable, - use_2to3=False, - use_2to3_fixers=None, - convert_2to3_doctests=None - ) - return build_scripts(dist) - - def write_sample_scripts(self, dir): - expected = [] - expected.append("script1.py") - self.write_script(dir, "script1.py", - ("#! /usr/bin/env python2.3\n" - "# bogus script w/ Python sh-bang\n" - "pass\n")) - expected.append("script2.py") - self.write_script(dir, "script2.py", - ("#!/usr/bin/python\n" - "# bogus script w/ Python sh-bang\n" - "pass\n")) - expected.append("shell.sh") - self.write_script(dir, "shell.sh", - ("#!/bin/sh\n" - "# bogus shell script w/ sh-bang\n" - "exit 0\n")) - return expected - - def write_script(self, dir, name, text): - with open(os.path.join(dir, name), "w") as f: - f.write(text) - - def test_version_int(self): - source = self.mkdtemp() - target = self.mkdtemp() - expected = self.write_sample_scripts(source) - - - cmd = self.get_build_scripts_cmd(target, - [os.path.join(source, fn) - for fn in expected]) - cmd.finalize_options() - - # http://bugs.python.org/issue4524 - # - # On linux-g++-32 with command line `./configure --enable-ipv6 - # --with-suffix=3`, python is compiled okay but the build scripts - # failed when writing the name of the executable - old = sysconfig.get_config_vars().get('VERSION') - sysconfig._CONFIG_VARS['VERSION'] = 4 - try: - cmd.run() - finally: - if old is not None: - sysconfig._CONFIG_VARS['VERSION'] = old - - built = os.listdir(target) - for name in expected: - self.assertIn(name, built) - -def test_suite(): - return unittest.makeSuite(BuildScriptsTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_check.py --- a/Lib/packaging/tests/test_command_check.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -"""Tests for distutils.command.check.""" - -import logging -from packaging.command.check import check -from packaging.metadata import _HAS_DOCUTILS -from packaging.errors import PackagingSetupError, MetadataMissingError -from packaging.tests import unittest, support - - -class CheckTestCase(support.LoggingCatcher, - support.TempdirManager, - unittest.TestCase): - - def _run(self, metadata=None, **options): - if metadata is None: - metadata = {'name': 'xxx', 'version': '1.2'} - pkg_info, dist = self.create_dist(**metadata) - cmd = check(dist) - cmd.initialize_options() - for name, value in options.items(): - setattr(cmd, name, value) - cmd.ensure_finalized() - cmd.run() - return cmd - - def test_check_metadata(self): - # let's run the command with no metadata at all - # by default, check is checking the metadata - # should have some warnings - cmd = self._run() - # trick: using assertNotEqual with an empty list will give us a more - # useful error message than assertGreater(.., 0) when the code change - # and the test fails - self.assertNotEqual([], self.get_logs(logging.WARNING)) - - # now let's add the required fields - # and run it again, to make sure we don't get - # any warning anymore - metadata = {'home_page': 'xxx', 'author': 'xxx', - 'author_email': 'xxx', - 'name': 'xxx', 'version': '4.2', - } - cmd = self._run(metadata) - self.assertEqual([], self.get_logs(logging.WARNING)) - - # now with the strict mode, we should - # get an error if there are missing metadata - self.assertRaises(MetadataMissingError, self._run, {}, **{'strict': 1}) - self.assertRaises(PackagingSetupError, self._run, - {'name': 'xxx', 'version': 'xxx'}, **{'strict': 1}) - - # clear warnings from the previous calls - self.loghandler.flush() - - # and of course, no error when all metadata fields are present - cmd = self._run(metadata, strict=True) - self.assertEqual([], self.get_logs(logging.WARNING)) - - def test_check_metadata_1_2(self): - # let's run the command with no metadata at all - # by default, check is checking the metadata - # should have some warnings - cmd = self._run() - self.assertNotEqual([], self.get_logs(logging.WARNING)) - - # now let's add the required fields and run it again, to make sure we - # don't get any warning anymore let's use requires_python as a marker - # to enforce Metadata-Version 1.2 - metadata = {'home_page': 'xxx', 'author': 'xxx', - 'author_email': 'xxx', - 'name': 'xxx', 'version': '4.2', - 'requires_python': '2.4', - } - cmd = self._run(metadata) - self.assertEqual([], self.get_logs(logging.WARNING)) - - # now with the strict mode, we should - # get an error if there are missing metadata - self.assertRaises(MetadataMissingError, self._run, {}, **{'strict': 1}) - self.assertRaises(PackagingSetupError, self._run, - {'name': 'xxx', 'version': 'xxx'}, **{'strict': 1}) - - # complain about version format - metadata['version'] = 'xxx' - self.assertRaises(PackagingSetupError, self._run, metadata, - **{'strict': 1}) - - # clear warnings from the previous calls - self.loghandler.flush() - - # now with correct version format again - metadata['version'] = '4.2' - cmd = self._run(metadata, strict=True) - self.assertEqual([], self.get_logs(logging.WARNING)) - - @unittest.skipUnless(_HAS_DOCUTILS, "requires docutils") - def test_check_restructuredtext(self): - # let's see if it detects broken rest in long_description - broken_rest = 'title\n===\n\ntest' - pkg_info, dist = self.create_dist(description=broken_rest) - cmd = check(dist) - cmd.check_restructuredtext() - self.assertEqual(len(self.get_logs(logging.WARNING)), 1) - - pkg_info, dist = self.create_dist(description='title\n=====\n\ntest') - cmd = check(dist) - cmd.check_restructuredtext() - self.assertEqual([], self.get_logs(logging.WARNING)) - - def test_check_all(self): - self.assertRaises(PackagingSetupError, self._run, - {'name': 'xxx', 'version': 'xxx'}, **{'strict': 1, - 'all': 1}) - self.assertRaises(MetadataMissingError, self._run, - {}, **{'strict': 1, - 'all': 1}) - - def test_check_hooks(self): - pkg_info, dist = self.create_dist() - dist.command_options['install_dist'] = { - 'pre_hook': ('file', {"a": 'some.nonextistant.hook.ghrrraarrhll'}), - } - cmd = check(dist) - cmd.check_hooks_resolvable() - self.assertEqual(len(self.get_logs(logging.WARNING)), 1) - - def test_warn(self): - _, dist = self.create_dist() - cmd = check(dist) - self.assertEqual([], self.get_logs()) - cmd.warn('hello') - self.assertEqual(['check: hello'], self.get_logs()) - cmd.warn('hello %s', 'world') - self.assertEqual(['check: hello world'], self.get_logs()) - cmd.warn('hello %s %s', 'beautiful', 'world') - self.assertEqual(['check: hello beautiful world'], self.get_logs()) - - -def test_suite(): - return unittest.makeSuite(CheckTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_clean.py --- a/Lib/packaging/tests/test_command_clean.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -"""Tests for distutils.command.clean.""" -import os - -from packaging.command.clean import clean -from packaging.tests import unittest, support - - -class cleanTestCase(support.TempdirManager, support.LoggingCatcher, - unittest.TestCase): - - def test_simple_run(self): - pkg_dir, dist = self.create_dist() - cmd = clean(dist) - - # let's add some elements clean should remove - dirs = [(d, os.path.join(pkg_dir, d)) - for d in ('build_temp', 'build_lib', 'bdist_base', - 'build_scripts', 'build_base')] - - for name, path in dirs: - os.mkdir(path) - setattr(cmd, name, path) - if name == 'build_base': - continue - for f in ('one', 'two', 'three'): - self.write_file(os.path.join(path, f)) - - # let's run the command - cmd.all = True - cmd.ensure_finalized() - cmd.run() - - # make sure the files where removed - for name, path in dirs: - self.assertFalse(os.path.exists(path), - '%r was not removed' % path) - - # let's run the command again (should spit warnings but succeed) - cmd.all = True - cmd.ensure_finalized() - cmd.run() - - -def test_suite(): - return unittest.makeSuite(cleanTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_cmd.py --- a/Lib/packaging/tests/test_command_cmd.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -"""Tests for distutils.cmd.""" -import os - -from packaging.command.cmd import Command -from packaging.dist import Distribution -from packaging.errors import PackagingOptionError -from packaging.tests import support, unittest - - -class MyCmd(Command): - def initialize_options(self): - pass - - -class CommandTestCase(support.LoggingCatcher, - unittest.TestCase): - - def setUp(self): - super(CommandTestCase, self).setUp() - dist = Distribution() - self.cmd = MyCmd(dist) - - def test_make_file(self): - cmd = self.cmd - - # making sure it raises when infiles is not a string or a list/tuple - self.assertRaises(TypeError, cmd.make_file, - infiles=1, outfile='', func='func', args=()) - - # making sure execute gets called properly - def _execute(func, args, exec_msg, level): - self.assertEqual(exec_msg, 'generating out from in') - cmd.force = True - cmd.execute = _execute - cmd.make_file(infiles='in', outfile='out', func='func', args=()) - - def test_dump_options(self): - cmd = self.cmd - cmd.option1 = 1 - cmd.option2 = 1 - cmd.user_options = [('option1', '', ''), ('option2', '', '')] - cmd.dump_options() - - wanted = ["command options for 'MyCmd':", ' option1 = 1', - ' option2 = 1'] - msgs = self.get_logs() - self.assertEqual(msgs, wanted) - - def test_ensure_string(self): - cmd = self.cmd - cmd.option1 = 'ok' - cmd.ensure_string('option1') - - cmd.option2 = None - cmd.ensure_string('option2', 'xxx') - self.assertTrue(hasattr(cmd, 'option2')) - - cmd.option3 = 1 - self.assertRaises(PackagingOptionError, cmd.ensure_string, 'option3') - - def test_ensure_string_list(self): - cmd = self.cmd - cmd.option1 = 'ok,dok' - cmd.ensure_string_list('option1') - self.assertEqual(cmd.option1, ['ok', 'dok']) - - cmd.yes_string_list = ['one', 'two', 'three'] - cmd.yes_string_list2 = 'ok' - cmd.ensure_string_list('yes_string_list') - cmd.ensure_string_list('yes_string_list2') - self.assertEqual(cmd.yes_string_list, ['one', 'two', 'three']) - self.assertEqual(cmd.yes_string_list2, ['ok']) - - cmd.not_string_list = ['one', 2, 'three'] - cmd.not_string_list2 = object() - self.assertRaises(PackagingOptionError, - cmd.ensure_string_list, 'not_string_list') - - self.assertRaises(PackagingOptionError, - cmd.ensure_string_list, 'not_string_list2') - - def test_ensure_filename(self): - cmd = self.cmd - cmd.option1 = __file__ - cmd.ensure_filename('option1') - cmd.option2 = 'xxx' - self.assertRaises(PackagingOptionError, cmd.ensure_filename, 'option2') - - def test_ensure_dirname(self): - cmd = self.cmd - cmd.option1 = os.path.dirname(__file__) or os.curdir - cmd.ensure_dirname('option1') - cmd.option2 = 'xxx' - self.assertRaises(PackagingOptionError, cmd.ensure_dirname, 'option2') - - -def test_suite(): - return unittest.makeSuite(CommandTestCase) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_config.py --- a/Lib/packaging/tests/test_command_config.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -"""Tests for distutils.command.config.""" -import os -import sys -import logging - -from packaging.command.config import dump_file, config -from packaging.tests import unittest, support - - -class ConfigTestCase(support.LoggingCatcher, - support.TempdirManager, - unittest.TestCase): - - def test_dump_file(self): - this_file = __file__.rstrip('co') - with open(this_file) as f: - numlines = len(f.readlines()) - - dump_file(this_file, 'I am the header') - - logs = [] - for log in self.get_logs(logging.INFO): - logs.extend(line for line in log.split('\n')) - self.assertEqual(len(logs), numlines + 2) - - @unittest.skipIf(sys.platform == 'win32', 'disabled on win32') - def test_search_cpp(self): - pkg_dir, dist = self.create_dist() - cmd = config(dist) - - # simple pattern searches - match = cmd.search_cpp(pattern='xxx', body='// xxx') - self.assertEqual(match, 0) - - match = cmd.search_cpp(pattern='_configtest', body='// xxx') - self.assertEqual(match, 1) - - def test_finalize_options(self): - # finalize_options does a bit of transformation - # on options - pkg_dir, dist = self.create_dist() - cmd = config(dist) - cmd.include_dirs = 'one%stwo' % os.pathsep - cmd.libraries = 'one' - cmd.library_dirs = 'three%sfour' % os.pathsep - cmd.ensure_finalized() - - self.assertEqual(cmd.include_dirs, ['one', 'two']) - self.assertEqual(cmd.libraries, ['one']) - self.assertEqual(cmd.library_dirs, ['three', 'four']) - - def test_clean(self): - # _clean removes files - tmp_dir = self.mkdtemp() - f1 = os.path.join(tmp_dir, 'one') - f2 = os.path.join(tmp_dir, 'two') - - self.write_file(f1, 'xxx') - self.write_file(f2, 'xxx') - - for f in (f1, f2): - self.assertTrue(os.path.exists(f)) - - pkg_dir, dist = self.create_dist() - cmd = config(dist) - cmd._clean(f1, f2) - - for f in (f1, f2): - self.assertFalse(os.path.exists(f)) - - -def test_suite(): - return unittest.makeSuite(ConfigTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_install_data.py --- a/Lib/packaging/tests/test_command_install_data.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ -"""Tests for packaging.command.install_data.""" -import os -import sysconfig -from sysconfig import _get_default_scheme -from packaging.tests import unittest, support -from packaging.command.install_data import install_data - - -class InstallDataTestCase(support.TempdirManager, - support.LoggingCatcher, - unittest.TestCase): - - def test_simple_run(self): - scheme = _get_default_scheme() - old_items = sysconfig._SCHEMES.items(scheme) - def restore(): - sysconfig._SCHEMES.remove_section(scheme) - sysconfig._SCHEMES.add_section(scheme) - for option, value in old_items: - sysconfig._SCHEMES.set(scheme, option, value) - self.addCleanup(restore) - - pkg_dir, dist = self.create_dist() - cmd = install_data(dist) - cmd.install_dir = inst = os.path.join(pkg_dir, 'inst') - - sysconfig._SCHEMES.set(scheme, 'inst', - os.path.join(pkg_dir, 'inst')) - sysconfig._SCHEMES.set(scheme, 'inst2', - os.path.join(pkg_dir, 'inst2')) - - one = os.path.join(pkg_dir, 'one') - self.write_file(one, 'xxx') - inst2 = os.path.join(pkg_dir, 'inst2') - two = os.path.join(pkg_dir, 'two') - self.write_file(two, 'xxx') - - cmd.data_files = {one: '{inst}/one', two: '{inst2}/two'} - self.assertCountEqual(cmd.get_inputs(), [one, two]) - - # let's run the command - cmd.ensure_finalized() - cmd.run() - - # let's check the result - self.assertEqual(len(cmd.get_outputs()), 2) - rtwo = os.path.split(two)[-1] - self.assertTrue(os.path.exists(os.path.join(inst2, rtwo))) - rone = os.path.split(one)[-1] - self.assertTrue(os.path.exists(os.path.join(inst, rone))) - cmd.outfiles = [] - - # let's try with warn_dir one - cmd.warn_dir = True - cmd.ensure_finalized() - cmd.run() - - # let's check the result - self.assertEqual(len(cmd.get_outputs()), 2) - self.assertTrue(os.path.exists(os.path.join(inst2, rtwo))) - self.assertTrue(os.path.exists(os.path.join(inst, rone))) - cmd.outfiles = [] - - # now using root and empty dir - cmd.root = os.path.join(pkg_dir, 'root') - three = os.path.join(cmd.install_dir, 'three') - self.write_file(three, 'xx') - - sysconfig._SCHEMES.set(scheme, 'inst3', - cmd.install_dir) - - cmd.data_files = {one: '{inst}/one', two: '{inst2}/two', - three: '{inst3}/three'} - cmd.ensure_finalized() - cmd.run() - - # let's check the result - self.assertEqual(len(cmd.get_outputs()), 3) - self.assertTrue(os.path.exists(os.path.join(inst2, rtwo))) - self.assertTrue(os.path.exists(os.path.join(inst, rone))) - - -def test_suite(): - return unittest.makeSuite(InstallDataTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_install_dist.py --- a/Lib/packaging/tests/test_command_install_dist.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,205 +0,0 @@ -"""Tests for packaging.command.install.""" - -import os -import sys - -from sysconfig import (get_scheme_names, get_config_vars, - _SCHEMES, get_config_var, get_path) - -_CONFIG_VARS = get_config_vars() - -from packaging.tests import captured_stdout - -from packaging.command.install_dist import install_dist -from packaging.command import install_dist as install_module -from packaging.dist import Distribution -from packaging.errors import PackagingOptionError - -from packaging.tests import unittest, support - - -class InstallTestCase(support.TempdirManager, - support.LoggingCatcher, - unittest.TestCase): - - def test_home_installation_scheme(self): - # This ensure two things: - # - that --home generates the desired set of directory names - # - test --home is supported on all platforms - builddir = self.mkdtemp() - destination = os.path.join(builddir, "installation") - - dist = Distribution({"name": "foopkg"}) - dist.command_obj["build"] = support.DummyCommand( - build_base=builddir, - build_lib=os.path.join(builddir, "lib"), - ) - - old_posix_prefix = _SCHEMES.get('posix_prefix', 'platinclude') - old_posix_home = _SCHEMES.get('posix_home', 'platinclude') - - new_path = '{platbase}/include/python{py_version_short}' - _SCHEMES.set('posix_prefix', 'platinclude', new_path) - _SCHEMES.set('posix_home', 'platinclude', '{platbase}/include/python') - - try: - cmd = install_dist(dist) - cmd.home = destination - cmd.ensure_finalized() - finally: - _SCHEMES.set('posix_prefix', 'platinclude', old_posix_prefix) - _SCHEMES.set('posix_home', 'platinclude', old_posix_home) - - self.assertEqual(cmd.install_base, destination) - self.assertEqual(cmd.install_platbase, destination) - - def check_path(got, expected): - got = os.path.normpath(got) - expected = os.path.normpath(expected) - self.assertEqual(got, expected) - - libdir = os.path.join(destination, "lib", "python") - check_path(cmd.install_lib, libdir) - check_path(cmd.install_platlib, libdir) - check_path(cmd.install_purelib, libdir) - check_path(cmd.install_headers, - os.path.join(destination, "include", "python", "foopkg")) - check_path(cmd.install_scripts, os.path.join(destination, "bin")) - check_path(cmd.install_data, destination) - - @unittest.skipIf(sys.version < '2.6', 'requires Python 2.6 or higher') - def test_user_site(self): - # test install with --user - # preparing the environment for the test - self.old_user_base = get_config_var('userbase') - self.old_user_site = get_path('purelib', '%s_user' % os.name) - self.tmpdir = self.mkdtemp() - self.user_base = os.path.join(self.tmpdir, 'B') - self.user_site = os.path.join(self.tmpdir, 'S') - _CONFIG_VARS['userbase'] = self.user_base - scheme = '%s_user' % os.name - _SCHEMES.set(scheme, 'purelib', self.user_site) - - def _expanduser(path): - if path[0] == '~': - path = os.path.normpath(self.tmpdir) + path[1:] - return path - - self.old_expand = os.path.expanduser - os.path.expanduser = _expanduser - - try: - # this is the actual test - self._test_user_site() - finally: - _CONFIG_VARS['userbase'] = self.old_user_base - _SCHEMES.set(scheme, 'purelib', self.old_user_site) - os.path.expanduser = self.old_expand - - def _test_user_site(self): - schemes = get_scheme_names() - for key in ('nt_user', 'posix_user', 'os2_home'): - self.assertIn(key, schemes) - - dist = Distribution({'name': 'xx'}) - cmd = install_dist(dist) - # making sure the user option is there - options = [name for name, short, lable in - cmd.user_options] - self.assertIn('user', options) - - # setting a value - cmd.user = True - - # user base and site shouldn't be created yet - self.assertFalse(os.path.exists(self.user_base)) - self.assertFalse(os.path.exists(self.user_site)) - - # let's run finalize - cmd.ensure_finalized() - - # now they should - self.assertTrue(os.path.exists(self.user_base)) - self.assertTrue(os.path.exists(self.user_site)) - - self.assertIn('userbase', cmd.config_vars) - self.assertIn('usersite', cmd.config_vars) - - def test_handle_extra_path(self): - dist = Distribution({'name': 'xx', 'extra_path': 'path,dirs'}) - cmd = install_dist(dist) - - # two elements - cmd.handle_extra_path() - self.assertEqual(cmd.extra_path, ['path', 'dirs']) - self.assertEqual(cmd.extra_dirs, 'dirs') - self.assertEqual(cmd.path_file, 'path') - - # one element - cmd.extra_path = ['path'] - cmd.handle_extra_path() - self.assertEqual(cmd.extra_path, ['path']) - self.assertEqual(cmd.extra_dirs, 'path') - self.assertEqual(cmd.path_file, 'path') - - # none - dist.extra_path = cmd.extra_path = None - cmd.handle_extra_path() - self.assertEqual(cmd.extra_path, None) - self.assertEqual(cmd.extra_dirs, '') - self.assertEqual(cmd.path_file, None) - - # three elements (no way !) - cmd.extra_path = 'path,dirs,again' - self.assertRaises(PackagingOptionError, cmd.handle_extra_path) - - def test_finalize_options(self): - dist = Distribution({'name': 'xx'}) - cmd = install_dist(dist) - - # must supply either prefix/exec-prefix/home or - # install-base/install-platbase -- not both - cmd.prefix = 'prefix' - cmd.install_base = 'base' - self.assertRaises(PackagingOptionError, cmd.finalize_options) - - # must supply either home or prefix/exec-prefix -- not both - cmd.install_base = None - cmd.home = 'home' - self.assertRaises(PackagingOptionError, cmd.finalize_options) - - if sys.version >= '2.6': - # can't combine user with with prefix/exec_prefix/home or - # install_(plat)base - cmd.prefix = None - cmd.user = 'user' - self.assertRaises(PackagingOptionError, cmd.finalize_options) - - def test_old_record(self): - # test pre-PEP 376 --record option (outside dist-info dir) - install_dir = self.mkdtemp() - pkgdir, dist = self.create_dist() - - dist = Distribution() - cmd = install_dist(dist) - dist.command_obj['install_dist'] = cmd - cmd.root = install_dir - cmd.record = os.path.join(pkgdir, 'filelist') - cmd.ensure_finalized() - cmd.run() - - # let's check the record file was created with four - # lines, one for each .dist-info entry: METADATA, - # INSTALLER, REQUSTED, RECORD - with open(cmd.record) as f: - self.assertEqual(len(f.readlines()), 4) - - # XXX test that fancy_getopt is okay with options named - # record and no-record but unrelated - - -def test_suite(): - return unittest.makeSuite(InstallTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_install_distinfo.py --- a/Lib/packaging/tests/test_command_install_distinfo.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,192 +0,0 @@ -"""Tests for ``packaging.command.install_distinfo``. """ - -import os -import csv -import hashlib -import sys - -from packaging.command.install_distinfo import install_distinfo -from packaging.command.cmd import Command -from packaging.metadata import Metadata -from packaging.tests import unittest, support - - -class DummyInstallCmd(Command): - - def __init__(self, dist=None): - self.outputs = [] - self.distribution = dist - - def __getattr__(self, name): - return None - - def ensure_finalized(self): - pass - - def get_outputs(self): - return (self.outputs + - self.get_finalized_command('install_distinfo').get_outputs()) - - -class InstallDistinfoTestCase(support.TempdirManager, - support.LoggingCatcher, - unittest.TestCase): - - checkLists = lambda self, x, y: self.assertListEqual(sorted(x), sorted(y)) - - def test_empty_install(self): - pkg_dir, dist = self.create_dist(name='foo', - version='1.0') - install_dir = self.mkdtemp() - - install = DummyInstallCmd(dist) - dist.command_obj['install_dist'] = install - - cmd = install_distinfo(dist) - dist.command_obj['install_distinfo'] = cmd - - cmd.initialize_options() - cmd.distinfo_dir = install_dir - cmd.ensure_finalized() - cmd.run() - - self.checkLists(os.listdir(install_dir), ['foo-1.0.dist-info']) - - dist_info = os.path.join(install_dir, 'foo-1.0.dist-info') - self.checkLists(os.listdir(dist_info), - ['METADATA', 'RECORD', 'REQUESTED', 'INSTALLER']) - with open(os.path.join(dist_info, 'INSTALLER')) as fp: - self.assertEqual(fp.read(), 'distutils') - with open(os.path.join(dist_info, 'REQUESTED')) as fp: - self.assertEqual(fp.read(), '') - meta_path = os.path.join(dist_info, 'METADATA') - self.assertTrue(Metadata(path=meta_path).check()) - - def test_installer(self): - pkg_dir, dist = self.create_dist(name='foo', - version='1.0') - install_dir = self.mkdtemp() - - install = DummyInstallCmd(dist) - dist.command_obj['install_dist'] = install - - cmd = install_distinfo(dist) - dist.command_obj['install_distinfo'] = cmd - - cmd.initialize_options() - cmd.distinfo_dir = install_dir - cmd.installer = 'bacon-python' - cmd.ensure_finalized() - cmd.run() - - dist_info = os.path.join(install_dir, 'foo-1.0.dist-info') - with open(os.path.join(dist_info, 'INSTALLER')) as fp: - self.assertEqual(fp.read(), 'bacon-python') - - def test_requested(self): - pkg_dir, dist = self.create_dist(name='foo', - version='1.0') - install_dir = self.mkdtemp() - - install = DummyInstallCmd(dist) - dist.command_obj['install_dist'] = install - - cmd = install_distinfo(dist) - dist.command_obj['install_distinfo'] = cmd - - cmd.initialize_options() - cmd.distinfo_dir = install_dir - cmd.requested = False - cmd.ensure_finalized() - cmd.run() - - dist_info = os.path.join(install_dir, 'foo-1.0.dist-info') - self.checkLists(os.listdir(dist_info), - ['METADATA', 'RECORD', 'INSTALLER']) - - def test_no_record(self): - pkg_dir, dist = self.create_dist(name='foo', - version='1.0') - install_dir = self.mkdtemp() - - install = DummyInstallCmd(dist) - dist.command_obj['install_dist'] = install - - cmd = install_distinfo(dist) - dist.command_obj['install_distinfo'] = cmd - - cmd.initialize_options() - cmd.distinfo_dir = install_dir - cmd.no_record = True - cmd.ensure_finalized() - cmd.run() - - dist_info = os.path.join(install_dir, 'foo-1.0.dist-info') - self.checkLists(os.listdir(dist_info), - ['METADATA', 'REQUESTED', 'INSTALLER']) - - def test_record(self): - pkg_dir, dist = self.create_dist(name='foo', - version='1.0') - install_dir = self.mkdtemp() - - install = DummyInstallCmd(dist) - dist.command_obj['install_dist'] = install - - fake_dists = os.path.join(os.path.dirname(__file__), 'fake_dists') - fake_dists = os.path.realpath(fake_dists) - - # for testing, we simply add all files from _backport's fake_dists - dirs = [] - for dir in os.listdir(fake_dists): - full_path = os.path.join(fake_dists, dir) - if (not dir.endswith('.egg') or dir.endswith('.egg-info') or - dir.endswith('.dist-info')) and os.path.isdir(full_path): - dirs.append(full_path) - - for dir in dirs: - for path, subdirs, files in os.walk(dir): - install.outputs += [os.path.join(path, f) for f in files] - install.outputs += [os.path.join('path', f + 'c') - for f in files if f.endswith('.py')] - - cmd = install_distinfo(dist) - dist.command_obj['install_distinfo'] = cmd - - cmd.initialize_options() - cmd.distinfo_dir = install_dir - cmd.ensure_finalized() - cmd.run() - - dist_info = os.path.join(install_dir, 'foo-1.0.dist-info') - - expected = [] - for f in install.get_outputs(): - if (f.endswith('.pyc') or f == os.path.join( - install_dir, 'foo-1.0.dist-info', 'RECORD')): - expected.append([f, '', '']) - else: - size = os.path.getsize(f) - md5 = hashlib.md5() - with open(f, 'rb') as fp: - md5.update(fp.read()) - hash = md5.hexdigest() - expected.append([f, hash, str(size)]) - - parsed = [] - with open(os.path.join(dist_info, 'RECORD'), 'r') as f: - reader = csv.reader(f, delimiter=',', - lineterminator=os.linesep, - quotechar='"') - parsed = list(reader) - - self.maxDiff = None - self.checkLists(parsed, expected) - - -def test_suite(): - return unittest.makeSuite(InstallDistinfoTestCase) - - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_install_headers.py --- a/Lib/packaging/tests/test_command_install_headers.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -"""Tests for packaging.command.install_headers.""" -import os - -from packaging.command.install_headers import install_headers -from packaging.tests import unittest, support - - -class InstallHeadersTestCase(support.TempdirManager, - support.LoggingCatcher, - unittest.TestCase): - - def test_simple_run(self): - # we have two headers - header_list = self.mkdtemp() - header1 = os.path.join(header_list, 'header1') - header2 = os.path.join(header_list, 'header2') - self.write_file(header1) - self.write_file(header2) - headers = [header1, header2] - - pkg_dir, dist = self.create_dist(headers=headers) - cmd = install_headers(dist) - self.assertEqual(cmd.get_inputs(), headers) - - # let's run the command - cmd.install_dir = os.path.join(pkg_dir, 'inst') - cmd.ensure_finalized() - cmd.run() - - # let's check the results - self.assertEqual(len(cmd.get_outputs()), 2) - - -def test_suite(): - return unittest.makeSuite(InstallHeadersTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_install_lib.py --- a/Lib/packaging/tests/test_command_install_lib.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -"""Tests for packaging.command.install_data.""" -import sys -import os - -from packaging.tests import unittest, support -from packaging.command.install_lib import install_lib -from packaging.compiler.extension import Extension -from packaging.errors import PackagingOptionError - -try: - no_bytecode = sys.dont_write_bytecode - bytecode_support = True -except AttributeError: - no_bytecode = False - bytecode_support = False - - -class InstallLibTestCase(support.TempdirManager, - support.LoggingCatcher, - support.EnvironRestorer, - unittest.TestCase): - - restore_environ = ['PYTHONPATH'] - - def test_finalize_options(self): - pkg_dir, dist = self.create_dist() - cmd = install_lib(dist) - - cmd.finalize_options() - self.assertTrue(cmd.compile) - self.assertEqual(cmd.optimize, 0) - - # optimize must be 0, 1, or 2 - cmd.optimize = 'foo' - self.assertRaises(PackagingOptionError, cmd.finalize_options) - cmd.optimize = '4' - self.assertRaises(PackagingOptionError, cmd.finalize_options) - - cmd.optimize = '2' - cmd.finalize_options() - self.assertEqual(cmd.optimize, 2) - - @unittest.skipIf(no_bytecode, 'byte-compile not supported') - def test_byte_compile(self): - pkg_dir, dist = self.create_dist() - cmd = install_lib(dist) - cmd.compile = True - cmd.optimize = 1 - - f = os.path.join(pkg_dir, 'foo.py') - self.write_file(f, '# python file') - cmd.byte_compile([f]) - self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'foo.pyc'))) - self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'foo.pyo'))) - - def test_get_outputs(self): - pkg_dir, dist = self.create_dist() - cmd = install_lib(dist) - - # setting up a dist environment - cmd.compile = True - cmd.optimize = 1 - cmd.install_dir = pkg_dir - f = os.path.join(pkg_dir, '__init__.py') - self.write_file(f, '# python package') - cmd.distribution.ext_modules = [Extension('foo', ['xxx'])] - cmd.distribution.packages = [pkg_dir] - - # make sure the build_lib is set the temp dir - build_dir = os.path.split(pkg_dir)[0] - cmd.get_finalized_command('build_py').build_lib = build_dir - - # get_output should return 4 elements - self.assertEqual(len(cmd.get_outputs()), 4) - - def test_get_inputs(self): - pkg_dir, dist = self.create_dist() - cmd = install_lib(dist) - - # setting up a dist environment - cmd.compile = True - cmd.optimize = 1 - cmd.install_dir = pkg_dir - f = os.path.join(pkg_dir, '__init__.py') - self.write_file(f, '# python package') - cmd.distribution.ext_modules = [Extension('foo', ['xxx'])] - cmd.distribution.packages = [pkg_dir] - - # get_input should return 2 elements - self.assertEqual(len(cmd.get_inputs()), 2) - - @unittest.skipUnless(bytecode_support, - 'sys.dont_write_bytecode not supported') - def test_dont_write_bytecode(self): - # makes sure byte_compile is not used - pkg_dir, dist = self.create_dist() - cmd = install_lib(dist) - cmd.compile = True - cmd.optimize = 1 - - self.addCleanup(setattr, sys, 'dont_write_bytecode', - sys.dont_write_bytecode) - sys.dont_write_bytecode = True - cmd.byte_compile([]) - - self.assertIn('byte-compiling is disabled', self.get_logs()[0]) - - -def test_suite(): - return unittest.makeSuite(InstallLibTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_install_scripts.py --- a/Lib/packaging/tests/test_command_install_scripts.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -"""Tests for packaging.command.install_scripts.""" -import os - -from packaging.tests import unittest, support -from packaging.command.install_scripts import install_scripts -from packaging.dist import Distribution - - -class InstallScriptsTestCase(support.TempdirManager, - support.LoggingCatcher, - unittest.TestCase): - - def test_default_settings(self): - dist = Distribution() - dist.command_obj["build"] = support.DummyCommand( - build_scripts="/foo/bar") - dist.command_obj["install_dist"] = support.DummyCommand( - install_scripts="/splat/funk", - force=True, - skip_build=True, - ) - cmd = install_scripts(dist) - self.assertFalse(cmd.force) - self.assertFalse(cmd.skip_build) - self.assertIs(cmd.build_dir, None) - self.assertIs(cmd.install_dir, None) - - cmd.finalize_options() - - self.assertTrue(cmd.force) - self.assertTrue(cmd.skip_build) - self.assertEqual(cmd.build_dir, "/foo/bar") - self.assertEqual(cmd.install_dir, "/splat/funk") - - def test_installation(self): - source = self.mkdtemp() - expected = [] - - def write_script(name, text): - expected.append(name) - with open(os.path.join(source, name), "w") as f: - f.write(text) - - write_script("script1.py", ("#! /usr/bin/env python2.3\n" - "# bogus script w/ Python sh-bang\n" - "pass\n")) - write_script("script2.py", ("#!/usr/bin/python\n" - "# bogus script w/ Python sh-bang\n" - "pass\n")) - write_script("shell.sh", ("#!/bin/sh\n" - "# bogus shell script w/ sh-bang\n" - "exit 0\n")) - - target = self.mkdtemp() - dist = Distribution() - dist.command_obj["build"] = support.DummyCommand(build_scripts=source) - dist.command_obj["install_dist"] = support.DummyCommand( - install_scripts=target, - force=True, - skip_build=True, - ) - cmd = install_scripts(dist) - cmd.finalize_options() - cmd.run() - - installed = os.listdir(target) - for name in expected: - self.assertIn(name, installed) - - -def test_suite(): - return unittest.makeSuite(InstallScriptsTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_register.py --- a/Lib/packaging/tests/test_command_register.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,259 +0,0 @@ -"""Tests for packaging.command.register.""" -import os -import getpass -import urllib.request -import urllib.error -import urllib.parse - -try: - import docutils - DOCUTILS_SUPPORT = True -except ImportError: - DOCUTILS_SUPPORT = False - -from packaging.tests import unittest, support -from packaging.command import register as register_module -from packaging.command.register import register -from packaging.errors import PackagingSetupError - - -PYPIRC_NOPASSWORD = """\ -[distutils] - -index-servers = - server1 - -[server1] -username:me -""" - -WANTED_PYPIRC = """\ -[distutils] -index-servers = - pypi - -[pypi] -username:tarek -password:password -""" - - -class Inputs: - """Fakes user inputs.""" - def __init__(self, *answers): - self.answers = answers - self.index = 0 - - def __call__(self, prompt=''): - try: - return self.answers[self.index] - finally: - self.index += 1 - - -class FakeOpener: - """Fakes a PyPI server""" - def __init__(self): - self.reqs = [] - - def __call__(self, *args): - return self - - def open(self, req): - self.reqs.append(req) - return self - - def read(self): - return 'xxx' - - -class RegisterTestCase(support.TempdirManager, - support.EnvironRestorer, - support.LoggingCatcher, - unittest.TestCase): - - restore_environ = ['HOME'] - - def setUp(self): - super(RegisterTestCase, self).setUp() - self.tmp_dir = self.mkdtemp() - self.rc = os.path.join(self.tmp_dir, '.pypirc') - os.environ['HOME'] = self.tmp_dir - - # patching the password prompt - self._old_getpass = getpass.getpass - - def _getpass(prompt): - return 'password' - - getpass.getpass = _getpass - self.old_opener = urllib.request.build_opener - self.conn = urllib.request.build_opener = FakeOpener() - - def tearDown(self): - getpass.getpass = self._old_getpass - urllib.request.build_opener = self.old_opener - if hasattr(register_module, 'input'): - del register_module.input - super(RegisterTestCase, self).tearDown() - - def _get_cmd(self, metadata=None): - if metadata is None: - metadata = {'url': 'xxx', 'author': 'xxx', - 'author_email': 'xxx', - 'name': 'xxx', 'version': 'xxx'} - pkg_info, dist = self.create_dist(**metadata) - return register(dist) - - def test_create_pypirc(self): - # this test makes sure a .pypirc file - # is created when requested. - - # let's create a register instance - cmd = self._get_cmd() - - # we shouldn't have a .pypirc file yet - self.assertFalse(os.path.exists(self.rc)) - - # patching input and getpass.getpass - # so register gets happy - # Here's what we are faking : - # use your existing login (choice 1.) - # Username : 'tarek' - # Password : 'password' - # Save your login (y/N)? : 'y' - inputs = Inputs('1', 'tarek', 'y') - register_module.input = inputs - cmd.ensure_finalized() - cmd.run() - - # we should have a brand new .pypirc file - self.assertTrue(os.path.exists(self.rc)) - - # with the content similar to WANTED_PYPIRC - with open(self.rc) as fp: - content = fp.read() - self.assertEqual(content, WANTED_PYPIRC) - - # now let's make sure the .pypirc file generated - # really works : we shouldn't be asked anything - # if we run the command again - def _no_way(prompt=''): - raise AssertionError(prompt) - - register_module.input = _no_way - cmd.show_response = True - cmd.ensure_finalized() - cmd.run() - - # let's see what the server received : we should - # have 2 similar requests - self.assertEqual(len(self.conn.reqs), 2) - req1 = dict(self.conn.reqs[0].headers) - req2 = dict(self.conn.reqs[1].headers) - self.assertEqual(req2['Content-length'], req1['Content-length']) - self.assertIn('xxx', self.conn.reqs[1].data) - - def test_password_not_in_file(self): - - self.write_file(self.rc, PYPIRC_NOPASSWORD) - cmd = self._get_cmd() - cmd.finalize_options() - cmd._set_config() - cmd.send_metadata() - - # dist.password should be set - # therefore used afterwards by other commands - self.assertEqual(cmd.distribution.password, 'password') - - def test_registration(self): - # this test runs choice 2 - cmd = self._get_cmd() - inputs = Inputs('2', 'tarek', 'tarek@ziade.org') - register_module.input = inputs - # let's run the command - # FIXME does this send a real request? use a mock server - cmd.ensure_finalized() - cmd.run() - - # we should have send a request - self.assertEqual(len(self.conn.reqs), 1) - req = self.conn.reqs[0] - headers = dict(req.headers) - self.assertEqual(headers['Content-length'], '608') - self.assertIn('tarek', req.data) - - def test_password_reset(self): - # this test runs choice 3 - cmd = self._get_cmd() - inputs = Inputs('3', 'tarek@ziade.org') - register_module.input = inputs - cmd.ensure_finalized() - cmd.run() - - # we should have send a request - self.assertEqual(len(self.conn.reqs), 1) - req = self.conn.reqs[0] - headers = dict(req.headers) - self.assertEqual(headers['Content-length'], '290') - self.assertIn('tarek', req.data) - - @unittest.skipUnless(DOCUTILS_SUPPORT, 'needs docutils') - def test_strict(self): - # testing the script option - # when on, the register command stops if - # the metadata is incomplete or if - # long_description is not reSt compliant - - # empty metadata - cmd = self._get_cmd({'name': 'xxx', 'version': 'xxx'}) - cmd.ensure_finalized() - cmd.strict = True - inputs = Inputs('1', 'tarek', 'y') - register_module.input = inputs - self.assertRaises(PackagingSetupError, cmd.run) - - # metadata is OK but long_description is broken - metadata = {'home_page': 'xxx', 'author': 'xxx', - 'author_email': 'éxéxé', - 'name': 'xxx', 'version': 'xxx', - 'description': 'title\n==\n\ntext'} - - cmd = self._get_cmd(metadata) - cmd.ensure_finalized() - cmd.strict = True - - self.assertRaises(PackagingSetupError, cmd.run) - - # now something that works - metadata['description'] = 'title\n=====\n\ntext' - cmd = self._get_cmd(metadata) - cmd.ensure_finalized() - cmd.strict = True - inputs = Inputs('1', 'tarek', 'y') - register_module.input = inputs - cmd.ensure_finalized() - cmd.run() - - # strict is not by default - cmd = self._get_cmd() - cmd.ensure_finalized() - inputs = Inputs('1', 'tarek', 'y') - register_module.input = inputs - cmd.ensure_finalized() - cmd.run() - - def test_register_pep345(self): - cmd = self._get_cmd({}) - cmd.ensure_finalized() - cmd.distribution.metadata['Requires-Dist'] = ['lxml'] - data = cmd.build_post_data('submit') - self.assertEqual(data['metadata_version'], '1.2') - self.assertEqual(data['requires_dist'], ['lxml']) - - -def test_suite(): - return unittest.makeSuite(RegisterTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_sdist.py --- a/Lib/packaging/tests/test_command_sdist.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,399 +0,0 @@ -"""Tests for packaging.command.sdist.""" -import os -import zipfile -import tarfile -import logging - -from packaging.tests.support import requires_zlib - -try: - import grp - import pwd - UID_GID_SUPPORT = True -except ImportError: - UID_GID_SUPPORT = False - -from os.path import join -from packaging.tests import captured_stdout -from packaging.command.sdist import sdist -from packaging.command.sdist import show_formats -from packaging.dist import Distribution -from packaging.tests import unittest -from packaging.errors import PackagingOptionError -from packaging.util import find_executable -from packaging.tests import support -from shutil import get_archive_formats - - -MANIFEST = """\ -# file GENERATED by packaging, do NOT edit -inroot.txt -setup.cfg -data%(sep)sdata.dt -scripts%(sep)sscript.py -some%(sep)sfile.txt -some%(sep)sother_file.txt -somecode%(sep)s__init__.py -somecode%(sep)sdoc.dat -somecode%(sep)sdoc.txt -""" - - -def builder(dist, filelist): - filelist.append('bah') - - -class SDistTestCase(support.TempdirManager, - support.LoggingCatcher, - support.EnvironRestorer, - unittest.TestCase): - - restore_environ = ['HOME'] - - def setUp(self): - super(SDistTestCase, self).setUp() - self.tmp_dir = self.mkdtemp() - os.environ['HOME'] = self.tmp_dir - # setting up an environment - self.old_path = os.getcwd() - os.mkdir(join(self.tmp_dir, 'somecode')) - os.mkdir(join(self.tmp_dir, 'dist')) - # a package, and a README - self.write_file((self.tmp_dir, 'README'), 'xxx') - self.write_file((self.tmp_dir, 'somecode', '__init__.py'), '#') - os.chdir(self.tmp_dir) - - def tearDown(self): - # back to normal - os.chdir(self.old_path) - super(SDistTestCase, self).tearDown() - - def get_cmd(self, metadata=None): - """Returns a cmd""" - if metadata is None: - metadata = {'name': 'fake', 'version': '1.0', - 'url': 'xxx', 'author': 'xxx', - 'author_email': 'xxx'} - dist = Distribution(metadata) - dist.packages = ['somecode'] - dist.include_package_data = True - cmd = sdist(dist) - cmd.dist_dir = 'dist' - return dist, cmd - - @requires_zlib - def test_prune_file_list(self): - # this test creates a package with some vcs dirs in it - # and launch sdist to make sure they get pruned - # on all systems - - # creating VCS directories with some files in them - os.mkdir(join(self.tmp_dir, 'somecode', '.svn')) - - self.write_file((self.tmp_dir, 'somecode', '.svn', 'ok.py'), 'xxx') - - os.mkdir(join(self.tmp_dir, 'somecode', '.hg')) - self.write_file((self.tmp_dir, 'somecode', '.hg', - 'ok'), 'xxx') - - os.mkdir(join(self.tmp_dir, 'somecode', '.git')) - self.write_file((self.tmp_dir, 'somecode', '.git', - 'ok'), 'xxx') - - # now building a sdist - dist, cmd = self.get_cmd() - - # zip is available universally - # (tar might not be installed under win32) - cmd.formats = ['zip'] - - cmd.ensure_finalized() - cmd.run() - - # now let's check what we have - dist_folder = join(self.tmp_dir, 'dist') - files = os.listdir(dist_folder) - self.assertEqual(files, ['fake-1.0.zip']) - - with zipfile.ZipFile(join(dist_folder, 'fake-1.0.zip')) as zip_file: - content = zip_file.namelist() - - # making sure everything has been pruned correctly - self.assertEqual(len(content), 2) - - @requires_zlib - @unittest.skipIf(find_executable('tar') is None or - find_executable('gzip') is None, - 'requires tar and gzip programs') - def test_make_distribution(self): - # building a sdist - dist, cmd = self.get_cmd() - - # creating a gztar then a tar - cmd.formats = ['gztar', 'tar'] - cmd.ensure_finalized() - cmd.run() - - # making sure we have two files - dist_folder = join(self.tmp_dir, 'dist') - result = sorted(os.listdir(dist_folder)) - self.assertEqual(result, ['fake-1.0.tar', 'fake-1.0.tar.gz']) - - os.remove(join(dist_folder, 'fake-1.0.tar')) - os.remove(join(dist_folder, 'fake-1.0.tar.gz')) - - # now trying a tar then a gztar - cmd.formats = ['tar', 'gztar'] - - cmd.ensure_finalized() - cmd.run() - - result = sorted(os.listdir(dist_folder)) - self.assertEqual(result, ['fake-1.0.tar', 'fake-1.0.tar.gz']) - - @requires_zlib - def test_add_defaults(self): - - # http://bugs.python.org/issue2279 - - # add_default should also include - # data_files and package_data - dist, cmd = self.get_cmd() - - # filling data_files by pointing files - # in package_data - dist.package_data = {'': ['*.cfg', '*.dat'], - 'somecode': ['*.txt']} - self.write_file((self.tmp_dir, 'setup.cfg'), '#') - self.write_file((self.tmp_dir, 'somecode', 'doc.txt'), '#') - self.write_file((self.tmp_dir, 'somecode', 'doc.dat'), '#') - - # adding some data in data_files - data_dir = join(self.tmp_dir, 'data') - os.mkdir(data_dir) - self.write_file((data_dir, 'data.dt'), '#') - some_dir = join(self.tmp_dir, 'some') - os.mkdir(some_dir) - self.write_file((self.tmp_dir, 'inroot.txt'), '#') - self.write_file((some_dir, 'file.txt'), '#') - self.write_file((some_dir, 'other_file.txt'), '#') - - dist.data_files = {'data/data.dt': '{appdata}/data.dt', - 'inroot.txt': '{appdata}/inroot.txt', - 'some/file.txt': '{appdata}/file.txt', - 'some/other_file.txt': '{appdata}/other_file.txt'} - - # adding a script - script_dir = join(self.tmp_dir, 'scripts') - os.mkdir(script_dir) - self.write_file((script_dir, 'script.py'), '#') - dist.scripts = [join('scripts', 'script.py')] - - cmd.formats = ['zip'] - cmd.use_defaults = True - - cmd.ensure_finalized() - cmd.run() - - # now let's check what we have - dist_folder = join(self.tmp_dir, 'dist') - files = os.listdir(dist_folder) - self.assertEqual(files, ['fake-1.0.zip']) - - with zipfile.ZipFile(join(dist_folder, 'fake-1.0.zip')) as zip_file: - content = zip_file.namelist() - - # Making sure everything was added. This includes 8 code and data - # files in addition to PKG-INFO and setup.cfg - self.assertEqual(len(content), 10) - - # Checking the MANIFEST - with open(join(self.tmp_dir, 'MANIFEST')) as fp: - manifest = fp.read() - self.assertEqual(manifest, MANIFEST % {'sep': os.sep}) - - @requires_zlib - def test_metadata_check_option(self): - # testing the `check-metadata` option - dist, cmd = self.get_cmd(metadata={'name': 'xxx', 'version': 'xxx'}) - - # this should raise some warnings - # with the check subcommand - cmd.ensure_finalized() - cmd.run() - warnings = self.get_logs(logging.WARN) - self.assertEqual(len(warnings), 4) - - # trying with a complete set of metadata - self.loghandler.flush() - dist, cmd = self.get_cmd() - cmd.ensure_finalized() - cmd.metadata_check = False - cmd.run() - warnings = self.get_logs(logging.WARN) - # removing manifest generated warnings - warnings = [warn for warn in warnings if - not warn.endswith('-- skipping')] - # the remaining warnings are about the use of the default file list and - # the absence of setup.cfg - self.assertEqual(len(warnings), 2) - - def test_show_formats(self): - __, stdout = captured_stdout(show_formats) - - # the output should be a header line + one line per format - num_formats = len(get_archive_formats()) - output = [line for line in stdout.split('\n') - if line.strip().startswith('--formats=')] - self.assertEqual(len(output), num_formats) - - def test_finalize_options(self): - - dist, cmd = self.get_cmd() - cmd.finalize_options() - - # default options set by finalize - self.assertEqual(cmd.manifest, 'MANIFEST') - self.assertEqual(cmd.dist_dir, 'dist') - - # formats has to be a string splitable on (' ', ',') or - # a stringlist - cmd.formats = 1 - self.assertRaises(PackagingOptionError, cmd.finalize_options) - cmd.formats = ['zip'] - cmd.finalize_options() - - # formats has to be known - cmd.formats = 'supazipa' - self.assertRaises(PackagingOptionError, cmd.finalize_options) - - @requires_zlib - @unittest.skipUnless(UID_GID_SUPPORT, "requires grp and pwd support") - @unittest.skipIf(find_executable('tar') is None or - find_executable('gzip') is None, - 'requires tar and gzip programs') - def test_make_distribution_owner_group(self): - # building a sdist - dist, cmd = self.get_cmd() - - # creating a gztar and specifying the owner+group - cmd.formats = ['gztar'] - cmd.owner = pwd.getpwuid(0)[0] - cmd.group = grp.getgrgid(0)[0] - cmd.ensure_finalized() - cmd.run() - - # making sure we have the good rights - archive_name = join(self.tmp_dir, 'dist', 'fake-1.0.tar.gz') - with tarfile.open(archive_name) as archive: - for member in archive.getmembers(): - self.assertEqual(member.uid, 0) - self.assertEqual(member.gid, 0) - - # building a sdist again - dist, cmd = self.get_cmd() - - # creating a gztar - cmd.formats = ['gztar'] - cmd.ensure_finalized() - cmd.run() - - # making sure we have the good rights - archive_name = join(self.tmp_dir, 'dist', 'fake-1.0.tar.gz') - with tarfile.open(archive_name) as archive: - - # note that we are not testing the group ownership here - # because, depending on the platforms and the container - # rights (see #7408) - for member in archive.getmembers(): - self.assertEqual(member.uid, os.getuid()) - - @requires_zlib - def test_get_file_list(self): - # make sure MANIFEST is recalculated - dist, cmd = self.get_cmd() - # filling data_files by pointing files in package_data - dist.package_data = {'somecode': ['*.txt']} - self.write_file((self.tmp_dir, 'somecode', 'doc.txt'), '#') - cmd.ensure_finalized() - cmd.run() - - # Should produce four lines. Those lines are one comment, one default - # (README) and two package files. - with open(cmd.manifest) as f: - manifest = [line.strip() for line in f.read().split('\n') - if line.strip() != ''] - self.assertEqual(len(manifest), 3) - - # Adding a file - self.write_file((self.tmp_dir, 'somecode', 'doc2.txt'), '#') - - # make sure build_py is reinitialized, like a fresh run - build_py = dist.get_command_obj('build_py') - build_py.finalized = False - build_py.ensure_finalized() - - cmd.run() - - with open(cmd.manifest) as f: - manifest2 = [line.strip() for line in f.read().split('\n') - if line.strip() != ''] - - # Do we have the new file in MANIFEST? - self.assertEqual(len(manifest2), 4) - self.assertIn('doc2.txt', manifest2[-1]) - - @requires_zlib - def test_manifest_marker(self): - # check that autogenerated MANIFESTs have a marker - dist, cmd = self.get_cmd() - cmd.ensure_finalized() - cmd.run() - - with open(cmd.manifest) as f: - manifest = [line.strip() for line in f.read().split('\n') - if line.strip() != ''] - - self.assertEqual(manifest[0], - '# file GENERATED by packaging, do NOT edit') - - @requires_zlib - def test_manual_manifest(self): - # check that a MANIFEST without a marker is left alone - dist, cmd = self.get_cmd() - cmd.ensure_finalized() - self.write_file((self.tmp_dir, cmd.manifest), 'README.manual') - cmd.run() - - with open(cmd.manifest) as f: - manifest = [line.strip() for line in f.read().split('\n') - if line.strip() != ''] - - self.assertEqual(manifest, ['README.manual']) - - @requires_zlib - def test_template(self): - dist, cmd = self.get_cmd() - dist.extra_files = ['include yeah'] - cmd.ensure_finalized() - self.write_file((self.tmp_dir, 'yeah'), 'xxx') - cmd.run() - with open(cmd.manifest) as f: - content = f.read() - - self.assertIn('yeah', content) - - @requires_zlib - def test_manifest_builder(self): - dist, cmd = self.get_cmd() - cmd.manifest_builders = 'packaging.tests.test_command_sdist.builder' - cmd.ensure_finalized() - cmd.run() - self.assertIn('bah', cmd.filelist.files) - - -def test_suite(): - return unittest.makeSuite(SDistTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_test.py --- a/Lib/packaging/tests/test_command_test.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,224 +0,0 @@ -import os -import re -import sys -import shutil -import logging -import unittest as ut1 -import packaging.database - -from os.path import join -from operator import getitem, setitem, delitem -from packaging.command.build import build -from packaging.tests import unittest -from packaging.tests.support import (TempdirManager, EnvironRestorer, - LoggingCatcher) -from packaging.command.test import test -from packaging.command import set_command -from packaging.dist import Distribution - - -EXPECTED_OUTPUT_RE = r'''FAIL: test_blah \(myowntestmodule.SomeTest\) ----------------------------------------------------------------------- -Traceback \(most recent call last\): - File ".+/myowntestmodule.py", line \d+, in test_blah - self.fail\("horribly"\) -AssertionError: horribly -''' - -here = os.path.dirname(os.path.abspath(__file__)) - - -class MockBuildCmd(build): - build_lib = "mock build lib" - command_name = 'build' - plat_name = 'whatever' - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - self._record.append("build has run") - - -class TestTest(TempdirManager, - EnvironRestorer, - LoggingCatcher, - unittest.TestCase): - - restore_environ = ['PYTHONPATH'] - - def setUp(self): - super(TestTest, self).setUp() - self.addCleanup(packaging.database.clear_cache) - new_pythonpath = os.path.dirname(os.path.dirname(here)) - pythonpath = os.environ.get('PYTHONPATH') - if pythonpath is not None: - new_pythonpath = os.pathsep.join((new_pythonpath, pythonpath)) - os.environ['PYTHONPATH'] = new_pythonpath - - def assert_re_match(self, pattern, string): - def quote(s): - lines = ['## ' + line for line in s.split('\n')] - sep = ["#" * 60] - return [''] + sep + lines + sep - msg = quote(pattern) + ["didn't match"] + quote(string) - msg = "\n".join(msg) - if not re.search(pattern, string): - self.fail(msg) - - def prepare_dist(self, dist_name): - pkg_dir = join(os.path.dirname(__file__), "dists", dist_name) - temp_pkg_dir = join(self.mkdtemp(), dist_name) - shutil.copytree(pkg_dir, temp_pkg_dir) - return temp_pkg_dir - - def safely_replace(self, obj, attr, - new_val=None, delete=False, dictionary=False): - """Replace a object's attribute returning to its original state at the - end of the test run. Creates the attribute if not present before - (deleting afterwards). When delete=True, makes sure the value is del'd - for the test run. If dictionary is set to True, operates of its items - rather than attributes.""" - if dictionary: - _setattr, _getattr, _delattr = setitem, getitem, delitem - - def _hasattr(_dict, value): - return value in _dict - else: - _setattr, _getattr, _delattr, _hasattr = (setattr, getattr, - delattr, hasattr) - - orig_has_attr = _hasattr(obj, attr) - if orig_has_attr: - orig_val = _getattr(obj, attr) - - if delete is False: - _setattr(obj, attr, new_val) - elif orig_has_attr: - _delattr(obj, attr) - - def do_cleanup(): - if orig_has_attr: - _setattr(obj, attr, orig_val) - elif _hasattr(obj, attr): - _delattr(obj, attr) - - self.addCleanup(do_cleanup) - - def test_runs_unittest(self): - module_name, a_module = self.prepare_a_module() - record = [] - a_module.recorder = lambda *args: record.append("suite") - - class MockTextTestRunner: - def __init__(*_, **__): - pass - - def run(_self, suite): - record.append("run") - - self.safely_replace(ut1, "TextTestRunner", MockTextTestRunner) - - dist = Distribution() - cmd = test(dist) - cmd.suite = "%s.recorder" % module_name - cmd.run() - self.assertEqual(record, ["suite", "run"]) - - def test_builds_before_running_tests(self): - self.addCleanup(set_command, 'packaging.command.build.build') - set_command('packaging.tests.test_command_test.MockBuildCmd') - - dist = Distribution() - dist.get_command_obj('build')._record = record = [] - cmd = test(dist) - cmd.runner = self.prepare_named_function(lambda: None) - cmd.ensure_finalized() - cmd.run() - self.assertEqual(['build has run'], record) - - def _test_works_with_2to3(self): - pass - - def test_checks_requires(self): - dist = Distribution() - cmd = test(dist) - phony_project = 'ohno_ohno-impossible_1234-name_stop-that!' - cmd.tests_require = [phony_project] - cmd.ensure_finalized() - logs = self.get_logs(logging.WARNING) - self.assertIn(phony_project, logs[-1]) - - def prepare_a_module(self): - tmp_dir = self.mkdtemp() - sys.path.append(tmp_dir) - self.addCleanup(sys.path.remove, tmp_dir) - - self.write_file((tmp_dir, 'packaging_tests_a.py'), '') - import packaging_tests_a as a_module - return "packaging_tests_a", a_module - - def prepare_named_function(self, func): - module_name, a_module = self.prepare_a_module() - a_module.recorder = func - return "%s.recorder" % module_name - - def test_custom_runner(self): - dist = Distribution() - cmd = test(dist) - record = [] - cmd.runner = self.prepare_named_function( - lambda: record.append("runner called")) - cmd.ensure_finalized() - cmd.run() - self.assertEqual(["runner called"], record) - - def prepare_mock_ut2(self): - class MockUTClass: - def __init__(*_, **__): - pass - - def discover(self): - pass - - def run(self, _): - pass - - class MockUTModule: - TestLoader = MockUTClass - TextTestRunner = MockUTClass - - mock_ut2 = MockUTModule() - self.safely_replace(sys.modules, "unittest2", - mock_ut2, dictionary=True) - return mock_ut2 - - def test_gets_unittest_discovery(self): - mock_ut2 = self.prepare_mock_ut2() - dist = Distribution() - cmd = test(dist) - self.safely_replace(ut1.TestLoader, "discover", lambda: None) - self.assertEqual(cmd.get_ut_with_discovery(), ut1) - - del ut1.TestLoader.discover - self.assertEqual(cmd.get_ut_with_discovery(), mock_ut2) - - def test_calls_discover(self): - self.safely_replace(ut1.TestLoader, "discover", delete=True) - mock_ut2 = self.prepare_mock_ut2() - record = [] - mock_ut2.TestLoader.discover = lambda self, path: record.append(path) - dist = Distribution() - cmd = test(dist) - cmd.run() - self.assertEqual([os.curdir], record) - - -def test_suite(): - return unittest.makeSuite(TestTest) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_upload.py --- a/Lib/packaging/tests/test_command_upload.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,163 +0,0 @@ -"""Tests for packaging.command.upload.""" -import os -import sys - -from packaging.command.upload import upload -from packaging.dist import Distribution -from packaging.errors import PackagingOptionError - -from packaging.tests import unittest, support -try: - import threading - from packaging.tests.pypi_server import PyPIServerTestCase -except ImportError: - threading = None - PyPIServerTestCase = unittest.TestCase - - -PYPIRC_NOPASSWORD = """\ -[distutils] - -index-servers = - server1 - -[server1] -username:me -""" - -PYPIRC = """\ -[distutils] - -index-servers = - server1 - server2 - -[server1] -username:me -password:secret - -[server2] -username:meagain -password: secret -realm:acme -repository:http://another.pypi/ -""" - - -@unittest.skipIf(threading is None, 'needs threading') -class UploadTestCase(support.TempdirManager, support.EnvironRestorer, - support.LoggingCatcher, PyPIServerTestCase): - - restore_environ = ['HOME'] - - def setUp(self): - super(UploadTestCase, self).setUp() - self.tmp_dir = self.mkdtemp() - self.rc = os.path.join(self.tmp_dir, '.pypirc') - os.environ['HOME'] = self.tmp_dir - - def test_finalize_options(self): - # new format - self.write_file(self.rc, PYPIRC) - dist = Distribution() - cmd = upload(dist) - cmd.finalize_options() - for attr, expected in (('username', 'me'), ('password', 'secret'), - ('realm', 'pypi'), - ('repository', 'http://pypi.python.org/pypi')): - self.assertEqual(getattr(cmd, attr), expected) - - def test_finalize_options_unsigned_identity_raises_exception(self): - self.write_file(self.rc, PYPIRC) - dist = Distribution() - cmd = upload(dist) - cmd.identity = True - cmd.sign = False - self.assertRaises(PackagingOptionError, cmd.finalize_options) - - def test_saved_password(self): - # file with no password - self.write_file(self.rc, PYPIRC_NOPASSWORD) - - # make sure it passes - dist = Distribution() - cmd = upload(dist) - cmd.ensure_finalized() - self.assertEqual(cmd.password, None) - - # make sure we get it as well, if another command - # initialized it at the dist level - dist.password = 'xxx' - cmd = upload(dist) - cmd.finalize_options() - self.assertEqual(cmd.password, 'xxx') - - def test_upload_without_files_raises_exception(self): - dist = Distribution() - cmd = upload(dist) - self.assertRaises(PackagingOptionError, cmd.run) - - def test_upload(self): - path = os.path.join(self.tmp_dir, 'xxx') - self.write_file(path) - command, pyversion, filename = 'xxx', '3.3', path - dist_files = [(command, pyversion, filename)] - - # lets run it - pkg_dir, dist = self.create_dist(dist_files=dist_files, author='dédé') - cmd = upload(dist) - cmd.ensure_finalized() - cmd.repository = self.pypi.full_address - cmd.run() - - # what did we send ? - handler, request_data = self.pypi.requests[-1] - headers = handler.headers - #self.assertIn('dédé', str(request_data)) - self.assertIn(b'xxx', request_data) - - self.assertEqual(int(headers['content-length']), len(request_data)) - self.assertLess(int(headers['content-length']), 2500) - self.assertTrue(headers['content-type'].startswith('multipart/form-data')) - self.assertEqual(handler.command, 'POST') - self.assertNotIn('\n', headers['authorization']) - - def test_upload_docs(self): - path = os.path.join(self.tmp_dir, 'xxx') - self.write_file(path) - command, pyversion, filename = 'xxx', '3.3', path - dist_files = [(command, pyversion, filename)] - docs_path = os.path.join(self.tmp_dir, "build", "docs") - os.makedirs(docs_path) - self.write_file(os.path.join(docs_path, "index.html"), "yellow") - self.write_file(self.rc, PYPIRC) - - # lets run it - pkg_dir, dist = self.create_dist(dist_files=dist_files, author='dédé') - - cmd = upload(dist) - cmd.get_finalized_command("build").run() - cmd.upload_docs = True - cmd.ensure_finalized() - cmd.repository = self.pypi.full_address - prev_dir = os.getcwd() - try: - os.chdir(self.tmp_dir) - cmd.run() - finally: - os.chdir(prev_dir) - - handler, request_data = self.pypi.requests[-1] - action, name, content = request_data.split( - "----------------GHSKFJDLGDS7543FJKLFHRE75642756743254" - .encode())[1:4] - - self.assertIn(b'name=":action"', action) - self.assertIn(b'doc_upload', action) - - -def test_suite(): - return unittest.makeSuite(UploadTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_command_upload_docs.py --- a/Lib/packaging/tests/test_command_upload_docs.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,217 +0,0 @@ -"""Tests for packaging.command.upload_docs.""" -import os -import sys -import shutil -import zipfile -try: - import _ssl -except ImportError: - _ssl = None - -from packaging.command import upload_docs as upload_docs_mod -from packaging.command.upload_docs import (upload_docs, zip_dir, - encode_multipart) -from packaging.dist import Distribution -from packaging.errors import PackagingFileError, PackagingOptionError - -from packaging.tests import unittest, support -try: - import threading - from packaging.tests.pypi_server import PyPIServerTestCase -except ImportError: - threading = None - PyPIServerTestCase = object - - -EXPECTED_MULTIPART_OUTPUT = [ - b'---x', - b'Content-Disposition: form-data; name="username"', - b'', - b'wok', - b'---x', - b'Content-Disposition: form-data; name="password"', - b'', - b'secret', - b'---x', - b'Content-Disposition: form-data; name="picture"; filename="wok.png"', - b'', - b'PNG89', - b'---x--', - b'', -] - -PYPIRC = """\ -[distutils] -index-servers = server1 - -[server1] -repository = %s -username = real_slim_shady -password = long_island -""" - - -@unittest.skipIf(threading is None, "Needs threading") -class UploadDocsTestCase(support.TempdirManager, - support.EnvironRestorer, - support.LoggingCatcher, - PyPIServerTestCase): - - restore_environ = ['HOME'] - - def setUp(self): - super(UploadDocsTestCase, self).setUp() - self.tmp_dir = self.mkdtemp() - self.rc = os.path.join(self.tmp_dir, '.pypirc') - os.environ['HOME'] = self.tmp_dir - self.dist = Distribution() - self.dist.metadata['Name'] = "distr-name" - self.cmd = upload_docs(self.dist) - - def test_default_uploaddir(self): - sandbox = self.mkdtemp() - previous = os.getcwd() - os.chdir(sandbox) - try: - os.mkdir("build") - self.prepare_sample_dir("build") - self.cmd.ensure_finalized() - self.assertEqual(self.cmd.upload_dir, os.path.join("build", "docs")) - finally: - os.chdir(previous) - - def test_default_uploaddir_looks_for_doc_also(self): - sandbox = self.mkdtemp() - previous = os.getcwd() - os.chdir(sandbox) - try: - os.mkdir("build") - self.prepare_sample_dir("build") - os.rename(os.path.join("build", "docs"), os.path.join("build", "doc")) - self.cmd.ensure_finalized() - self.assertEqual(self.cmd.upload_dir, os.path.join("build", "doc")) - finally: - os.chdir(previous) - - def prepare_sample_dir(self, sample_dir=None): - if sample_dir is None: - sample_dir = self.mkdtemp() - os.mkdir(os.path.join(sample_dir, "docs")) - self.write_file(os.path.join(sample_dir, "docs", "index.html"), "Ce mortel ennui") - self.write_file(os.path.join(sample_dir, "index.html"), "Oh la la") - return sample_dir - - def test_zip_dir(self): - source_dir = self.prepare_sample_dir() - compressed = zip_dir(source_dir) - - zip_f = zipfile.ZipFile(compressed) - self.assertEqual(zip_f.namelist(), ['index.html', 'docs/index.html']) - - def test_encode_multipart(self): - fields = [('username', 'wok'), ('password', 'secret')] - files = [('picture', 'wok.png', b'PNG89')] - content_type, body = encode_multipart(fields, files, b'-x') - self.assertEqual(b'multipart/form-data; boundary=-x', content_type) - self.assertEqual(EXPECTED_MULTIPART_OUTPUT, body.split(b'\r\n')) - - def prepare_command(self): - self.cmd.upload_dir = self.prepare_sample_dir() - self.cmd.ensure_finalized() - self.cmd.repository = self.pypi.full_address - self.cmd.username = "username" - self.cmd.password = "password" - - def test_upload(self): - self.prepare_command() - self.cmd.run() - - self.assertEqual(len(self.pypi.requests), 1) - handler, request_data = self.pypi.requests[-1] - self.assertIn(b"content", request_data) - self.assertIn("Basic", handler.headers['authorization']) - self.assertTrue(handler.headers['content-type'] - .startswith('multipart/form-data;')) - - action, name, version, content =\ - request_data.split("----------------GHSKFJDLGDS7543FJKLFHRE75642756743254".encode())[1:5] - - - # check that we picked the right chunks - self.assertIn(b'name=":action"', action) - self.assertIn(b'name="name"', name) - self.assertIn(b'name="version"', version) - self.assertIn(b'name="content"', content) - - # check their contents - self.assertIn(b'doc_upload', action) - self.assertIn(b'distr-name', name) - self.assertIn(b'docs/index.html', content) - self.assertIn(b'Ce mortel ennui', content) - - @unittest.skipIf(_ssl is None, 'Needs SSL support') - def test_https_connection(self): - https_called = False - - orig_https = upload_docs_mod.http.client.HTTPSConnection - - def https_conn_wrapper(*args): - nonlocal https_called - https_called = True - # the testing server is http - return upload_docs_mod.http.client.HTTPConnection(*args) - - upload_docs_mod.http.client.HTTPSConnection = https_conn_wrapper - try: - self.prepare_command() - self.cmd.run() - self.assertFalse(https_called) - - self.cmd.repository = self.cmd.repository.replace("http", "https") - self.cmd.run() - self.assertTrue(https_called) - finally: - upload_docs_mod.http.client.HTTPSConnection = orig_https - - def test_handling_response(self): - self.pypi.default_response_status = '403 Forbidden' - self.prepare_command() - self.cmd.run() - self.assertIn('Upload failed (403): Forbidden', self.get_logs()[-1]) - - self.pypi.default_response_status = '301 Moved Permanently' - self.pypi.default_response_headers.append(("Location", "brand_new_location")) - self.cmd.run() - self.assertIn('brand_new_location', self.get_logs()[-1]) - - def test_reads_pypirc_data(self): - self.write_file(self.rc, PYPIRC % self.pypi.full_address) - self.cmd.repository = self.pypi.full_address - self.cmd.upload_dir = self.prepare_sample_dir() - self.cmd.ensure_finalized() - self.assertEqual(self.cmd.username, "real_slim_shady") - self.assertEqual(self.cmd.password, "long_island") - - def test_checks_index_html_presence(self): - self.cmd.upload_dir = self.prepare_sample_dir() - os.remove(os.path.join(self.cmd.upload_dir, "index.html")) - self.assertRaises(PackagingFileError, self.cmd.ensure_finalized) - - def test_checks_upload_dir(self): - self.cmd.upload_dir = self.prepare_sample_dir() - shutil.rmtree(os.path.join(self.cmd.upload_dir)) - self.assertRaises(PackagingOptionError, self.cmd.ensure_finalized) - - def test_show_response(self): - self.prepare_command() - self.cmd.show_response = True - self.cmd.run() - record = self.get_logs()[-1] - self.assertTrue(record, "should report the response") - self.assertIn(self.pypi.default_response_data, record) - -def test_suite(): - return unittest.makeSuite(UploadDocsTestCase) - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_compiler.py --- a/Lib/packaging/tests/test_compiler.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -"""Tests for distutils.compiler.""" -import os - -from packaging.compiler import (get_default_compiler, customize_compiler, - gen_lib_options) -from packaging.tests import unittest, support - - -class FakeCompiler: - - name = 'fake' - description = 'Fake' - - def library_dir_option(self, dir): - return "-L" + dir - - def runtime_library_dir_option(self, dir): - return ["-cool", "-R" + dir] - - def find_library_file(self, dirs, lib, debug=False): - return 'found' - - def library_option(self, lib): - return "-l" + lib - - -class CompilerTestCase(support.EnvironRestorer, unittest.TestCase): - - restore_environ = ['AR', 'ARFLAGS'] - - @unittest.skipUnless(get_default_compiler() == 'unix', - 'irrelevant if default compiler is not unix') - def test_customize_compiler(self): - - os.environ['AR'] = 'my_ar' - os.environ['ARFLAGS'] = '-arflags' - - # make sure AR gets caught - class compiler: - name = 'unix' - - def set_executables(self, **kw): - self.exes = kw - - comp = compiler() - customize_compiler(comp) - self.assertEqual(comp.exes['archiver'], 'my_ar -arflags') - - def test_gen_lib_options(self): - compiler = FakeCompiler() - libdirs = ['lib1', 'lib2'] - runlibdirs = ['runlib1'] - libs = [os.path.join('dir', 'name'), 'name2'] - - opts = gen_lib_options(compiler, libdirs, runlibdirs, libs) - wanted = ['-Llib1', '-Llib2', '-cool', '-Rrunlib1', 'found', - '-lname2'] - self.assertEqual(opts, wanted) - - -def test_suite(): - return unittest.makeSuite(CompilerTestCase) - - -if __name__ == "__main__": - unittest.main(defaultTest="test_suite") diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_config.py --- a/Lib/packaging/tests/test_config.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,431 +0,0 @@ -"""Tests for packaging.config.""" -import os -import sys -import logging -from io import StringIO - -from packaging import command -from packaging.dist import Distribution -from packaging.errors import PackagingFileError -from packaging.compiler import new_compiler, _COMPILERS -from packaging.command.sdist import sdist - -from packaging.tests import unittest, support -from packaging.tests.support import requires_zlib - - -SETUP_CFG = """ -[metadata] -name = RestingParrot -version = 0.6.4 -author = Carl Meyer -author_email = carl@oddbird.net -maintainer = Éric Araujo -maintainer_email = merwok@netwok.org -summary = A sample project demonstrating packaging -description-file = %(description-file)s -keywords = packaging, sample project - -classifier = - Development Status :: 4 - Beta - Environment :: Console (Text Based) - Environment :: X11 Applications :: GTK; python_version < '3' - License :: OSI Approved :: MIT License - Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 3 - -requires_python = >=2.4, <3.2 - -requires_dist = - PetShoppe - MichaelPalin (> 1.1) - pywin32; sys.platform == 'win32' - pysqlite2; python_version < '2.5' - inotify (0.0.1); sys.platform == 'linux2' - -requires_external = libxml2 - -provides_dist = packaging-sample-project (0.2) - unittest2-sample-project - -project_url = - Main repository, http://bitbucket.org/carljm/sample-distutils2-project - Fork in progress, http://bitbucket.org/Merwok/sample-distutils2-project - -[files] -packages_root = src - -packages = one - two - three - -modules = haven - -scripts = - script1.py - scripts/find-coconuts - bin/taunt - -package_data = - cheese = data/templates/* - -extra_files = %(extra-files)s - -# Replaces MANIFEST.in -sdist_extra = - include THANKS HACKING - recursive-include examples *.txt *.py - prune examples/sample?/build - -resources= - bm/ {b1,b2}.gif = {icon} - Cf*/ *.CFG = {config}/baBar/ - init_script = {script}/JunGle/ - -[global] -commands = - packaging.tests.test_config.FooBarBazTest - -compilers = - packaging.tests.test_config.DCompiler - -setup_hook = %(setup-hook)s - - - -[install_dist] -sub_commands = foo -""" - -# Can not be merged with SETUP_CFG else install_dist -# command will fail when trying to compile C sources -EXT_SETUP_CFG = """ -[files] -packages = one - two - -[extension=speed_coconuts] -name = one.speed_coconuts -sources = c_src/speed_coconuts.c -extra_link_args = "`gcc -print-file-name=libgcc.a`" -shared -define_macros = HAVE_CAIRO HAVE_GTK2 -libraries = gecodeint gecodekernel -- sys.platform != 'win32' - GecodeInt GecodeKernel -- sys.platform == 'win32' - -[extension=fast_taunt] -name = two.fast_taunt -sources = cxx_src/utils_taunt.cxx - cxx_src/python_module.cxx -include_dirs = /usr/include/gecode - /usr/include/blitz -extra_compile_args = -fPIC -O2 - -DGECODE_VERSION=$(./gecode_version) -- sys.platform != 'win32' - /DGECODE_VERSION='win32' -- sys.platform == 'win32' -language = cxx - -""" - - -class DCompiler: - name = 'd' - description = 'D Compiler' - - def __init__(self, *args): - pass - - -def hook(content): - content['metadata']['version'] += '.dev1' - - -class FooBarBazTest: - - def __init__(self, dist): - self.distribution = dist - - @classmethod - def get_command_name(cls): - return 'foo' - - def run(self): - self.distribution.foo_was_here = True - - def nothing(self): - pass - - def get_source_files(self): - return [] - - ensure_finalized = finalize_options = initialize_options = nothing - - -class ConfigTestCase(support.TempdirManager, - support.EnvironRestorer, - support.LoggingCatcher, - unittest.TestCase): - - restore_environ = ['PLAT'] - - def setUp(self): - super(ConfigTestCase, self).setUp() - self.addCleanup(setattr, sys, 'stdout', sys.stdout) - self.addCleanup(setattr, sys, 'stderr', sys.stderr) - sys.stdout = StringIO() - sys.stderr = StringIO() - - self.addCleanup(os.chdir, os.getcwd()) - tempdir = self.mkdtemp() - self.working_dir = os.getcwd() - os.chdir(tempdir) - self.tempdir = tempdir - - def tearDown(self): - os.chdir(self.working_dir) - super(ConfigTestCase, self).tearDown() - - def write_setup(self, kwargs=None): - opts = {'description-file': 'README', 'extra-files': '', - 'setup-hook': 'packaging.tests.test_config.hook'} - if kwargs: - opts.update(kwargs) - self.write_file('setup.cfg', SETUP_CFG % opts, encoding='utf-8') - - def get_dist(self): - dist = Distribution() - dist.parse_config_files() - return dist - - def test_config(self): - self.write_setup() - self.write_file('README', 'yeah') - os.mkdir('bm') - self.write_file(('bm', 'b1.gif'), '') - self.write_file(('bm', 'b2.gif'), '') - os.mkdir('Cfg') - self.write_file(('Cfg', 'data.CFG'), '') - self.write_file('init_script', '') - - # try to load the metadata now - dist = self.get_dist() - - # check what was done - self.assertEqual(dist.metadata['Author'], 'Carl Meyer') - self.assertEqual(dist.metadata['Author-Email'], 'carl@oddbird.net') - - # the hook adds .dev1 - self.assertEqual(dist.metadata['Version'], '0.6.4.dev1') - - wanted = [ - 'Development Status :: 4 - Beta', - 'Environment :: Console (Text Based)', - "Environment :: X11 Applications :: GTK; python_version < '3'", - 'License :: OSI Approved :: MIT License', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 3'] - self.assertEqual(dist.metadata['Classifier'], wanted) - - wanted = ['packaging', 'sample project'] - self.assertEqual(dist.metadata['Keywords'], wanted) - - self.assertEqual(dist.metadata['Requires-Python'], '>=2.4, <3.2') - - wanted = ['PetShoppe', - 'MichaelPalin (> 1.1)', - "pywin32; sys.platform == 'win32'", - "pysqlite2; python_version < '2.5'", - "inotify (0.0.1); sys.platform == 'linux2'"] - - self.assertEqual(dist.metadata['Requires-Dist'], wanted) - urls = [('Main repository', - 'http://bitbucket.org/carljm/sample-distutils2-project'), - ('Fork in progress', - 'http://bitbucket.org/Merwok/sample-distutils2-project')] - self.assertEqual(dist.metadata['Project-Url'], urls) - - self.assertEqual(dist.packages, ['one', 'two', 'three']) - self.assertEqual(dist.py_modules, ['haven']) - self.assertEqual(dist.package_data, {'cheese': 'data/templates/*'}) - self.assertEqual( - {'bm/b1.gif': '{icon}/b1.gif', - 'bm/b2.gif': '{icon}/b2.gif', - 'Cfg/data.CFG': '{config}/baBar/data.CFG', - 'init_script': '{script}/JunGle/init_script'}, - dist.data_files) - - self.assertEqual(dist.package_dir, 'src') - - # Make sure we get the foo command loaded. We use a string comparison - # instead of assertIsInstance because the class is not the same when - # this test is run directly: foo is packaging.tests.test_config.Foo - # because get_command_class uses the full name, but a bare "Foo" in - # this file would be __main__.Foo when run as "python test_config.py". - # The name FooBarBazTest should be unique enough to prevent - # collisions. - self.assertEqual('FooBarBazTest', - dist.get_command_obj('foo').__class__.__name__) - - # did the README got loaded ? - self.assertEqual(dist.metadata['description'], 'yeah') - - # do we have the D Compiler enabled ? - self.assertIn('d', _COMPILERS) - d = new_compiler(compiler='d') - self.assertEqual(d.description, 'D Compiler') - - def test_multiple_description_file(self): - self.write_setup({'description-file': 'README CHANGES'}) - self.write_file('README', 'yeah') - self.write_file('CHANGES', 'changelog2') - dist = self.get_dist() - self.assertEqual(dist.metadata.requires_files, ['README', 'CHANGES']) - - def test_multiline_description_file(self): - self.write_setup({'description-file': 'README\n CHANGES'}) - self.write_file('README', 'yeah') - self.write_file('CHANGES', 'changelog') - dist = self.get_dist() - self.assertEqual(dist.metadata['description'], 'yeah\nchangelog') - self.assertEqual(dist.metadata.requires_files, ['README', 'CHANGES']) - - def test_parse_extensions_in_config(self): - self.write_file('setup.cfg', EXT_SETUP_CFG) - dist = self.get_dist() - - ext_modules = dict((mod.name, mod) for mod in dist.ext_modules) - self.assertEqual(len(ext_modules), 2) - ext = ext_modules.get('one.speed_coconuts') - self.assertEqual(ext.sources, ['c_src/speed_coconuts.c']) - self.assertEqual(ext.define_macros, ['HAVE_CAIRO', 'HAVE_GTK2']) - libs = ['gecodeint', 'gecodekernel'] - if sys.platform == 'win32': - libs = ['GecodeInt', 'GecodeKernel'] - self.assertEqual(ext.libraries, libs) - self.assertEqual(ext.extra_link_args, - ['`gcc -print-file-name=libgcc.a`', '-shared']) - - ext = ext_modules.get('two.fast_taunt') - self.assertEqual(ext.sources, - ['cxx_src/utils_taunt.cxx', 'cxx_src/python_module.cxx']) - self.assertEqual(ext.include_dirs, - ['/usr/include/gecode', '/usr/include/blitz']) - cargs = ['-fPIC', '-O2'] - if sys.platform == 'win32': - cargs.append("/DGECODE_VERSION=win32") - else: - cargs.append('-DGECODE_VERSION=$(./gecode_version)') - self.assertEqual(ext.extra_compile_args, cargs) - self.assertEqual(ext.language, 'cxx') - - def test_missing_setuphook_warns(self): - self.write_setup({'setup-hook': 'this.does._not.exist'}) - self.write_file('README', 'yeah') - dist = self.get_dist() - logs = self.get_logs(logging.WARNING) - self.assertEqual(1, len(logs)) - self.assertIn('could not import setup_hook', logs[0]) - - def test_metadata_requires_description_files_missing(self): - self.write_setup({'description-file': 'README\n README2'}) - self.write_file('README', 'yeah') - self.write_file('README2', 'yeah') - os.mkdir('src') - self.write_file(('src', 'haven.py'), '#') - self.write_file('script1.py', '#') - os.mkdir('scripts') - self.write_file(('scripts', 'find-coconuts'), '#') - os.mkdir('bin') - self.write_file(('bin', 'taunt'), '#') - - for pkg in ('one', 'two', 'three'): - pkg = os.path.join('src', pkg) - os.mkdir(pkg) - self.write_file((pkg, '__init__.py'), '#') - - dist = self.get_dist() - cmd = sdist(dist) - cmd.finalize_options() - cmd.get_file_list() - self.assertRaises(PackagingFileError, cmd.make_distribution) - - @requires_zlib - def test_metadata_requires_description_files(self): - # Create the following file structure: - # README - # README2 - # script1.py - # scripts/ - # find-coconuts - # bin/ - # taunt - # src/ - # haven.py - # one/__init__.py - # two/__init__.py - # three/__init__.py - - self.write_setup({'description-file': 'README\n README2', - 'extra-files': '\n README3'}) - self.write_file('README', 'yeah 1') - self.write_file('README2', 'yeah 2') - self.write_file('README3', 'yeah 3') - os.mkdir('src') - self.write_file(('src', 'haven.py'), '#') - self.write_file('script1.py', '#') - os.mkdir('scripts') - self.write_file(('scripts', 'find-coconuts'), '#') - os.mkdir('bin') - self.write_file(('bin', 'taunt'), '#') - - for pkg in ('one', 'two', 'three'): - pkg = os.path.join('src', pkg) - os.mkdir(pkg) - self.write_file((pkg, '__init__.py'), '#') - - dist = self.get_dist() - self.assertIn('yeah 1\nyeah 2', dist.metadata['description']) - - cmd = sdist(dist) - cmd.finalize_options() - cmd.get_file_list() - self.assertRaises(PackagingFileError, cmd.make_distribution) - - self.write_setup({'description-file': 'README\n README2', - 'extra-files': '\n README2\n README'}) - dist = self.get_dist() - cmd = sdist(dist) - cmd.finalize_options() - cmd.get_file_list() - cmd.make_distribution() - with open('MANIFEST') as fp: - self.assertIn('README\nREADME2\n', fp.read()) - - def test_sub_commands(self): - self.write_setup() - self.write_file('README', 'yeah') - os.mkdir('src') - self.write_file(('src', 'haven.py'), '#') - self.write_file('script1.py', '#') - os.mkdir('scripts') - self.write_file(('scripts', 'find-coconuts'), '#') - os.mkdir('bin') - self.write_file(('bin', 'taunt'), '#') - - for pkg in ('one', 'two', 'three'): - pkg = os.path.join('src', pkg) - os.mkdir(pkg) - self.write_file((pkg, '__init__.py'), '#') - - # try to run the install command to see if foo is called - dist = self.get_dist() - self.assertIn('foo', command.get_command_names()) - self.assertEqual('FooBarBazTest', - dist.get_command_obj('foo').__class__.__name__) - - -def test_suite(): - return unittest.makeSuite(ConfigTestCase) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_create.py --- a/Lib/packaging/tests/test_create.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,243 +0,0 @@ -"""Tests for packaging.create.""" -import io -import os -import sys -import sysconfig -from textwrap import dedent -from packaging.create import MainProgram, ask_yn, ask, main - -from packaging.tests import support, unittest - - -class CreateTestCase(support.TempdirManager, - support.EnvironRestorer, - unittest.TestCase): - - maxDiff = None - restore_environ = ['PLAT'] - - def setUp(self): - super(CreateTestCase, self).setUp() - self._stdin = sys.stdin # TODO use Inputs - self._stdout = sys.stdout - sys.stdin = io.StringIO() - sys.stdout = io.StringIO() - self._cwd = os.getcwd() - self.wdir = self.mkdtemp() - os.chdir(self.wdir) - # patch sysconfig - self._old_get_paths = sysconfig.get_paths - sysconfig.get_paths = lambda *args, **kwargs: { - 'man': sys.prefix + '/share/man', - 'doc': sys.prefix + '/share/doc/pyxfoil', } - - def tearDown(self): - sys.stdin = self._stdin - sys.stdout = self._stdout - os.chdir(self._cwd) - sysconfig.get_paths = self._old_get_paths - super(CreateTestCase, self).tearDown() - - def test_ask_yn(self): - sys.stdin.write('y\n') - sys.stdin.seek(0) - self.assertEqual('y', ask_yn('is this a test')) - - def test_ask(self): - sys.stdin.write('a\n') - sys.stdin.write('b\n') - sys.stdin.seek(0) - self.assertEqual('a', ask('is this a test')) - self.assertEqual('b', ask(str(list(range(0, 70))), default='c', - lengthy=True)) - - def test_set_multi(self): - mainprogram = MainProgram() - sys.stdin.write('aaaaa\n') - sys.stdin.seek(0) - mainprogram.data['author'] = [] - mainprogram._set_multi('_set_multi test', 'author') - self.assertEqual(['aaaaa'], mainprogram.data['author']) - - def test_find_files(self): - # making sure we scan a project dir correctly - mainprogram = MainProgram() - - # building the structure - tempdir = self.wdir - dirs = ['pkg1', 'data', 'pkg2', 'pkg2/sub'] - files = [ - 'README', - 'data/data1', - 'foo.py', - 'pkg1/__init__.py', - 'pkg1/bar.py', - 'pkg2/__init__.py', - 'pkg2/sub/__init__.py', - ] - - for dir_ in dirs: - os.mkdir(os.path.join(tempdir, dir_)) - - for file_ in files: - path = os.path.join(tempdir, file_) - self.write_file(path, 'xxx') - - mainprogram._find_files() - mainprogram.data['packages'].sort() - - # do we have what we want? - self.assertEqual(mainprogram.data['packages'], - ['pkg1', 'pkg2', 'pkg2.sub']) - self.assertEqual(mainprogram.data['modules'], ['foo']) - data_fn = os.path.join('data', 'data1') - self.assertEqual(mainprogram.data['extra_files'], - ['README', data_fn]) - - def test_convert_setup_py_to_cfg(self): - self.write_file((self.wdir, 'setup.py'), - dedent(""" - # coding: utf-8 - from distutils.core import setup - - long_description = '''My super Death-scription - barbar is now on the public domain, - ho, baby !''' - - setup(name='pyxfoil', - version='0.2', - description='Python bindings for the Xfoil engine', - long_description=long_description, - maintainer='André Espaze', - maintainer_email='andre.espaze@logilab.fr', - url='http://www.python-science.org/project/pyxfoil', - license='GPLv2', - packages=['pyxfoil', 'babar', 'me'], - data_files=[ - ('share/doc/pyxfoil', ['README.rst']), - ('share/man', ['pyxfoil.1']), - ], - py_modules=['my_lib', 'mymodule'], - package_dir={ - 'babar': '', - 'me': 'Martinique/Lamentin', - }, - package_data={ - 'babar': ['Pom', 'Flora', 'Alexander'], - 'me': ['dady', 'mumy', 'sys', 'bro'], - '': ['setup.py', 'README'], - 'pyxfoil': ['fengine.so'], - }, - scripts=['my_script', 'bin/run'], - ) - """), encoding='utf-8') - sys.stdin.write('y\n') - sys.stdin.seek(0) - main() - - with open(os.path.join(self.wdir, 'setup.cfg'), encoding='utf-8') as fp: - contents = fp.read() - - self.assertEqual(contents, dedent("""\ - [metadata] - name = pyxfoil - version = 0.2 - summary = Python bindings for the Xfoil engine - download_url = UNKNOWN - home_page = http://www.python-science.org/project/pyxfoil - maintainer = André Espaze - maintainer_email = andre.espaze@logilab.fr - description = My super Death-scription - |barbar is now on the public domain, - |ho, baby ! - - [files] - packages = pyxfoil - babar - me - modules = my_lib - mymodule - scripts = my_script - bin/run - extra_files = Martinique/Lamentin/dady - Martinique/Lamentin/mumy - Martinique/Lamentin/sys - Martinique/Lamentin/bro - setup.py - README - Pom - Flora - Alexander - pyxfoil/fengine.so - - resources = - README.rst = {doc} - pyxfoil.1 = {man} - - """)) - - def test_convert_setup_py_to_cfg_with_description_in_readme(self): - self.write_file((self.wdir, 'setup.py'), - dedent(""" - # coding: utf-8 - from distutils.core import setup - with open('README.txt') as fp: - long_description = fp.read() - - setup(name='pyxfoil', - version='0.2', - description='Python bindings for the Xfoil engine', - long_description=long_description, - maintainer='André Espaze', - maintainer_email='andre.espaze@logilab.fr', - url='http://www.python-science.org/project/pyxfoil', - license='GPLv2', - packages=['pyxfoil'], - package_data={'pyxfoil': ['fengine.so', 'babar.so']}, - data_files=[ - ('share/doc/pyxfoil', ['README.rst']), - ('share/man', ['pyxfoil.1']), - ], - ) - """), encoding='utf-8') - self.write_file((self.wdir, 'README.txt'), - dedent(''' -My super Death-scription -barbar is now in the public domain, -ho, baby! - ''')) - sys.stdin.write('y\n') - sys.stdin.seek(0) - # FIXME Out of memory error. - main() - with open(os.path.join(self.wdir, 'setup.cfg'), encoding='utf-8') as fp: - contents = fp.read() - - self.assertEqual(contents, dedent("""\ - [metadata] - name = pyxfoil - version = 0.2 - summary = Python bindings for the Xfoil engine - download_url = UNKNOWN - home_page = http://www.python-science.org/project/pyxfoil - maintainer = André Espaze - maintainer_email = andre.espaze@logilab.fr - description-file = README.txt - - [files] - packages = pyxfoil - extra_files = pyxfoil/fengine.so - pyxfoil/babar.so - - resources = - README.rst = {doc} - pyxfoil.1 = {man} - - """)) - - -def test_suite(): - return unittest.makeSuite(CreateTestCase) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_cygwinccompiler.py --- a/Lib/packaging/tests/test_cygwinccompiler.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -"""Tests for packaging.cygwinccompiler.""" -import os -import sys -import sysconfig -from packaging.compiler.cygwinccompiler import ( - check_config_h, get_msvcr, - CONFIG_H_OK, CONFIG_H_NOTOK, CONFIG_H_UNCERTAIN) - -from packaging.tests import unittest, support - - -class CygwinCCompilerTestCase(support.TempdirManager, - unittest.TestCase): - - def setUp(self): - super(CygwinCCompilerTestCase, self).setUp() - self.version = sys.version - self.python_h = os.path.join(self.mkdtemp(), 'python.h') - self.old_get_config_h_filename = sysconfig.get_config_h_filename - sysconfig.get_config_h_filename = self._get_config_h_filename - - def tearDown(self): - sys.version = self.version - sysconfig.get_config_h_filename = self.old_get_config_h_filename - super(CygwinCCompilerTestCase, self).tearDown() - - def _get_config_h_filename(self): - return self.python_h - - def test_check_config_h(self): - # check_config_h looks for "GCC" in sys.version first - # returns CONFIG_H_OK if found - sys.version = ('2.6.1 (r261:67515, Dec 6 2008, 16:42:21) \n[GCC ' - '4.0.1 (Apple Computer, Inc. build 5370)]') - - self.assertEqual(check_config_h()[0], CONFIG_H_OK) - - # then it tries to see if it can find "__GNUC__" in pyconfig.h - sys.version = 'something without the *CC word' - - # if the file doesn't exist it returns CONFIG_H_UNCERTAIN - self.assertEqual(check_config_h()[0], CONFIG_H_UNCERTAIN) - - # if it exists but does not contain __GNUC__, it returns CONFIG_H_NOTOK - self.write_file(self.python_h, 'xxx') - self.assertEqual(check_config_h()[0], CONFIG_H_NOTOK) - - # and CONFIG_H_OK if __GNUC__ is found - self.write_file(self.python_h, 'xxx __GNUC__ xxx') - self.assertEqual(check_config_h()[0], CONFIG_H_OK) - - def test_get_msvcr(self): - # none - sys.version = ('2.6.1 (r261:67515, Dec 6 2008, 16:42:21) ' - '\n[GCC 4.0.1 (Apple Computer, Inc. build 5370)]') - self.assertEqual(get_msvcr(), None) - - # MSVC 7.0 - sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) ' - '[MSC v.1300 32 bits (Intel)]') - self.assertEqual(get_msvcr(), ['msvcr70']) - - # MSVC 7.1 - sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) ' - '[MSC v.1310 32 bits (Intel)]') - self.assertEqual(get_msvcr(), ['msvcr71']) - - # VS2005 / MSVC 8.0 - sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) ' - '[MSC v.1400 32 bits (Intel)]') - self.assertEqual(get_msvcr(), ['msvcr80']) - - # VS2008 / MSVC 9.0 - sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) ' - '[MSC v.1500 32 bits (Intel)]') - self.assertEqual(get_msvcr(), ['msvcr90']) - - # unknown - sys.version = ('2.5.1 (r251:54863, Apr 18 2007, 08:51:08) ' - '[MSC v.1999 32 bits (Intel)]') - self.assertRaises(ValueError, get_msvcr) - - -def test_suite(): - return unittest.makeSuite(CygwinCCompilerTestCase) - -if __name__ == '__main__': - unittest.main(defaultTest='test_suite') diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_database.py --- a/Lib/packaging/tests/test_database.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,668 +0,0 @@ -import os -import io -import csv -import sys -import shutil -import tempfile -from os.path import relpath # separate import for backport concerns -from hashlib import md5 -from textwrap import dedent - -from packaging.tests.test_util import GlobTestCaseBase -from packaging.tests.support import requires_zlib - -from packaging.config import get_resources_dests -from packaging.errors import PackagingError -from packaging.metadata import Metadata -from packaging.tests import unittest, support -from packaging.database import ( - Distribution, EggInfoDistribution, get_distribution, get_distributions, - provides_distribution, obsoletes_distribution, get_file_users, - enable_cache, disable_cache, distinfo_dirname, _yield_distributions, - get_file, get_file_path) - -# TODO Add a test for getting a distribution provided by another distribution -# TODO Add a test for absolute pathed RECORD items (e.g. /etc/myapp/config.ini) -# TODO Add tests from the former pep376 project (zipped site-packages, etc.) - - -def get_hexdigest(filename): - with open(filename, 'rb') as file: - checksum = md5(file.read()) - return checksum.hexdigest() - - -def record_pieces(file): - path = relpath(file, sys.prefix) - digest = get_hexdigest(file) - size = os.path.getsize(file) - return [path, digest, size] - - -class CommonDistributionTests: - """Mixin used to test the interface common to both Distribution classes. - - Derived classes define cls, sample_dist, dirs and records. These - attributes are used in test methods. See source code for details. - """ - - def setUp(self): - super(CommonDistributionTests, self).setUp() - self.addCleanup(enable_cache) - disable_cache() - self.fake_dists_path = os.path.abspath( - os.path.join(os.path.dirname(__file__), 'fake_dists')) - - def test_instantiation(self): - # check that useful attributes are here - name, version, distdir = self.sample_dist - here = os.path.abspath(os.path.dirname(__file__)) - dist_path = os.path.join(here, 'fake_dists', distdir) - - dist = self.dist = self.cls(dist_path) - self.assertEqual(dist.path, dist_path) - self.assertEqual(dist.name, name) - self.assertEqual(dist.metadata['Name'], name) - self.assertIsInstance(dist.metadata, Metadata) - self.assertEqual(dist.version, version) - self.assertEqual(dist.metadata['Version'], version) - - @requires_zlib - def test_repr(self): - dist = self.cls(self.dirs[0]) - # just check that the class name is in the repr - self.assertIn(self.cls.__name__, repr(dist)) - - @requires_zlib - def test_comparison(self): - # tests for __eq__ and __hash__ - dist = self.cls(self.dirs[0]) - dist2 = self.cls(self.dirs[0]) - dist3 = self.cls(self.dirs[1]) - self.assertIn(dist, {dist: True}) - self.assertEqual(dist, dist) - - self.assertIsNot(dist, dist2) - self.assertEqual(dist, dist2) - self.assertNotEqual(dist, dist3) - self.assertNotEqual(dist, ()) - - def test_list_installed_files(self): - for dir_ in self.dirs: - dist = self.cls(dir_) - for path, md5_, size in dist.list_installed_files(): - record_data = self.records[dist.path] - self.assertIn(path, record_data) - self.assertEqual(md5_, record_data[path][0]) - self.assertEqual(size, record_data[path][1]) - - -class TestDistribution(CommonDistributionTests, unittest.TestCase): - - cls = Distribution - sample_dist = 'choxie', '2.0.0.9', 'choxie-2.0.0.9.dist-info' - - def setUp(self): - super(TestDistribution, self).setUp() - self.dirs = [os.path.join(self.fake_dists_path, f) - for f in os.listdir(self.fake_dists_path) - if f.endswith('.dist-info')] - - self.records = {} - for distinfo_dir in self.dirs: - record_file = os.path.join(distinfo_dir, 'RECORD') - with open(record_file, 'w') as file: - record_writer = csv.writer( - file, delimiter=',', quoting=csv.QUOTE_NONE, - lineterminator='\n') - - dist_location = distinfo_dir.replace('.dist-info', '') - - for path, dirs, files in os.walk(dist_location): - for f in files: - record_writer.writerow(record_pieces( - os.path.join(path, f))) - for file in ('INSTALLER', 'METADATA', 'REQUESTED'): - record_writer.writerow(record_pieces( - os.path.join(distinfo_dir, file))) - record_writer.writerow([relpath(record_file, sys.prefix)]) - - with open(record_file) as file: - record_reader = csv.reader(file, lineterminator='\n') - record_data = {} - for row in record_reader: - if row == []: - continue - path, md5_, size = (row[:] + - [None for i in range(len(row), 3)]) - record_data[path] = md5_, size - self.records[distinfo_dir] = record_data - - def tearDown(self): - for distinfo_dir in self.dirs: - record_file = os.path.join(distinfo_dir, 'RECORD') - open(record_file, 'wb').close() - super(TestDistribution, self).tearDown() - - def test_instantiation(self): - super(TestDistribution, self).test_instantiation() - self.assertIsInstance(self.dist.requested, bool) - - def test_uses(self): - # Test to determine if a distribution uses a specified file. - # Criteria to test against - distinfo_name = 'grammar-1.0a4' - distinfo_dir = os.path.join(self.fake_dists_path, - distinfo_name + '.dist-info') - true_path = [self.fake_dists_path, distinfo_name, - 'grammar', 'utils.py'] - true_path = relpath(os.path.join(*true_path), sys.prefix) - false_path = [self.fake_dists_path, 'towel_stuff-0.1', 'towel_stuff', - '__init__.py'] - false_path = relpath(os.path.join(*false_path), sys.prefix) - - # Test if the distribution uses the file in question - dist = Distribution(distinfo_dir) - self.assertTrue(dist.uses(true_path)) - self.assertFalse(dist.uses(false_path)) - - def test_get_distinfo_file(self): - # Test the retrieval of dist-info file objects. - distinfo_name = 'choxie-2.0.0.9' - other_distinfo_name = 'grammar-1.0a4' - distinfo_dir = os.path.join(self.fake_dists_path, - distinfo_name + '.dist-info') - dist = Distribution(distinfo_dir) - # Test for known good file matches - distinfo_files = [ - # Relative paths - 'INSTALLER', 'METADATA', - # Absolute paths - os.path.join(distinfo_dir, 'RECORD'), - os.path.join(distinfo_dir, 'REQUESTED'), - ] - - for distfile in distinfo_files: - with dist.get_distinfo_file(distfile) as value: - self.assertIsInstance(value, io.TextIOWrapper) - # Is it the correct file? - self.assertEqual(value.name, - os.path.join(distinfo_dir, distfile)) - - # Test an absolute path that is part of another distributions dist-info - other_distinfo_file = os.path.join( - self.fake_dists_path, other_distinfo_name + '.dist-info', - 'REQUESTED') - self.assertRaises(PackagingError, dist.get_distinfo_file, - other_distinfo_file) - # Test for a file that should not exist - self.assertRaises(PackagingError, dist.get_distinfo_file, - 'MAGICFILE') - - def test_list_distinfo_files(self): - # Test for the iteration of RECORD path entries. - distinfo_name = 'towel_stuff-0.1' - distinfo_dir = os.path.join(self.fake_dists_path, - distinfo_name + '.dist-info') - dist = Distribution(distinfo_dir) - # Test for the iteration of the raw path - distinfo_record_paths = self.records[distinfo_dir].keys() - found = dist.list_distinfo_files() - self.assertEqual(sorted(found), sorted(distinfo_record_paths)) - # Test for the iteration of local absolute paths - distinfo_record_paths = [os.path.join(sys.prefix, path) - for path in self.records[distinfo_dir]] - found = dist.list_distinfo_files(local=True) - self.assertEqual(sorted(found), sorted(distinfo_record_paths)) - - def test_get_resources_path(self): - distinfo_name = 'babar-0.1' - distinfo_dir = os.path.join(self.fake_dists_path, - distinfo_name + '.dist-info') - dist = Distribution(distinfo_dir) - resource_path = dist.get_resource_path('babar.png') - self.assertEqual(resource_path, 'babar.png') - self.assertRaises(KeyError, dist.get_resource_path, 'notexist') - - -class TestEggInfoDistribution(CommonDistributionTests, - support.LoggingCatcher, - unittest.TestCase): - - cls = EggInfoDistribution - sample_dist = 'bacon', '0.1', 'bacon-0.1.egg-info' - - def setUp(self): - super(TestEggInfoDistribution, self).setUp() - - self.dirs = [os.path.join(self.fake_dists_path, f) - for f in os.listdir(self.fake_dists_path) - if f.endswith('.egg') or f.endswith('.egg-info')] - - self.records = {} - - @unittest.skip('not implemented yet') - def test_list_installed_files(self): - # EggInfoDistribution defines list_installed_files but there is no - # test for it yet; someone with setuptools expertise needs to add a - # file with the list of installed files for one of the egg fake dists - # and write the support code to populate self.records (and then delete - # this method) - pass - - -class TestDatabase(support.LoggingCatcher, - unittest.TestCase): - - def setUp(self): - super(TestDatabase, self).setUp() - disable_cache() - # Setup the path environment with our fake distributions - current_path = os.path.abspath(os.path.dirname(__file__)) - self.sys_path = sys.path[:] - self.fake_dists_path = os.path.join(current_path, 'fake_dists') - sys.path.insert(0, self.fake_dists_path) - - def tearDown(self): - sys.path[:] = self.sys_path - enable_cache() - super(TestDatabase, self).tearDown() - - def test_distinfo_dirname(self): - # Given a name and a version, we expect the distinfo_dirname function - # to return a standard distribution information directory name. - - items = [ - # (name, version, standard_dirname) - # Test for a very simple single word name and decimal version - # number - ('docutils', '0.5', 'docutils-0.5.dist-info'), - # Test for another except this time with a '-' in the name, which - # needs to be transformed during the name lookup - ('python-ldap', '2.5', 'python_ldap-2.5.dist-info'), - # Test for both '-' in the name and a funky version number - ('python-ldap', '2.5 a---5', 'python_ldap-2.5 a---5.dist-info'), - ] - - # Loop through the items to validate the results - for name, version, standard_dirname in items: - dirname = distinfo_dirname(name, version) - self.assertEqual(dirname, standard_dirname) - - @requires_zlib - def test_get_distributions(self): - # Lookup all distributions found in the ``sys.path``. - # This test could potentially pick up other installed distributions - fake_dists = [('grammar', '1.0a4'), ('choxie', '2.0.0.9'), - ('towel-stuff', '0.1'), ('babar', '0.1')] - found_dists = [] - - # Verify the fake dists have been found. - dists = [dist for dist in get_distributions()] - for dist in dists: - self.assertIsInstance(dist, Distribution) - if (dist.name in dict(fake_dists) and - dist.path.startswith(self.fake_dists_path)): - found_dists.append((dist.name, dist.metadata['version'], )) - else: - # check that it doesn't find anything more than this - self.assertFalse(dist.path.startswith(self.fake_dists_path)) - # otherwise we don't care what other distributions are found - - # Finally, test that we found all that we were looking for - self.assertEqual(sorted(found_dists), sorted(fake_dists)) - - # Now, test if the egg-info distributions are found correctly as well - fake_dists += [('bacon', '0.1'), ('cheese', '2.0.2'), - ('coconuts-aster', '10.3'), - ('banana', '0.4'), ('strawberry', '0.6'), - ('truffles', '5.0'), ('nut', 'funkyversion')] - found_dists = [] - - dists = [dist for dist in get_distributions(use_egg_info=True)] - for dist in dists: - self.assertIsInstance(dist, (Distribution, EggInfoDistribution)) - if (dist.name in dict(fake_dists) and - dist.path.startswith(self.fake_dists_path)): - found_dists.append((dist.name, dist.metadata['version'])) - else: - self.assertFalse(dist.path.startswith(self.fake_dists_path)) - - self.assertEqual(sorted(fake_dists), sorted(found_dists)) - - @requires_zlib - def test_get_distribution(self): - # Test for looking up a distribution by name. - # Test the lookup of the towel-stuff distribution - name = 'towel-stuff' # Note: This is different from the directory name - - # Lookup the distribution - dist = get_distribution(name) - self.assertIsInstance(dist, Distribution) - self.assertEqual(dist.name, name) - - # Verify that an unknown distribution returns None - self.assertIsNone(get_distribution('bogus')) - - # Verify partial name matching doesn't work - self.assertIsNone(get_distribution('towel')) - - # Verify that it does not find egg-info distributions, when not - # instructed to - self.assertIsNone(get_distribution('bacon')) - self.assertIsNone(get_distribution('cheese')) - self.assertIsNone(get_distribution('strawberry')) - self.assertIsNone(get_distribution('banana')) - - # Now check that it works well in both situations, when egg-info - # is a file and directory respectively. - dist = get_distribution('cheese', use_egg_info=True) - self.assertIsInstance(dist, EggInfoDistribution) - self.assertEqual(dist.name, 'cheese') - - dist = get_distribution('bacon', use_egg_info=True) - self.assertIsInstance(dist, EggInfoDistribution) - self.assertEqual(dist.name, 'bacon') - - dist = get_distribution('banana', use_egg_info=True) - self.assertIsInstance(dist, EggInfoDistribution) - self.assertEqual(dist.name, 'banana') - - dist = get_distribution('strawberry', use_egg_info=True) - self.assertIsInstance(dist, EggInfoDistribution) - self.assertEqual(dist.name, 'strawberry') - - def test_get_file_users(self): - # Test the iteration of distributions that use a file. - name = 'towel_stuff-0.1' - path = os.path.join(self.fake_dists_path, name, - 'towel_stuff', '__init__.py') - for dist in get_file_users(path): - self.assertIsInstance(dist, Distribution) - self.assertEqual(dist.name, name) - - @requires_zlib - def test_provides(self): - # Test for looking up distributions by what they provide - checkLists = lambda x, y: self.assertEqual(sorted(x), sorted(y)) - - l = [dist.name for dist in provides_distribution('truffles')] - checkLists(l, ['choxie', 'towel-stuff']) - - l = [dist.name for dist in provides_distribution('truffles', '1.0')] - checkLists(l, ['choxie']) - - l = [dist.name for dist in provides_distribution('truffles', '1.0', - use_egg_info=True)] - checkLists(l, ['choxie', 'cheese']) - - l = [dist.name for dist in provides_distribution('truffles', '1.1.2')] - checkLists(l, ['towel-stuff']) - - l = [dist.name for dist in provides_distribution('truffles', '1.1')] - checkLists(l, ['towel-stuff']) - - l = [dist.name for dist in provides_distribution('truffles', - '!=1.1,<=2.0')] - checkLists(l, ['choxie']) - - l = [dist.name for dist in provides_distribution('truffles', - '!=1.1,<=2.0', - use_egg_info=True)] - checkLists(l, ['choxie', 'bacon', 'cheese']) - - l = [dist.name for dist in provides_distribution('truffles', '>1.0')] - checkLists(l, ['towel-stuff']) - - l = [dist.name for dist in provides_distribution('truffles', '>1.5')] - checkLists(l, []) - - l = [dist.name for dist in provides_distribution('truffles', '>1.5', - use_egg_info=True)] - checkLists(l, ['bacon']) - - l = [dist.name for dist in provides_distribution('truffles', '>=1.0')] - checkLists(l, ['choxie', 'towel-stuff']) - - l = [dist.name for dist in provides_distribution('strawberry', '0.6', - use_egg_info=True)] - checkLists(l, ['coconuts-aster']) - - l = [dist.name for dist in provides_distribution('strawberry', '>=0.5', - use_egg_info=True)] - checkLists(l, ['coconuts-aster']) - - l = [dist.name for dist in provides_distribution('strawberry', '>0.6', - use_egg_info=True)] - checkLists(l, []) - - l = [dist.name for dist in provides_distribution('banana', '0.4', - use_egg_info=True)] - checkLists(l, ['coconuts-aster']) - - l = [dist.name for dist in provides_distribution('banana', '>=0.3', - use_egg_info=True)] - checkLists(l, ['coconuts-aster']) - - l = [dist.name for dist in provides_distribution('banana', '!=0.4', - use_egg_info=True)] - checkLists(l, []) - - @requires_zlib - def test_obsoletes(self): - # Test looking for distributions based on what they obsolete - checkLists = lambda x, y: self.assertEqual(sorted(x), sorted(y)) - - l = [dist.name for dist in obsoletes_distribution('truffles', '1.0')] - checkLists(l, []) - - l = [dist.name for dist in obsoletes_distribution('truffles', '1.0', - use_egg_info=True)] - checkLists(l, ['cheese', 'bacon']) - - l = [dist.name for dist in obsoletes_distribution('truffles', '0.8')] - checkLists(l, ['choxie']) - - l = [dist.name for dist in obsoletes_distribution('truffles', '0.8', - use_egg_info=True)] - checkLists(l, ['choxie', 'cheese']) - - l = [dist.name for dist in obsoletes_distribution('truffles', '0.9.6')] - checkLists(l, ['choxie', 'towel-stuff']) - - l = [dist.name for dist in obsoletes_distribution('truffles', - '0.5.2.3')] - checkLists(l, ['choxie', 'towel-stuff']) - - l = [dist.name for dist in obsoletes_distribution('truffles', '0.2')] - checkLists(l, ['towel-stuff']) - - @requires_zlib - def test_yield_distribution(self): - # tests the internal function _yield_distributions - checkLists = lambda x, y: self.assertEqual(sorted(x), sorted(y)) - - eggs = [('bacon', '0.1'), ('banana', '0.4'), ('strawberry', '0.6'), - ('truffles', '5.0'), ('cheese', '2.0.2'), - ('coconuts-aster', '10.3'), ('nut', 'funkyversion')] - dists = [('choxie', '2.0.0.9'), ('grammar', '1.0a4'), - ('towel-stuff', '0.1'), ('babar', '0.1')] - - checkLists([], _yield_distributions(False, False)) - - found = [(dist.name, dist.metadata['Version']) - for dist in _yield_distributions(False, True) - if dist.path.startswith(self.fake_dists_path)] - checkLists(eggs, found) - - found = [(dist.name, dist.metadata['Version']) - for dist in _yield_distributions(True, False) - if dist.path.startswith(self.fake_dists_path)] - checkLists(dists, found) - - found = [(dist.name, dist.metadata['Version']) - for dist in _yield_distributions(True, True) - if dist.path.startswith(self.fake_dists_path)] - checkLists(dists + eggs, found) - - -class DataFilesTestCase(GlobTestCaseBase): - - def assertRulesMatch(self, rules, spec): - tempdir = self.build_files_tree(spec) - expected = self.clean_tree(spec) - result = get_resources_dests(tempdir, rules) - self.assertEqual(expected, result) - - def clean_tree(self, spec): - files = {} - for path, value in spec.items(): - if value is not None: - files[path] = value - return files - - def test_simple_glob(self): - rules = [('', '*.tpl', '{data}')] - spec = {'coucou.tpl': '{data}/coucou.tpl', - 'Donotwant': None} - self.assertRulesMatch(rules, spec) - - def test_multiple_match(self): - rules = [('scripts', '*.bin', '{appdata}'), - ('scripts', '*', '{appscript}')] - spec = {'scripts/script.bin': '{appscript}/script.bin', - 'Babarlikestrawberry': None} - self.assertRulesMatch(rules, spec) - - def test_set_match(self): - rules = [('scripts', '*.{bin,sh}', '{appscript}')] - spec = {'scripts/script.bin': '{appscript}/script.bin', - 'scripts/babar.sh': '{appscript}/babar.sh', - 'Babarlikestrawberry': None} - self.assertRulesMatch(rules, spec) - - def test_set_match_multiple(self): - rules = [('scripts', 'script{s,}.{bin,sh}', '{appscript}')] - spec = {'scripts/scripts.bin': '{appscript}/scripts.bin', - 'scripts/script.sh': '{appscript}/script.sh', - 'Babarlikestrawberry': None} - self.assertRulesMatch(rules, spec) - - def test_set_match_exclude(self): - rules = [('scripts', '*', '{appscript}'), - ('', os.path.join('**', '*.sh'), None)] - spec = {'scripts/scripts.bin': '{appscript}/scripts.bin', - 'scripts/script.sh': None, - 'Babarlikestrawberry': None} - self.assertRulesMatch(rules, spec) - - def test_glob_in_base(self): - rules = [('scrip*', '*.bin', '{appscript}')] - spec = {'scripts/scripts.bin': '{appscript}/scripts.bin', - 'scripouille/babar.bin': '{appscript}/babar.bin', - 'scriptortu/lotus.bin': '{appscript}/lotus.bin', - 'Babarlikestrawberry': None} - self.assertRulesMatch(rules, spec) - - def test_recursive_glob(self): - rules = [('', os.path.join('**', '*.bin'), '{binary}')] - spec = {'binary0.bin': '{binary}/binary0.bin', - 'scripts/binary1.bin': '{binary}/scripts/binary1.bin', - 'scripts/bin/binary2.bin': '{binary}/scripts/bin/binary2.bin', - 'you/kill/pandabear.guy': None} - self.assertRulesMatch(rules, spec) - - def test_final_exemple_glob(self): - rules = [ - ('mailman/database/schemas/', '*', '{appdata}/schemas'), - ('', os.path.join('**', '*.tpl'), '{appdata}/templates'), - ('', os.path.join('developer-docs', '**', '*.txt'), '{doc}'), - ('', 'README', '{doc}'), - ('mailman/etc/', '*', '{config}'), - ('mailman/foo/', os.path.join('**', 'bar', '*.cfg'), - '{config}/baz'), - ('mailman/foo/', os.path.join('**', '*.cfg'), '{config}/hmm'), - ('', 'some-new-semantic.sns', '{funky-crazy-category}'), - ] - spec = { - 'README': '{doc}/README', - 'some.tpl': '{appdata}/templates/some.tpl', - 'some-new-semantic.sns': - '{funky-crazy-category}/some-new-semantic.sns', - 'mailman/database/mailman.db': None, - 'mailman/database/schemas/blah.schema': - '{appdata}/schemas/blah.schema', - 'mailman/etc/my.cnf': '{config}/my.cnf', - 'mailman/foo/some/path/bar/my.cfg': - '{config}/hmm/some/path/bar/my.cfg', - 'mailman/foo/some/path/other.cfg': - '{config}/hmm/some/path/other.cfg', - 'developer-docs/index.txt': '{doc}/developer-docs/index.txt', - 'developer-docs/api/toc.txt': '{doc}/developer-docs/api/toc.txt', - } - self.maxDiff = None - self.assertRulesMatch(rules, spec) - - def test_get_file(self): - # Create a fake dist - temp_site_packages = tempfile.mkdtemp() - self.addCleanup(shutil.rmtree, temp_site_packages) - - dist_name = 'test' - dist_info = os.path.join(temp_site_packages, 'test-0.1.dist-info') - os.mkdir(dist_info) - - metadata_path = os.path.join(dist_info, 'METADATA') - resources_path = os.path.join(dist_info, 'RESOURCES') - - with open(metadata_path, 'w') as fp: - fp.write(dedent("""\ - Metadata-Version: 1.2 - Name: test - Version: 0.1 - Summary: test - Author: me - """)) - - test_path = 'test.cfg' - - fd, test_resource_path = tempfile.mkstemp() - os.close(fd) - self.addCleanup(os.remove, test_resource_path) - - with open(test_resource_path, 'w') as fp: - fp.write('Config') - - with open(resources_path, 'w') as fp: - fp.write('%s,%s' % (test_path, test_resource_path)) - - # Add fake site-packages to sys.path to retrieve fake dist - self.addCleanup(sys.path.remove, temp_site_packages) - sys.path.insert(0, temp_site_packages) - - # Force packaging.database to rescan the sys.path - self.addCleanup(enable_cache) - disable_cache() - - # Try to retrieve resources paths and files - self.assertEqual(get_file_path(dist_name, test_path), - test_resource_path) - self.assertRaises(KeyError, get_file_path, dist_name, 'i-dont-exist') - - with get_file(dist_name, test_path) as fp: - self.assertEqual(fp.read(), 'Config') - self.assertRaises(KeyError, get_file, dist_name, 'i-dont-exist') - - -def test_suite(): - suite = unittest.TestSuite() - load = unittest.defaultTestLoader.loadTestsFromTestCase - suite.addTest(load(TestDistribution)) - suite.addTest(load(TestEggInfoDistribution)) - suite.addTest(load(TestDatabase)) - suite.addTest(load(DataFilesTestCase)) - return suite - - -if __name__ == "__main__": - unittest.main(defaultTest='test_suite') diff -r 2e49722c7263 -r 6944bdf1289a Lib/packaging/tests/test_depgraph.py --- a/Lib/packaging/tests/test_depgraph.py Thu Jun 09 15:52:31 2011 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,309 +0,0 @@ -"""Tests for packaging.depgraph """ -import io -import os -import re -import sys -import packaging.database -from packaging import depgraph - -from packaging.tests import unittest, support -from packaging.tests.support import requires_zlib - - -class DepGraphTestCase(support.LoggingCatcher, - unittest.TestCase): - - DISTROS_DIST = ('choxie', 'grammar', 'towel-stuff') - DISTROS_EGG = ('bacon', 'banana', 'strawberry', 'cheese') - BAD_EGGS = ('nut',) - - EDGE = re.compile( - r'"(?P.*)" -> "(?P.*)" \[label="(?P