⇤ ← Revision 1 as of 2005-07-23 12:11:42
Size: 58980
Comment:
|
Size: 196
Comment:
|
Deletions are marked like this. | Additions are marked like this. |
Line 5: | Line 5: |
= Building and Distributing Packages with setuptools = | |
Line 7: | Line 6: |
setuptools is a collection of enhancements to the Python distutils (for Python 2.3 and up) that allow you to more easily build and distribute Python packages, especially ones that have dependencies on other packages. Packages built and distributed using setuptools look to the user like ordinary Python packages based on the distutils. Your users don't need to install or even know about setuptools in order to use them, and you don't have to include the entire setuptools package in your distributions. By including just a single [http://peak.telecommunity.com/dist/ez_setup.py bootstrap module] (a 5K .py file), your package will automatically download and install setuptools if the user is building your package from source and doesn't have a suitable version already installed. Feature Highlights: * Automatically find/download/install/upgrade dependencies at build time using the [http://peak.telecommunity.com/DevCenter/EasyInstall EasyInstall tool], which supports downloading via HTTP, FTP, Subversion, and SourceForge, and automatically scans web pages linked from PyPI to find download links. (It's the closest thing to CPAN currently available for Python.) * Create [http://peak.telecommunity.com/DevCenter/PythonEggs Python Eggs] - a single-file importable distribution format * Include data files inside your package directories, where your code can actually use them. (Python 2.4 distutils also supports this feature, but setuptools provides the feature for Python 2.3 packages also, and supports accessing data files in zipped packages too.) * Automatically include all packages in your source tree, without listing them individually in setup.py * Automatically include all relevant files in your source distributions, without needing to create a MANIFEST.in file, and without having to force regeneration of the MANIFEST file when your source tree changes. * Transparent Pyrex support, so that your setup.py can list .pyx files and still work even when the end-user doesn't have Pyrex installed (as long as you include the Pyrex-generated C in your source distribution) * Command aliases - create project-specific, per-user, or site-wide shortcut names for commonly used commands and options * PyPI upload support - upload your source distributions and eggs to PyPI * Deploy your project in "development mode", such that it's available on sys.path, yet can still be edited directly from its source checkout. = Developer's Guide = == Installing setuptools == Download [http://peak.telecommunity.com/dist/ez_setup.py ez_setup.py] and run it; this will download and install the appropriate egg for your Python version. You may receive a message telling you about an obsolete version of setuptools being present; if so, you must be sure to delete it entirely, along with the old pkg_resources module if it's present on sys.path. == Basic Use == For basic use of setuptools, just import things from setuptools instead of the distutils. Here's a minimal setup script using setuptools: {{{#!python from setuptools import setup, find_packages setup( name = "HelloWorld", version = "0.1", packages = find_packages(), ) }}} As you can see, it doesn't take much to use setuptools in a project. Just by doing the above, this project will be able to produce eggs, upload to PyPI, and automatically include all packages in the directory where the setup.py lives. See the Command Reference section below to see what commands you can give to this setup script. Of course, before you release your project to PyPI, you'll want to add a bit more information to your setup script to help people find or learn about your project. And maybe your project will have grown by then to include a few dependencies, and perhaps some data files and scripts: {{{#!python from setuptools import setup, find_packages setup( name = "HelloWorld", version = "0.1", packages = find_packages(), scripts = ['say_hello.py'], # Project uses reStructuredText, so ensure that the docutils get # installed or upgraded on the target machine install_requires = ['docutils>=0.3'], package_data = { # If any package contains *.txt or *.rst files, include them: '': ['*.txt', '*.rst'], # And include any *.msg files found in the 'hello' package, too: 'hello': ['*.msg'], } # metadata for upload to PyPI author = "Me", author_email = "[email protected]", description = "This is an Example Package", license = "PSF", keywords = "hello world example examples", url = "http://example.com/HelloWorld/", # project home page, if any # could also include long_description, download_url, classifiers, etc. ) }}} In the sections that follow, we'll explain what most of these setup() arguments do (except for the metadata ones), and the various ways you might use them in your own project(s). == New and Changed setup() Keywords == The following keyword arguments to setup() are added or changed by setuptools. All of them are optional; you do not have to supply them unless you need the associated setuptools feature. package_data A dictionary mapping package names to lists of glob patterns. For a complete description and examples, see the section below on Including Data Files. zip_safe A boolean (True or False) flag specifying whether the project can be safely installed and run from a zip file. If this argument is not supplied, the bdist_egg command will have to analyze all of your project's contents for possible problems each time it buids an egg. install_requires A string or list of strings specifying what other distributions need to be installed when this one is. See the section below on Declaring Dependencies for details and examples of the format of this argument. extras_require A dictionary mapping names of "extras" (optional features of your project) to strings or lists of strings specifying what other distributions must be installed to support those features. See the section below on Declaring Dependencies for details and examples of the format of this argument. test_suite A string naming a unittest.TestCase subclass (or a module containing one or more of them, or a method of such a subclass), or naming a function that can be called with no arguments and returns a unittest.TestSuite. Specifying this argument enables use of the test command to run the specified test suite, e.g. via setup.py test. See the section on the test command below for more details. namespace_packages A list of strings naming the project's "namespace packages". A namespace package is a package that may be split across multiple project distributions. For example, Zope 3's zope package is a namespace package, because subpackages like zope.interface and zope.publisher may be distributed separately. The egg runtime system can automatically merge such subpackages into a single parent package at runtime, as long as you declare them in each project that contains any subpackages of the namespace package, and as long as the namespace package's `__init__`.py does not contain any code. See the section below on Namespace Packages for more information. === Using find_packages() === For simple projects, it's usually easy enough to manually add packages to the packages argument of setup(). However, for very large projects (Twisted, PEAK, Zope, Chandler, etc.), it can be a big burden to keep the package list updated. That's what setuptools.find_packages() is for. find_packages() takes a source directory, and a list of package names or patterns to exclude. If omitted, the source directory defaults to the same directory as the setup script. Some projects use a src or lib directory as the root of their source tree, and those projects would of course use "src" or "lib" as the first argument to find_packages(). (And such projects also need something like package_dir = {'':'src'} in their setup() arguments, but that's just a normal distutils thing.) Anyway, find_packages() walks the target directory, and finds Python packages by looking for `__init__`.py files. It then filters the list of packages using the exclusion patterns. Exclusion patterns are package names, optionally including wildcards. For example, find_packages(exclude=["*.tests"]) will exclude all packages whose last name part is tests. Or, find_packages(exclude=["*.tests", "*.tests.*"]) will also exclude any subpackages of packages named tests, but it still won't exclude a top-level tests package or the children thereof. In fact, if you really want no tests packages at all, you'll need something like this: {{{#!python find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]) }}} in order to cover all the bases. Really, the exclusion patterns are intended to cover simpler use cases than this, like excluding a single, specified package and its subpackages. Regardless of the target directory or exclusions, the find_packages() function returns a list of package names suitable for use as the packages argument to setup(), and so is usually the easiest way to set that argument in your setup script. Especially since it frees you from having to remember to modify your setup script whenever your project grows additional top-level packages or subpackages. == Declaring Dependencies == setuptools supports automatically installing dependencies when a package is installed, and including information about dependencies in Python Eggs (so that package management tools like EasyInstall can use the information). setuptools and pkg_resources use a common syntax for specifying a project's required dependencies. This syntax consists of a project's PyPI name, optionally followed by a comma-separated list of "extras" in square brackets, optionally followed by a comma-separated list of version specifiers. A version specifier is one of the operators <, >, <=, >=, == or !=, followed by a version identifier. Tokens may be separated by whitespace, but any whitespace or nonstandard characters within a project name or version identifier must be replaced with -. Here are some example requirement specifiers: {{{#!python docutils >= 0.3 # comment lines and \ continuations are allowed in requirement strings BazSpam ==1.1, ==1.2, ==1.3, ==1.4, ==1.5, \ ==1.6, ==1.7 # and so are line-end comments PEAK[FastCGI, reST]>=0.5a4 setuptools==0.5a7 }}} The simplest way to include requirement specifiers is to use the install_requires argument to setup(). It takes a string or list of strings containing requirement specifiers. If you include more than one requirement in a string, each requirement must begin on a new line. This has three effects: 1. When your project is installed, either by using EasyInstall, setup.py install, or setup.py develop, all of the dependencies not already installed will be located (via PyPI), downloaded, built (if necessary), and installed. 1. Any scripts in your project will be installed with wrappers that verify the availability of the specified dependencies at runtime, and ensure that the correct versions are added to sys.path (e.g. if multiple versions have been installed). 1. Python Egg distributions will include a metadata file listing the dependencies. Note, by the way, that if you declare your dependencies in setup.py, you do ''not''' need to use the require() function in your scripts or modules, as long as you either install the project or use setup.py develop to do development work on it. (See "Development Mode" below for more details on using setup.py develop.) === Declaring "Extras" (optional features with their own dependencies) === Sometimes a project has "recommended" dependencies, that are not required for all uses of the project. For example, a project might offer optional PDF output if ReportLab is installed, and reStructuredText support if docutils is installed. These optional features are called "extras", and setuptools allows you to define their requirements as well. In this way, other projects that require these optional features can force the additional requirements to be installed, by naming the desired extras in their install_requires. For example, let's say that Project A offers optional PDF and reST support: {{{#!python setup( name="Project-A", ... extras_require = { 'PDF': ["ReportLab>=1.2", "RXP"], 'reST': ["docutils>=0.3"], } ) }}} And that project B needs project A, ''with''' PDF support: {{{#!python setup( name="Project-B", install_requires = ["Project-A[PDF]"], ... ) }}} This will cause ReportLab to be installed along with project A, if project B is installed -- even if project A was already installed. In this way, a project can encapsulate groups of optional "downstream dependencies" under a feature name, so that packages that depend on it don't have to know what the downstream dependencies are. If a later version of Project A builds in PDF support and no longer needs ReportLab, or if it ends up needing other dependencies besides ReportLab in order to provide PDF support, Project B's setup information does not need to change, but the right packages will still be installed if needed. As you can see, the extras_require argument takes a dictionary mapping names of "extra" features, to strings or lists of strings describing those features' requirements. These requirements will ''not''' be automatically installed unless another package depends on them (directly or indirectly) by including the desired "extras" in square brackets after the associated project name. (Or if the extras were listed in a requirement spec on the EasyInstall command line.) Note, by the way, that if a project ends up not needing any other packages to support a feature, it should keep an empty requirements list for that feature in its extras_require argument, so that packages depending on that feature don't break (due to an invalid feature name). For example, if Project A above builds in PDF support and no longer needs ReportLab, it should change its setup to this: {{{#!python setup( name="Project-A", ... extras_require = { 'PDF': [], 'reST': ["docutils>=0.3"], } ) }}} so that Package B doesn't have to remove the [PDF] from its requirement specifier. == Including Data Files == The distutils have traditionally allowed installation of "data files", which are placed in a platform-specific location. However, the most common use case for data files distributed with a package is for use ''by''' the package, usually by including the data files in the package directory. Setuptools supports this by allowing a package_data argument to setup(), e.g.: {{{#!python from setuptools import setup, find_packages setup( ... package_data = { # If any package contains *.txt or *.rst files, include them: '': ['*.txt', '*.rst'], # And include any *.msg files found in the 'hello' package, too: 'hello': ['*.msg'], } ) }}} The package_data argument is a dictionary that maps from package names to lists of glob patterns. The globs may include subdirectory names, if the data files are contained in a subdirectory of the package. For example, if the package tree looks like this: {{{#!python setup.py src/ mypkg/ __init__.py mypkg.txt data/ somefile.dat otherdata.dat }}} The setuptools setup file might look like this: {{{#!python from setuptools import setup, find_packages setup( ... packages = find_packages('src'), # include all packages under src package_dir = {'':'src'}, # tell distutils packages are under src package_data = { # If any package contains *.txt files, include them: '': ['*.txt'], # And include any *.dat files found in the 'data' subdirectory # of the 'mypkg' package, also: 'mypkg': ['data/*.dat'], } ) }}} Notice that if you list patterns in package_data under the empty string, these patterns are used to find files in every package, even ones that also have their own patterns listed. Thus, in the above example, the mypkg.txt file gets included even though it's not listed in the patterns for mypkg. Also notice that if you use paths, you ''must''' use a forward slash (/) as the path separator, even if you are on Windows. Setuptools automatically converts slashes to appropriate platform-specific separators at build time. (Note: although the package_data argument was previously only available in setuptools, it was also added to the Python distutils package as of Python 2.4; there is [http://docs.python.org/dist/node11.html some documentation for the feature] available on the python.org website.) === Accessing Data Files at Runtime === Typically, existing programs manipulate a package's `__file__` attribute in order to find the location of data files. However, this manipulation isn't compatible with PEP 302-based import hooks, including importing from zip files and Python Eggs. It is strongly recommended that, if you are using data files, you should use the [http://peak.telecommunity.com/DevCenter/PythonEggs#resource-management Resource Management API] of pkg_resources to access them. The pkg_resources module is distributed as part of setuptools, so if you're using setuptools to distribute your package, there is no reason not to use its resource management API. See also [http://peak.telecommunity.com/DevCenter/PythonEggs#accessing-package-resources Accessing Package Resources] for a quick example of converting code that uses `__file__` to use pkg_resources instead. == "Development Mode" == Under normal circumstances, the distutils assume that you are going to build a distribution of your project, not use it in its "raw" or "unbuilt" form. If you were to use the distutils that way, you would have to rebuild and reinstall your project every time you made a change to it during development. Another problem that sometimes comes up with the distutils is that you may need to do development on two related projects at the same time. You may need to put both projects' packages in the same directory to run them, but need to keep them separate for revision control purposes. How can you do this? Setuptools allows you to deploy your projects for use in a common directory or staging area, but without copying any files. Thus, you can edit each project's code in its checkout directory, and only need to run build commands when you change a project's C extensions or similarly compiled files. You can even deploy a project into another project's checkout directory, if that's your preferred way of working (as opposed to using a common independent staging area or the site-packages directory). To do this, use the setup.py develop command. It works very similarly to setup.py install or the EasyInstall tool, except that it doesn't actually install anything. Instead, it creates a special .egg-link file in the deployment directory, that links to your project's source code. And, if your deployment directory is Python's site-packages directory, it will also update the easy-install.pth file to include your project's source code, thereby making it available on sys.path for all programs using that Python installation. In addition, the develop command creates wrapper scripts in the target script directory that will run your in-development scripts after ensuring that all your install_requires packages are available on sys.path. You can deploy the same project to multiple staging areas, e.g. if you have multiple projects on the same machine that are sharing the same project you're doing development work. When you're done with a given development task, you can remove the project source from a staging area using setup.py develop --uninstall, specifying the desired staging area if it's not the default. There are several options to control the precise behavior of the develop command; see the section on the develop command below for more details. == Distributing a setuptools-based package == === Using setuptools... Without bundling it! === Your users might not have setuptools installed on their machines, or even if they do, it might not be the right version. Fixing this is easy; just download [http://peak.telecommunity.com/dist/ez_setup.py ez_setup.py], and put it in the same directory as your setup.py script. (Be sure to add it to your revision control system, too.) Then add these two lines to the very top of your setup script, before the script imports anything from setuptools: {{{#!python import ez_setup ez_setup.use_setuptools() }}} That's it. The ez_setup module will automatically download a matching version of setuptools from PyPI, if it isn't present on the target system. Whenever you install an updated version of setuptools, you should also update your projects' ez_setup.py files, so that a matching version gets installed on the target machine(s). By the way, setuptools supports the new PyPI "upload" command, so you can use setup.py sdist upload or setup.py bdist_egg upload to upload your source or egg distributions respectively. Your project's current version must be registered with PyPI first, of course; you can use setup.py register to do that. Or you can do it all in one step, e.g. setup.py register sdist bdist_egg upload will register the package, build source and egg distributions, and then upload them both to PyPI, where they'll be easily found by other projects that depend on them. === Managing Multiple Projects === If you're managing several projects that need to use ez_setup, and you are using Subversion as your revision control system, you can use the "svn:externals" property to share a single copy of ez_setup between projects, so that it will always be up-to-date whenever you check out or update an individual project, without having to manually update each project to use a new version. However, because Subversion only supports using directories as externals, you have to turn ez_setup.py into ez_setup/`__init__`.py in order to do this, then create "externals" definitions that map the ez_setup directory into each project. Also, if any of your projects use find_packages() on their setup directory, you will need to exclude the resulting ez_setup package, to keep it from being included in your distributions, e.g.: {{{#!python setup( ... packages = find_packages(exclude=['ez_setup']), ) }}} Of course, the ez_setup package will still be included in your packages' source distributions, as it needs to be. For your convenience, you may use the following external definition, which will track the latest version of setuptools: {{{#!python ez_setup svn://svn.eby-sarna.com/svnroot/ez_setup }}} You can set this by executing this command in your project directory: {{{#!python svn propedit svn:externals . }}} And then adding the line shown above to the file that comes up for editing. === Setting the zip_safe flag === For maximum performance, Python packages are best installed as zip files. Not all packages, however, are capable of running in compressed form, because they may expect to be able to access either source code or data files as normal operating system files. So, setuptools can install your project as a zipfile or a directory, and its default choice is determined by the project's zip_safe flag. You can pass a True or False value for the zip_safe argument to the setup() function, or you can omit it. If you omit it, the bdist_egg command will analyze your project's contents to see if it can detect any conditions that would prevent it from working in a zipfile. It will output notices to the console about any such conditions that it finds. Currently, this analysis is extremely conservative: it will consider the project unsafe if it contains any C extensions or datafiles whatsoever. This does ''not''' mean that the project can't or won't work as a zipfile! It just means that the bdist_egg authors aren't yet comfortable asserting that the project ''will''' work. If the project contains no C or data files, and does no `__file__` or `__path__` introspection or source code manipulation, then there is an extremely solid chance the project will work when installed as a zipfile. (And if the project uses pkg_resources for all its data file access, then C extensions and other data files shouldn't be a problem at all. See the Accessing Data Files at Runtime section above for more information.) However, if bdist_egg can't be ''sure''' that your package will work, but you've checked over all the warnings it issued, and you are either satisfied it ''will''' work (or if you want to try it for yourself), then you should set zip_safe to True in your setup() call. If it turns out that it doesn't work, you can always change it to False, which will force setuptools to install your project as a directory rather than as a zipfile. Of course, the end-user can still override either decision, if they are using EasyInstall to install your package. And, if you want to override for testing purposes, you can just run setup.py easy_install --zip-ok . or setup.py easy_install --always-unzip . in your project directory. to install the package as a zipfile or directory, respectively. In the future, as we gain more experience with different packages and become more satisfied with the robustness of the pkg_resources runtime, the "zip safety" analysis may become less conservative. However, we strongly recommend that you determine for yourself whether your project functions correctly when installed as a zipfile, correct any problems if you can, and then make an explicit declaration of True or False for the zip_safe flag, so that it will not be necessary for bdist_egg or EasyInstall to try to guess whether your project can work as a zipfile. === Namespace Packages === Sometimes, a large package is more useful if distributed as a collection of smaller eggs. However, Python does not normally allow the contents of a package to be retrieved from more than one location. "Namespace packages" are a solution for this problem. When you declare a package to be a namespace package, it means that the package has no meaningful contents in its `__init__`.py, and that it is merely a container for modules and subpackages. The pkg_resources runtime will automatically ensure that the contents of namespace packages that are spread over multiple eggs or directories are combined into a single virtual package. The namespace_packages argument to setup() lets you declare your project's namespace packages, so that they will be included in your project's metadata. Then, the runtime will automatically detect this when it adds the distribution to sys.path, and ensure that the packages are properly merged. The argument should list the namespace packages that the egg participates in. For example, the ZopeInterface project might do this: {{{#!python setup( # ... namespace_packages = ['zope'] ) }}} because it contains a zope.interface package that lives in the zope namespace package. Similarly, a project for a standalone zope.publisher would also declare the zope namespace package. Namespace packages don't have to be top-level packages. For example, Zope 3's zope.app package is a namespace package, and in the future PEAK's peak.util package will be too. Note, by the way, that your project's source tree must include the namespace packages' `__init__`.py files (and the `__init__`.py of any parent packages), in a normal Python package layout. These `__init__`.py files should not contain any code or data, because only ''one''' egg's `__init__`.py files will be used to construct the parent packages in memory at runtime, and there is no guarantee which egg will be used. For example, if both zope.interface and zope.publisher have been installed from separate distributions, it is unspecified which of the two distributions' zope/`__init__`.py files will be used to create the zope package in memory. Therefore, it is better not to have any code or data in a namespace package's `__init__` module, so as to prevent any complications. (This is one reason the concept is called a "namespace package": it is a package that exists ''only''' to provide a namespace under which other modules or packages are gathered. In Java, for example, namespace packages are often used just to avoid naming collisions between different projects, using package names like org.apache as a namespace for packages that are part of apache.org projects.) === Tagging and "Daily Build" or "Snapshot" Releases === When a set of related projects are under development, it may be important to track finer-grained version increments than you would normally use for e.g. "stable" releases. While stable releases might be measured in dotted numbers with alpha/beta/etc. status codes, development versions of a project often need to be tracked by revision or build number or even build date. This is especially true when projects in development need to refer to one another, and therefore may literally need an up-to-the-minute version of something! To support these scenarios, setuptools allows you to "tag" your source and egg distributions by adding one or more of the following to the project's "official" version identifier: * An identifying string, such as "build" or "dev", or a manually-tracked build or revision number (--tag-build=STRING, -bSTRING) * A "last-modified revision number" string generated automatically from Subversion's metadata (assuming your project is being built from a Subversion "working copy") (--tag-svn-revision, -r) * An 8-character representation of the build date (--tag-date, -d) You can add these tags by adding egg_info and the desired options to the command line ahead of the sdist or bdist commands that you want to generate a daily build or snapshot for. See the section below on the egg_info command for more details. Also, if you are creating builds frequently, and either building them in a downloadable location or are copying them to a distribution server, you should probably also check out the rotate command, which lets you automatically delete all but the N most-recently-modified distributions matching a glob pattern. So, you can use a command line like: {{{#!python setup.py egg_info -rbDEV bdist_egg rotate -m.egg -k3 }}} to build an egg whose version info includes 'DEV-rNNNN' (where NNNN is the most recent Subversion revision that affected the source tree), and then delete any egg files from the distribution directory except for the three that were built most recently. If you have to manage automated builds for multiple packages, each with different tagging and rotation policies, you may also want to check out the alias command, which would let each package define an alias like daily that would perform the necessary tag, build, and rotate commands. Then, a simpler scriptor cron job could just run setup.py daily in each project directory. (And, you could also define sitewide or per-user default versions of the daily alias, so that projects that didn't define their own would use the appropriate defaults.) === Generating Source Distributions === setuptools enhances the distutils' default algorithm for source file selection, so that all files managed by CVS or Subversion in your project tree are included in any source distribution you build. This is a big improvement over having to manually write a MANIFEST.in file and try to keep it in sync with your project. So, if you are using CVS or Subversion, and your source distributions only need to include files that you're tracking in revision control, don't create a a MANIFEST.in file for your project. (And, if you already have one, you might consider deleting it the next time you would otherwise have to change it.) Unlike the distutils, setuptools regenerates the source distribution MANIFEST file every time you build a source distribution, as long as you ''don't''' have a MANIFEST.in file. If you do have a MANIFEST.in (e.g. because you aren't using CVS or Subversion), then you'll have to follow the normal distutils procedures for managing what files get included in a source distribution, and setuptools' enhanced algorithms will ''not''' be used. (Note, by the way, that if you're using some other revision control system, you might consider submitting a patch to the setuptools.command.sdist module so we can include support for it, too.) === Distributing Extensions compiled with Pyrex === setuptools includes transparent support for building Pyrex extensions, as long as you define your extensions using setuptools.Extension, ''not''' distutils.Extension. You must also not import anything from Pyrex in your setup script. If you follow these rules, you can safely list .pyx files as the source of your Extension objects in the setup script. setuptools will detect at build time whether Pyrex is installed or not. If it is, then setuptools will use it. If not, then setuptools will silently change the Extension objects to refer to the .c counterparts of the .pyx files, so that the normal distutils C compilation process will occur. Of course, for this to work, your source distributions must include the C code generated by Pyrex, as well as your original .pyx files. This means that you will probably want to include current .c files in your revision control system, rebuilding them whenever you check changes in for the .pyx source files. This will ensure that people tracking your project in CVS or Subversion will be able to build it even if they don't have Pyrex installed, and that your source releases will be similarly usable with or without Pyrex. = Command Reference = == alias - Define shortcuts for commonly used commands == Sometimes, you need to use the same commands over and over, but you can't necessarily set them as defaults. For example, if you produce both development snapshot releases and "stable" releases of a project, you may want to put the distributions in different places, or use different egg_info tagging options, etc. In these cases, it doesn't make sense to set the options in a distutils configuration file, because the values of the options changed based on what you're trying to do. Setuptools therefore allows you to define "aliases" - shortcut names for an arbitrary string of commands and options, using setup.py alias aliasname expansion, where aliasname is the name of the new alias, and the remainder of the command line supplies its expansion. For example, this command defines a sitewide alias called "daily", that sets various egg_info tagging options: {{{#!python setup.py alias --global-config daily egg_info --tag-svn-revision \ --tag-build=development }}} Once the alias is defined, it can then be used with other setup commands, e.g.: {{{#!python setup.py daily bdist_egg # generate a daily-build .egg file setup.py daily sdist # generate a daily-build source distro setup.py daily sdist bdist_egg # generate both }}} The above commands are interpreted as if the word daily were replaced with egg_info --tag-svn-revision --tag-build=development. Note that setuptools will expand each alias ''at most once''' in a given command line. This serves two purposes. First, if you accidentally create an alias loop, it will have no effect; you'll instead get an error message about an unknown command. Second, it allows you to define an alias for a command, that uses that command. For example, this (project-local) alias: {{{#!python setup.py alias bdist_egg bdist_egg rotate -k1 -m.egg }}} redefines the bdist_egg command so that it always runs the rotate command afterwards to delete all but the newest egg file. It doesn't loop indefinitely on bdist_egg because the alias is only expanded once when used. You can remove a defined alias with the --remove (or -r) option, e.g.: {{{#!python setup.py alias --global-config --remove daily }}} would delete the "daily" alias we defined above. Aliases can be defined on a project-specific, per-user, or sitewide basis. The default is to define or remove a project-specific alias, but you can use any of the configuration file options (listed under the saveopts command, below) to determine which distutils configuration file an aliases will be added to (or removed from). Note that if you omit the "expansion" argument to the alias command, you'll get output showing that alias' current definition (and what configuration file it's defined in). If you omit the alias name as well, you'll get a listing of all current aliases along with their configuration file locations. == bdist_egg - Create a Python Egg for the project == This command generates a Python Egg (.egg file) for the project. Python Eggs are the preferred binary distribution format for EasyInstall, because they are cross-platform (for "pure" packages), directly importable, and contain project metadata including scripts and information about the project's dependencies. They can be simply downloaded and added to sys.path directly, or they can be placed in a directory on sys.path and then automatically discovered by the egg runtime system. This command runs the egg_info command (if it hasn't already run) to update the project's metadata (.egg-info) directory. If you have added any extra metadata files to the .egg-info directory, those files will be included in the new egg file's metadata directory, for use by the egg runtime system or by any applications or frameworks that use that metadata. You won't usually need to specify any special options for this command; just use bdist_egg and you're done. But there are a few options that may be occasionally useful: --dist-dir=DIR, -d DIR Set the directory where the .egg file will be placed. If you don't supply this, then the --dist-dir setting of the bdist command will be used, which is usually a directory named dist in the project directory. --plat-name=PLATFORM, -p PLATFORM Set the platform name string that will be embedded in the egg's filename (assuming the egg contains C extensions). This can be used to override the distutils default platform name with something more meaningful. Keep in mind, however, that the egg runtime system expects to see eggs with distutils platform names, so it may ignore or reject eggs with non-standard platform names. Similarly, the EasyInstall program may ignore them when searching web pages for download links. However, if you are cross-compiling or doing some other unusual things, you might find a use for this option. --exclude-source-files Don't include any modules' .py files in the egg, just compiled Python, C, and data files. (Note that this doesn't affect any .py files in the EGG-INFO directory or its subdirectories, since for example there may be scripts with a .py extension which must still be retained.) We don't recommend that you use this option except for packages that are being bundled for proprietary end-user applications, or for "embedded" scenarios where space is at an absolute premium. On the other hand, if your package is going to be installed and used in compressed form, you might as well exclude the source because Python's traceback module doesn't currently understand how to display zipped source code anyway, or how to deal with files that are in a different place from where their code was compiled. There are also some options you will probably never need, but which are there because they were copied from similar bdist commands used as an example for creating this one. They may be useful for testing and debugging, however, which is why we kept them: --keep-temp, -k Keep the contents of the --bdist-dir tree around after creating the .egg file. --bdist-dir=DIR, -b DIR Set the temporary directory for creating the distribution. The entire contents of this directory are zipped to create the .egg file, after running various installation commands to copy the package's modules, data, and extensions here. --skip-build Skip doing any "build" commands; just go straight to the install-and-compress phases. == develop - Deploy the project source in "Development Mode" == This command allows you to deploy your project's source for use in one or more "staging areas" where it will be available for importing. This deployment is done in such a way that changes to the project source are immediately available in the staging area(s), without needing to run a build or install step after each change. The develop command works by creating an .egg-link file (named for the project) in the given staging area. If the staging area is Python's site-packages directory, it also updates an easy-install.pth file so that the project is on sys.path by default for all programs run using that Python installation. The develop command also installs wrapper scripts in the staging area (or a separate directory, as specified) that will ensure the project's dependencies are available on sys.path before running the project's source scripts. And, it ensures that any missing project dependencies are available in the staging area, by downloading and installing them if necessary. Last, but not least, the develop command invokes the build_ext -i command to ensure any C extensions in the project have been built and are up-to-date, and the egg_info command to ensure the project's metadata is updated (so that the runtime and wrappers know what the project's dependencies are). If you make changes to the project's metadata or C extensions, you should rerun the develop command (or egg_info, or build_ext -i) in order to keep the project up-to-date. If you add or rename any of the project's scripts, you should re-run develop against all relevant staging areas to update the wrapper scripts. Most other kinds of changes to your project should not require any build operations or rerunning develop. Here are the options that the develop command accepts. Note that they affect the project's dependencies as well as the project itself, so if you have dependencies that need to be installed and you use --exclude-scripts (for example), the dependencies' scripts will not be installed either! For this reason, you may want to use EasyInstall to install the project's dependencies before using the develop command, if you need finer control over the installation options for dependencies. --uninstall, -u Un-deploy the current project. You may use the --install-dir or -d option to designate the staging area. The created .egg-link file will be removed, if present and it is still pointing to the project directory. The project directory will be removed from easy-install.pth if the staging area is Python's site-packages directory. Note that this option currently does ''not''' uninstall script wrappers! You must uninstall them yourself, or overwrite them by using EasyInstall to activate a different version of the package. You can also avoid installing script wrappers in the first place, if you use the --exclude-scripts (aka -x) option when you run develop to deploy the project. --multi-version, -m "Multi-version" mode. Specifying this option prevents develop from adding an easy-install.pth entry for the project(s) being deployed, and if an entry for any version of a project already exists, the entry will be removed upon successful deployment. In multi-version mode, no specific version of the package is available for importing, unless you use pkg_resources.require() to put it on sys.path, or you are running a wrapper script generated by setuptools or EasyInstall. (In which case the wrapper script calls require() for you.) Note that if you install to a directory other than site-packages, this option is automatically in effect, because .pth files can only be used in site-packages (at least in Python 2.3 and 2.4). So, if you use the --install-dir or -d option (or they are set via configuration file(s)) your project and its dependencies will be deployed in multi- version mode. --install-dir=DIR, -d DIR Set the installation directory (staging area). If this option is not directly specified on the command line or in a distutils configuration file, the distutils default installation location is used. Normally, this will be the site-packages directory, but if you are using distutils configuration files, setting things like prefix or install_lib, then those settings are taken into account when computing the default staging area. --script-dir=DIR, -s DIR Set the script installation directory. If you don't supply this option (via the command line or a configuration file), but you ''have''' supplied an --install-dir (via command line or config file), then this option defaults to the same directory, so that the scripts will be able to find their associated package installation. Otherwise, this setting defaults to the location where the distutils would normally install scripts, taking any distutils configuration file settings into account. --exclude-scripts, -x Don't deploy script wrappers. This is useful if you don't want to disturb existing versions of the scripts in the staging area. --always-copy, -a Copy all needed distributions to the staging area, even if they are already present in another directory on sys.path. By default, if a requirement can be met using a distribution that is already available in a directory on sys.path, it will not be copied to the staging area. == egg_info - Create egg metadata and set build tags == This command performs two operations: it updates a project's .egg-info metadata directory (used by the bdist_egg, develop, and test commands), and it allows you to temporarily change a project's version string, to support "daily builds" or "snapshot" releases. It is run automatically by the sdist, bdist_egg, develop, and test commands in order to update the project's metadata, but you can also specify it explicitly in order to temporarily change the project's version string. The following options can be used to modify the project's version string for all remaining commands on the setup command line. The options are processed in the order shown, so if you use more than one, the requested tags will be added in the following order: --tag-build=NAME, -b NAME Append NAME to the project's version string. Due to the way setuptools processes "pre-release" version suffixes beginning with the letters "a" through "e" (like "alpha", "beta", and "candidate"), you will usually want to use a tag like "build" or "dev", as this will cause the version number to be considered ''lower''' than the project's default version. (If you want to make the version number ''higher''' than the default version, you can always leave off --tag-build and use one or both of the following options.) --tag-svn-revision, -r If the current directory is a Subversion checkout (i.e. has a .svn subdirectory, this appends a string of the form "-rNNNN" to the project's version string, where NNNN is the revision number of the most recent modification to the current directory, as obtained from the svn info command. --tag-date, -d Add a date stamp of the form "-YYYYMMDD" (e.g. "-20050528") to the project's version number. For advanced uses, there is one other option that can be set, to change the location of the project's .egg-info directory. Commands that need to find the project's source directory or metadata should get it from this setting: --egg-base=SOURCEDIR, -e SOURCEDIR Specify the directory that should contain the .egg-info directory. This should normally be the root of your project's source tree (which is not necessarily the same as your project directory; some projects use a src or lib subdirectory as the source root). You should not normally need to specify this directory, as it is normally determined from the package_dir argument to the setup() function, if any. If there is no package_dir set, this option defaults to the current directory. == rotate - Delete outdated distribution files == As you develop new versions of your project, your distribution (dist) directory will gradually fill up with older source and/or binary distribution files. The rotate command lets you automatically clean these up, keeping only the N most-recently modified files matching a given pattern. --match=PATTERNLIST, -m PATTERNLIST Comma-separated list of glob patterns to match. This option is ''required'''. The project name and -* is prepended to the supplied patterns, in order to match only distributions belonging to the current project (in case you have a shared distribution directory for multiple projects). Typically, you will use a glob pattern like .zip or .egg to match files of the specified type. Note that each supplied pattern is treated as a distinct group of files for purposes of selecting files to delete. --keep=COUNT, -k COUNT Number of matching distributions to keep. For each group of files identified by a pattern specified with the --match option, delete all but the COUNT most-recently-modified files in that group. This option is ''required'''. --dist-dir=DIR, -d DIR Directory where the distributions are. This defaults to the value of the bdist command's --dist-dir option, which will usually be the project's dist subdirectory. '''Example 1'': Delete all .tar.gz files from the distribution directory, except for the 3 most recently modified ones: {{{#!python setup.py rotate --match=.tar.gz --keep=3 }}} '''Example 2'': Delete all Python 2.3 or Python 2.4 eggs from the distribution directory, except the most recently modified one for each Python version: {{{#!python setup.py rotate --match=-py2.3*.egg,-py2.4*.egg --keep=1 }}} == saveopts - Save used options to a configuration file == Finding and editing distutils configuration files can be a pain, especially since you also have to translate the configuration options from command-line form to the proper configuration file format. You can avoid these hassles by using the saveopts command. Just add it to the command line to save the options you used. For example, this command builds the project using the mingw32 C compiler, then saves the --compiler setting as the default for future builds (even those run implicitly by the install command): {{{#!python setup.py build --compiler=mingw32 saveopts }}} The saveopts command saves all options for every commmand specified on the command line to the project's local setup.cfg file, unless you use one of the configuration file options to change where the options are saved. For example, this command does the same as above, but saves the compiler setting to the site-wide (global) distutils configuration: {{{#!python setup.py build --compiler=mingw32 saveopts -g }}} Note that it doesn't matter where you place the saveopts command on the command line; it will still save all the options specified for all commands. For example, this is another valid way to spell the last example: {{{#!python setup.py saveopts -g build --compiler=mingw32 }}} Note, however, that all of the commands specified are always run, regardless of where saveopts is placed on the command line. === Configuration File Options === Normally, settings such as options and aliases are saved to the project's local setup.cfg file. But you can override this and save them to the global or per-user configuration files, or to a manually-specified filename. --global-config, -g Save settings to the global distutils.cfg file inside the distutils package directory. You must have write access to that directory to use this option. You also can't combine this option with -u or -f. --user-config, -u Save settings to the current user's ~/.pydistutils.cfg (POSIX) or $HOME/pydistutils.cfg (Windows) file. You can't combine this option with -g or -f. --filename=FILENAME, -f FILENAME Save settings to the specified configuration file to use. You can't combine this option with -g or -u. Note that if you specify a non-standard filename, the distutils and setuptools will not use the file's contents. This option is mainly included for use in testing. These options are used by other setuptools commands that modify configuration files, such as the alias and setopt commands. == setopt - Set a distutils or setuptools option in a config file == This command is mainly for use by scripts, but it can also be used as a quick and dirty way to change a distutils configuration option without having to remember what file the options are in and then open an editor. '''Example 1''. Set the default C compiler to mingw32 (using long option names): {{{#!python setup.py setopt --command=build --option=compiler --set-value=mingw32 }}} '''Example 2''. Remove any setting for the distutils default package installation directory (short option names): {{{#!python setup.py setopt -c install -o install_lib -r }}} Options for the setopt command: --command=COMMAND, -c COMMAND Command to set the option for. This option is required. --option=OPTION, -o OPTION The name of the option to set. This option is required. --set-value=VALUE, -s VALUE The value to set the option to. Not needed if -r or --remove is set. --remove, -r Remove (unset) the option, instead of setting it. In addition to the above options, you may use any of the configuration file options (listed under the saveopts command, above) to determine which distutils configuration file the option will be added to (or removed from). == test - Build package and run a unittest suite == When doing test-driven development, or running automated builds that need testing before they are deployed for downloading or use, it's often useful to be able to run a project's unit tests without actually deploying the project anywhere, even using the develop command. The test command runs a project's unit tests without actually deploying it, by temporarily putting the project's source on sys.path, after first running build_ext -i and egg_info to ensure that any C extensions and project metadata are up-to-date. To use this command, your project's tests must be wrapped in a unittest test suite by either a function, a TestCase class or method, or a module containing TestCase classes. Note that many test systems including doctest support wrapping their non-unittest tests in TestSuite objects. So, if you are using a test package that does not support this, we suggest you encourage its developers to implement test suite support, as this is a convenient and standard way to aggregate a collection of tests to be run under a common test harness. By default, tests will be run in the "verbose" mode of the unittest package's text test runner, but you can get the "quiet" mode (just dots) if you supply the -q or --quiet option, either as a global option to the setup script (e.g. setup.py -q test) or as an option for the test command itself (e.g. setup.py test -q). There is one other option available: --test-suite=NAME, -s NAME Specify the test suite (or module, class, or method) to be run (e.g. some_module.test_suite). The default for this option can be set by giving a test_suite argument to the setup() function, e.g.: {{{#!python setup( # ... test_suite = "my_package.tests.test_all" ) }}} If you did not set a test_suite in your setup() call, and do not provide a --test-suite option, an error will occur. == upload - Upload source and/or egg distributions to PyPI == PyPI now supports uploading project files for redistribution; uploaded files are easily found by EasyInstall, even if you don't have download links on your project's home page. Although Python 2.5 will support uploading all types of distributions to PyPI, setuptools only supports source distributions and eggs. (This is partly because PyPI's upload support is currently broken for various other file types.) To upload files, you must include the upload command ''after''' the sdist or bdist_egg commands on the setup command line. For example: {{{#!python setup.py bdist_egg upload # create an egg and upload it setup.py sdist upload # create a source distro and upload it setup.py sdist bdist_egg upload # create and upload both }}} Note that to upload files for a project, the corresponding version must already be registered with PyPI, using the distutils register command. It's usually a good idea to include the register command at the start of the command line, so that any registration problems can be found and fixed before building and uploading the distributions, e.g.: {{{#!python setup.py register sdist bdist_egg upload }}} This will update PyPI's listing for your project's current version. Note, by the way, that the metadata in your setup() call determines what will be listed in PyPI for your package. Try to fill out as much of it as possible, as it will save you a lot of trouble manually adding and updating your PyPI listings. Just put it in setup.py and use the register comamnd to keep PyPI up to date. The upload command has a few options worth noting: --sign, -s Sign each uploaded file using GPG (GNU Privacy Guard). The gpg program must be available for execution on the system PATH. --show-response Display the full response text from server; this is useful for debugging PyPI problems. --repository=URL, -r URL The URL of the repository to upload to. Defaults to [http://www.python.org/pypi http://www.python.org/pypi] (i.e., the main PyPI installation). = Extending and Reusing setuptools = Sorry, this section isn't written yet, and neither is a lot of what's below this point, except for the change log. You might want to [setuptools?action=subscribe subscribe to changes in this page] to see when new documentation is added or updated. == Subclassing Command == XXX == Utility Modules == === ez_setup === XXX === setuptools.archive_util === XXX === setuptools.sandbox === XXX === setuptools.package_index === XXX |
= SetupTools工具 = == 概述 == == 使用说明 == [wiki:self/SetuptoolsManul] == 心得分享 == |
::-- limodou [DateTime(2005-07-23T12:11:42Z)] TableOfContents
SetupTools工具
概述
使用说明
[wiki:self/SetuptoolsManul]