From 28a1b18a047de2e81712c55e3d81cc3f2c0c54f9 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Mon, 11 May 2020 13:58:59 -0400 Subject: docs: created folder and index for userguide --- docs/userguide/index.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/userguide/index.txt (limited to 'docs/userguide') diff --git a/docs/userguide/index.txt b/docs/userguide/index.txt new file mode 100644 index 00000000..e69de29b -- cgit v1.2.1 From 7008a98cdcc359be75b1850db7c8f67270435328 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Mon, 11 May 2020 14:17:59 -0400 Subject: docs: update userguide index --- docs/userguide/index.txt | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'docs/userguide') diff --git a/docs/userguide/index.txt b/docs/userguide/index.txt index e69de29b..caaaa1d0 100644 --- a/docs/userguide/index.txt +++ b/docs/userguide/index.txt @@ -0,0 +1,17 @@ +================================================== +Building and Distributing Packages with Setuptools +================================================== + +``Setuptools`` is a collection of enhancements to the Python ``distutils`` +that allow developers 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``. + +.. toctree:: + :maxdepth: 1 + + Quickstart + keyword reference \ No newline at end of file -- cgit v1.2.1 From ef435da2b41adf9674db1df00415db2b46012f21 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Mon, 11 May 2020 14:19:18 -0400 Subject: docs: migrate basic use to quickstart Did a cut and paste from setuptoo.txt to userguide/quickstart.txt --- docs/userguide/quickstart.txt | 165 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 docs/userguide/quickstart.txt (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.txt b/docs/userguide/quickstart.txt new file mode 100644 index 00000000..4df50bc5 --- /dev/null +++ b/docs/userguide/quickstart.txt @@ -0,0 +1,165 @@ +Installing ``setuptools`` +========================= + +.. _Installing Packages: https://packaging.python.org/tutorials/installing-packages/ + +To install the latest version of setuptools, use:: + + pip install --upgrade setuptools + +Refer to `Installing Packages`_ guide for more information. + +Basic Use +========= + +For basic use of setuptools, just import things from setuptools instead of +the distutils. Here's a minimal setup script using setuptools:: + + 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. +Run that script in your project folder, alongside the Python packages +you have developed. + +Invoke that script to produce distributions 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. For example, to produce a source distribution, simply invoke:: + + setup.py sdist + +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:: + + 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 to display on PyPI + author="Me", + author_email="me@example.com", + description="This is an Example Package", + keywords="hello world example examples", + url="http://example.com/HelloWorld/", # project home page, if any + project_urls={ + "Bug Tracker": "https://bugs.example.com/HelloWorld/", + "Documentation": "https://docs.example.com/HelloWorld/", + "Source Code": "https://code.example.com/HelloWorld/", + }, + classifiers=[ + "License :: OSI Approved :: Python Software Foundation License" + ] + + # could also include long_description, download_url, 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). + + +Specifying Your Project's Version +--------------------------------- + +Setuptools can work well with most versioning schemes; there are, however, a +few special things to watch out for, in order to ensure that setuptools and +other tools can always tell what version of your package is newer than another +version. Knowing these things will also help you correctly specify what +versions of other projects your project depends on. + +A version consists of an alternating series of release numbers and pre-release +or post-release tags. A release number is a series of digits punctuated by +dots, such as ``2.4`` or ``0.5``. Each series of digits is treated +numerically, so releases ``2.1`` and ``2.1.0`` are different ways to spell the +same release number, denoting the first subrelease of release 2. But ``2.10`` +is the *tenth* subrelease of release 2, and so is a different and newer release +from ``2.1`` or ``2.1.0``. Leading zeros within a series of digits are also +ignored, so ``2.01`` is the same as ``2.1``, and different from ``2.0.1``. + +Following a release number, you can have either a pre-release or post-release +tag. Pre-release tags make a version be considered *older* than the version +they are appended to. So, revision ``2.4`` is *newer* than revision ``2.4c1``, +which in turn is newer than ``2.4b1`` or ``2.4a1``. Postrelease tags make +a version be considered *newer* than the version they are appended to. So, +revisions like ``2.4-1`` and ``2.4pl3`` are newer than ``2.4``, but are *older* +than ``2.4.1`` (which has a higher release number). + +A pre-release tag is a series of letters that are alphabetically before +"final". Some examples of prerelease tags would include ``alpha``, ``beta``, +``a``, ``c``, ``dev``, and so on. You do not have to place a dot or dash +before the prerelease tag if it's immediately after a number, but it's okay to +do so if you prefer. Thus, ``2.4c1`` and ``2.4.c1`` and ``2.4-c1`` all +represent release candidate 1 of version ``2.4``, and are treated as identical +by setuptools. + +In addition, there are three special prerelease tags that are treated as if +they were the letter ``c``: ``pre``, ``preview``, and ``rc``. So, version +``2.4rc1``, ``2.4pre1`` and ``2.4preview1`` are all the exact same version as +``2.4c1``, and are treated as identical by setuptools. + +A post-release tag is either a series of letters that are alphabetically +greater than or equal to "final", or a dash (``-``). Post-release tags are +generally used to separate patch numbers, port numbers, build numbers, revision +numbers, or date stamps from the release number. For example, the version +``2.4-r1263`` might denote Subversion revision 1263 of a post-release patch of +version ``2.4``. Or you might use ``2.4-20051127`` to denote a date-stamped +post-release. + +Notice that after each pre or post-release tag, you are free to place another +release number, followed again by more pre- or post-release tags. For example, +``0.6a9.dev-r41475`` could denote Subversion revision 41475 of the in- +development version of the ninth alpha of release 0.6. Notice that ``dev`` is +a pre-release tag, so this version is a *lower* version number than ``0.6a9``, +which would be the actual ninth alpha of release 0.6. But the ``-r41475`` is +a post-release tag, so this version is *newer* than ``0.6a9.dev``. + +For the most part, setuptools' interpretation of version numbers is intuitive, +but here are a few tips that will keep you out of trouble in the corner cases: + +* Don't stick adjoining pre-release tags together without a dot or number + between them. Version ``1.9adev`` is the ``adev`` prerelease of ``1.9``, + *not* a development pre-release of ``1.9a``. Use ``.dev`` instead, as in + ``1.9a.dev``, or separate the prerelease tags with a number, as in + ``1.9a0dev``. ``1.9a.dev``, ``1.9a0dev``, and even ``1.9.a.dev`` are + identical versions from setuptools' point of view, so you can use whatever + scheme you prefer. + +* If you want to be certain that your chosen numbering scheme works the way + you think it will, you can use the ``pkg_resources.parse_version()`` function + to compare different version numbers:: + + >>> from pkg_resources import parse_version + >>> parse_version("1.9.a.dev") == parse_version("1.9a0dev") + True + >>> parse_version("2.1-rc2") < parse_version("2.1") + True + >>> parse_version("0.6a9dev-r41475") < parse_version("0.6a9") + True + +Once you've decided on a version numbering scheme for your project, you can +have setuptools automatically tag your in-development releases with various +pre- or post-release tags. See the following sections for more details: + +* `Tagging and "Daily Build" or "Snapshot" Releases`_ +* The `egg_info`_ command \ No newline at end of file -- cgit v1.2.1 From 7971245c98f7218a8614135db56438e9a4642594 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Mon, 11 May 2020 14:22:04 -0400 Subject: docs: migrated keywords ref to keywords.txt Did a cut and paste from setuptools.txt --- docs/userguide/keywords.txt | 175 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 docs/userguide/keywords.txt (limited to 'docs/userguide') diff --git a/docs/userguide/keywords.txt b/docs/userguide/keywords.txt new file mode 100644 index 00000000..e2852b34 --- /dev/null +++ b/docs/userguide/keywords.txt @@ -0,0 +1,175 @@ +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. + +``include_package_data`` + If set to ``True``, this tells ``setuptools`` to automatically include any + data files it finds inside your package directories that are specified by + your ``MANIFEST.in`` file. For more information, see the section below on + `Including Data Files`_. + +``exclude_package_data`` + A dictionary mapping package names to lists of glob patterns that should + be *excluded* from your package directories. You can use this to trim back + any excess files included by ``include_package_data``. For a complete + description and examples, see the section below on `Including Data Files`_. + +``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`_. You do not need to use this option if you are using + ``include_package_data``, unless you need to add e.g. files that are + generated by your setup script and build process. (And are therefore not + in source control or are files that you don't want to include in your + source distribution.) + +``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 builds 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. + +``entry_points`` + A dictionary mapping entry point group names to strings or lists of strings + defining the entry points. Entry points are used to support dynamic + discovery of services or plugins provided by a project. See `Dynamic + Discovery of Services and Plugins`_ for details and examples of the format + of this argument. In addition, this keyword is used to support `Automatic + Script Creation`_. + +``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. + +``python_requires`` + A string corresponding to a version specifier (as defined in PEP 440) for + the Python version, used to specify the Requires-Python defined in PEP 345. + +``setup_requires`` + A string or list of strings specifying what other distributions need to + be present in order for the *setup script* to run. ``setuptools`` will + attempt to obtain these (using pip if available) before processing the + rest of the setup script or commands. This argument is needed if you + are using distutils extensions as part of your build process; for + example, extensions that process setup() arguments and turn them into + EGG-INFO metadata files. + + (Note: projects listed in ``setup_requires`` will NOT be automatically + installed on the system where the setup script is being run. They are + simply downloaded to the ./.eggs directory if they're not locally available + already. If you want them to be installed, as well as being available + when the setup script is run, you should add them to ``install_requires`` + **and** ``setup_requires``.) + +``dependency_links`` + A list of strings naming URLs to be searched when satisfying dependencies. + These links will be used if needed to install packages specified by + ``setup_requires`` or ``tests_require``. They will also be written into + the egg's metadata for use during install by tools that support them. + +``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 other than a namespace declaration. See the + section below on `Namespace Packages`_ for more information. + +``test_suite`` + A string naming a ``unittest.TestCase`` subclass (or a package or 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``. If the named suite is a module, and the module + has an ``additional_tests()`` function, it is called and the results are + added to the tests to be run. If the named suite is a package, any + submodules and subpackages are recursively added to the overall test suite. + + 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. + + New in 41.5.0: Deprecated the test command. + +``tests_require`` + If your project's tests need one or more additional packages besides those + needed to install it, you can use this option to specify them. It should + be a string or list of strings specifying what other distributions need to + be present for the package's tests to run. When you run the ``test`` + command, ``setuptools`` will attempt to obtain these (using pip if + available). Note that these required projects will *not* be installed on + the system where the tests are run, but only downloaded to the project's setup + directory if they're not already installed locally. + + New in 41.5.0: Deprecated the test command. + +.. _test_loader: + +``test_loader`` + If you would like to use a different way of finding tests to run than what + setuptools normally uses, you can specify a module name and class name in + this argument. The named class must be instantiable with no arguments, and + its instances must support the ``loadTestsFromNames()`` method as defined + in the Python ``unittest`` module's ``TestLoader`` class. Setuptools will + pass only one test "name" in the `names` argument: the value supplied for + the ``test_suite`` argument. The loader you specify may interpret this + string in any way it likes, as there are no restrictions on what may be + contained in a ``test_suite`` string. + + The module name and class name must be separated by a ``:``. The default + value of this argument is ``"setuptools.command.test:ScanningLoader"``. If + you want to use the default ``unittest`` behavior, you can specify + ``"unittest:TestLoader"`` as your ``test_loader`` argument instead. This + will prevent automatic scanning of submodules and subpackages. + + The module and class you specify here may be contained in another package, + as long as you use the ``tests_require`` option to ensure that the package + containing the loader class is available when the ``test`` command is run. + + New in 41.5.0: Deprecated the test command. + +``eager_resources`` + A list of strings naming resources that should be extracted together, if + any of them is needed, or if any C extensions included in the project are + imported. This argument is only useful if the project will be installed as + a zipfile, and there is a need to have all of the listed resources be + extracted to the filesystem *as a unit*. Resources listed here + should be "/"-separated paths, relative to the source root, so to list a + resource ``foo.png`` in package ``bar.baz``, you would include the string + ``bar/baz/foo.png`` in this argument. + + If you only need to obtain resources one at a time, or you don't have any C + extensions that access other files in the project (such as data files or + shared libraries), you probably do NOT need this argument and shouldn't + mess with it. For more details on how this argument works, see the section + below on `Automatic Resource Extraction`_. + +``use_2to3`` + Convert the source code from Python 2 to Python 3 with 2to3 during the + build process. See :doc:`python3` for more details. + +``convert_2to3_doctests`` + List of doctest source files that need to be converted with 2to3. + See :doc:`python3` for more details. + +``use_2to3_fixers`` + A list of modules to search for additional fixers to be used during + the 2to3 conversion. See :doc:`python3` for more details. + +``project_urls`` + An arbitrary map of URL names to hyperlinks, allowing more extensible + documentation of where various resources can be found than the simple + ``url`` and ``download_url`` options provide. \ No newline at end of file -- cgit v1.2.1 From 9175f899a4ddacc3c6bd6a02f3c17dde66403431 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Mon, 11 May 2020 14:25:44 -0400 Subject: docs: add commands ref entry in userguide index --- docs/userguide/index.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/index.txt b/docs/userguide/index.txt index caaaa1d0..901aad42 100644 --- a/docs/userguide/index.txt +++ b/docs/userguide/index.txt @@ -14,4 +14,5 @@ ordinary Python packages based on the ``distutils``. :maxdepth: 1 Quickstart - keyword reference \ No newline at end of file + keyword reference + Command reference \ No newline at end of file -- cgit v1.2.1 From 9ea37eda077883d310bfb7537f58c51cab84ff4c Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Mon, 11 May 2020 14:28:11 -0400 Subject: docs: migrate commands ref to commands.txt --- docs/userguide/commands.txt | 566 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 566 insertions(+) create mode 100644 docs/userguide/commands.txt (limited to 'docs/userguide') diff --git a/docs/userguide/commands.txt b/docs/userguide/commands.txt new file mode 100644 index 00000000..86048416 --- /dev/null +++ b/docs/userguide/commands.txt @@ -0,0 +1,566 @@ +----------------- +Command Reference +----------------- + +.. _alias: + +``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:: + + setup.py alias --global-config daily egg_info --tag-build=development + +Once the alias is defined, it can then be used with other setup commands, +e.g.:: + + 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-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:: + + 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.:: + + 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 +=================================================== + +.. warning:: + **eggs** are deprecated in favor of wheels, and not supported by pip. + +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: + +``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 any changes to the project's setup script or C extensions, +you should rerun the ``develop`` command against all relevant staging areas to +keep the project's scripts, metadata and extensions up-to-date. Most other +kinds of changes to your project should not require any build operations or +rerunning ``develop``, but keep in mind that even minor changes to the setup +script (e.g. changing an entry point definition) require you to re-run the +``develop`` or ``test`` commands to keep the distribution updated. + +Here are some of 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 pip 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 pip to install 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``. (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-path=DIR`` + Force the generated ``.egg-link`` file to use a specified relative path + to the source directory. This can be useful in circumstances where your + installation directory is being shared by code running under multiple + platforms (e.g. Mac and Windows) which have different absolute locations + for the code under development, but the same *relative* locations with + respect to the installation directory. If you use this option when + installing, you must supply the same relative path when uninstalling. + +In addition to the above options, the ``develop`` command also accepts all of +the same options accepted by ``easy_install``. If you've configured any +``easy_install`` settings in your ``setup.cfg`` (or other distutils config +files), the ``develop`` command will use them as defaults, unless you override +them in a ``[develop]`` section or on the command line. + + +.. _egg_info: + +``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 while executing other +commands. (It also generates the ``.egg-info/SOURCES.txt`` manifest file, which +is used when you are building source distributions.) + +In addition to writing the core egg metadata defined by ``setuptools`` and +required by ``pkg_resources``, this command can be extended to write other +metadata files as well, by defining entry points in the ``egg_info.writers`` +group. See the section on `Adding new EGG-INFO Files`_ below for more details. +Note that using additional metadata writers may require you to include a +``setup_requires`` argument to ``setup()`` in order to ensure that the desired +writers are available on ``sys.path``. + + +Release Tagging Options +----------------------- + +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 then use one or both of the following + options.) + + If you have a default build tag set in your ``setup.cfg``, you can suppress + it on the command line using ``-b ""`` or ``--tag-build=""`` as an argument + to the ``egg_info`` command. + +``--tag-date, -d`` + Add a date stamp of the form "-YYYYMMDD" (e.g. "-20050528") to the + project's version number. + +``--no-date, -D`` + Don't include a date stamp in the version number. This option is included + so you can override a default setting in ``setup.cfg``. + + +(Note: Because these options modify the version number used for source and +binary distributions of your project, you should first make sure that you know +how the resulting version numbers will be interpreted by automated tools +like pip. See the section above on `Specifying Your Project's Version`_ for an +explanation of pre- and post-release tags, as well as tips on how to choose and +verify a versioning scheme for your project.) + +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: + + +Other ``egg_info`` Options +-------------------------- + +``--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. + + +``egg_info`` Examples +--------------------- + +Creating a dated "nightly build" snapshot egg:: + + setup.py egg_info --tag-date --tag-build=DEV bdist_egg + +Creating a release with no version tags, even if some default tags are +specified in ``setup.cfg``:: + + setup.py egg_info -RDb "" sdist bdist_egg + +(Notice that ``egg_info`` must always appear on the command line *before* any +commands that you want the version changes to apply to.) + +.. _rotate: + +``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:: + + 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:: + + setup.py rotate --match=-py2.3*.egg,-py2.4*.egg --keep=1 + + +.. _saveopts: + +``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):: + + setup.py build --compiler=mingw32 saveopts + +The ``saveopts`` command saves all options for every command 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:: + + 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:: + + 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: + +``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):: + + 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):: + + 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: + +``test`` - Build package and run a unittest suite +================================================= + +.. warning:: + ``test`` is deprecated and will be removed in a future version. Users + looking for a generic test entry point independent of test runner are + encouraged to use `tox `_. + +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 +or package containing ``TestCase`` classes. If the named suite is a module, +and the module has an ``additional_tests()`` function, it is called and the +result (which must be a ``unittest.TestSuite``) is added to the tests to be +run. If the named suite is a package, any submodules and subpackages are +recursively added to the overall test suite. (Note: if your project specifies +a ``test_loader``, the rules for processing the chosen ``test_suite`` may +differ; see the `test_loader`_ documentation for more details.) + +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.:: + + 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. + +New in 41.5.0: Deprecated the test command. + + +.. _upload: + +``upload`` - Upload source and/or egg distributions to PyPI +=========================================================== + +The ``upload`` command was deprecated in version 40.0 and removed in version +42.0. Use `twine `_ instead. + +For more information on the current best practices in uploading your packages +to PyPI, see the Python Packaging User Guide's "Packaging Python Projects" +tutorial specifically the section on `uploading the distribution archives +`_. \ No newline at end of file -- cgit v1.2.1 From 14bae0541bb17824fa4530cf693ef0093b5bdf48 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Mon, 11 May 2020 14:46:49 -0400 Subject: docs: migrate functionality info to separate file cut-and-paste from setuptools.txt --- docs/userguide/functionalities.txt | 1338 ++++++++++++++++++++++++++++++++++++ 1 file changed, 1338 insertions(+) create mode 100644 docs/userguide/functionalities.txt (limited to 'docs/userguide') diff --git a/docs/userguide/functionalities.txt b/docs/userguide/functionalities.txt new file mode 100644 index 00000000..a310da97 --- /dev/null +++ b/docs/userguide/functionalities.txt @@ -0,0 +1,1338 @@ +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 two lists of package name +patterns to exclude and include. 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, filtering by inclusion +patterns, and finds Python packages (any directory). Packages are only +recognized if they include an ``__init__.py`` file. Finally, exclusion +patterns are applied to remove matching packages. + +Inclusion and 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:: + + 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 parameters, 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. + +``find_namespace_packages()`` +----------------------------- +In Python 3.3+, ``setuptools`` also provides the ``find_namespace_packages`` variant +of ``find_packages``, which has the same function signature as +``find_packages``, but works with `PEP 420`_ compliant implicit namespace +packages. Here is a minimal setup script using ``find_namespace_packages``:: + + from setuptools import setup, find_namespace_packages + setup( + name="HelloWorld", + version="0.1", + packages=find_namespace_packages(), + ) + + +Keep in mind that according to PEP 420, you may have to either re-organize your +codebase a bit or define a few exclusions, as the definition of an implicit +namespace package is quite lenient, so for a project organized like so:: + + + ├── namespace + │   └── mypackage + │   ├── __init__.py + │   └── mod1.py + ├── setup.py + └── tests + └── test_mod1.py + +A naive ``find_namespace_packages()`` would install both ``namespace.mypackage`` and a +top-level package called ``tests``! One way to avoid this problem is to use the +``include`` keyword to whitelist the packages to include, like so:: + + from setuptools import setup, find_namespace_packages + + setup( + name="namespace.mypackage", + version="0.1", + packages=find_namespace_packages(include=["namespace.*"]) + ) + +Another option is to use the "src" layout, where all package code is placed in +the ``src`` directory, like so:: + + + ├── setup.py + ├── src + │   └── namespace + │   └── mypackage + │   ├── __init__.py + │   └── mod1.py + └── tests + └── test_mod1.py + +With this layout, the package directory is specified as ``src``, as such:: + + setup(name="namespace.mypackage", + version="0.1", + package_dir={"": "src"}, + packages=find_namespace_packages(where="src")) + +.. _PEP 420: https://www.python.org/dev/peps/pep-0420/ + +Automatic Script Creation +========================= + +Packaging and installing scripts can be a bit awkward with the distutils. For +one thing, there's no easy way to have a script's filename match local +conventions on both Windows and POSIX platforms. For another, you often have +to create a separate file just for the "main" script, when your actual "main" +is a function in a module somewhere. And even in Python 2.4, using the ``-m`` +option only works for actual ``.py`` files that aren't installed in a package. + +``setuptools`` fixes all of these problems by automatically generating scripts +for you with the correct extension, and on Windows it will even create an +``.exe`` file so that users don't have to change their ``PATHEXT`` settings. +The way to use this feature is to define "entry points" in your setup script +that indicate what function the generated script should import and run. For +example, to create two console scripts called ``foo`` and ``bar``, and a GUI +script called ``baz``, you might do something like this:: + + setup( + # other arguments here... + entry_points={ + "console_scripts": [ + "foo = my_package.some_module:main_func", + "bar = other_module:some_func", + ], + "gui_scripts": [ + "baz = my_package_gui:start_func", + ] + } + ) + +When this project is installed on non-Windows platforms (using "setup.py +install", "setup.py develop", or with pip), a set of ``foo``, ``bar``, +and ``baz`` scripts will be installed that import ``main_func`` and +``some_func`` from the specified modules. The functions you specify are +called with no arguments, and their return value is passed to +``sys.exit()``, so you can return an errorlevel or message to print to +stderr. + +On Windows, a set of ``foo.exe``, ``bar.exe``, and ``baz.exe`` launchers are +created, alongside a set of ``foo.py``, ``bar.py``, and ``baz.pyw`` files. The +``.exe`` wrappers find and execute the right version of Python to run the +``.py`` or ``.pyw`` file. + +You may define as many "console script" and "gui script" entry points as you +like, and each one can optionally specify "extras" that it depends on, that +will be added to ``sys.path`` when the script is run. For more information on +"extras", see the section below on `Declaring Extras`_. For more information +on "entry points" in general, see the section below on `Dynamic Discovery of +Services and Plugins`_. + +"Eggsecutable" Scripts +---------------------- + +.. deprecated:: 45.3.0 + +Occasionally, there are situations where it's desirable to make an ``.egg`` +file directly executable. You can do this by including an entry point such +as the following:: + + setup( + # other arguments here... + entry_points={ + "setuptools.installation": [ + "eggsecutable = my_package.some_module:main_func", + ] + } + ) + +Any eggs built from the above setup script will include a short executable +prelude that imports and calls ``main_func()`` from ``my_package.some_module``. +The prelude can be run on Unix-like platforms (including Mac and Linux) by +invoking the egg with ``/bin/sh``, or by enabling execute permissions on the +``.egg`` file. For the executable prelude to run, the appropriate version of +Python must be available via the ``PATH`` environment variable, under its +"long" name. That is, if the egg is built for Python 2.3, there must be a +``python2.3`` executable present in a directory on ``PATH``. + +IMPORTANT NOTE: Eggs with an "eggsecutable" header cannot be renamed, or +invoked via symlinks. They *must* be invoked using their original filename, in +order to ensure that, once running, ``pkg_resources`` will know what project +and version is in use. The header script will check this and exit with an +error if the ``.egg`` file has been renamed or is invoked via a symlink that +changes its base name. + +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 pip 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 ``-``. + +Version specifiers for a given project are internally sorted into ascending +version order, and used to establish what ranges of versions are acceptable. +Adjacent redundant conditions are also consolidated (e.g. ``">1, >2"`` becomes +``">2"``, and ``"<2,<3"`` becomes ``"<2"``). ``"!="`` versions are excised from +the ranges they fall within. A project's version is then checked for +membership in the resulting ranges. (Note that providing conflicting conditions +for the same version (e.g. "<2,>=2" or "==2,!=2") is meaningless and may +therefore produce bizarre results.) + +Here are some example requirement specifiers:: + + 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 pip, ``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. + +2. 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). + +3. 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``.) + +Dependencies that aren't in PyPI +-------------------------------- + +.. warning:: + Dependency links support has been dropped by pip starting with version + 19.0 (released 2019-01-22). + +If your project depends on packages that don't exist on PyPI, you may still be +able to depend on them, as long as they are available for download as: + +- an egg, in the standard distutils ``sdist`` format, +- a single ``.py`` file, or +- a VCS repository (Subversion, Mercurial, or Git). + +You just need to add some URLs to the ``dependency_links`` argument to +``setup()``. + +The URLs must be either: + +1. direct download URLs, +2. the URLs of web pages that contain direct download links, or +3. the repository's URL + +In general, it's better to link to web pages, because it is usually less +complex to update a web page than to release a new version of your project. +You can also use a SourceForge ``showfiles.php`` link in the case where a +package you depend on is distributed via SourceForge. + +If you depend on a package that's distributed as a single ``.py`` file, you +must include an ``"#egg=project-version"`` suffix to the URL, to give a project +name and version number. (Be sure to escape any dashes in the name or version +by replacing them with underscores.) EasyInstall will recognize this suffix +and automatically create a trivial ``setup.py`` to wrap the single ``.py`` file +as an egg. + +In the case of a VCS checkout, you should also append ``#egg=project-version`` +in order to identify for what package that checkout should be used. You can +append ``@REV`` to the URL's path (before the fragment) to specify a revision. +Additionally, you can also force the VCS being used by prepending the URL with +a certain prefix. Currently available are: + +- ``svn+URL`` for Subversion, +- ``git+URL`` for Git, and +- ``hg+URL`` for Mercurial + +A more complete example would be: + + ``vcs+proto://host/path@revision#egg=project-version`` + +Be careful with the version. It should match the one inside the project files. +If you want to disregard the version, you have to omit it both in the +``requires`` and in the URL's fragment. + +This will do a checkout (or a clone, in Git and Mercurial parlance) to a +temporary folder and run ``setup.py bdist_egg``. + +The ``dependency_links`` option takes the form of a list of URL strings. For +example, this will cause a search of the specified page for eggs or source +distributions, if the package's dependencies aren't already installed:: + + setup( + ... + dependency_links=[ + "http://peak.telecommunity.com/snapshots/" + ], + ) + + +.. _Declaring Extras: + + +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:: + + setup( + name="Project-A", + ... + extras_require={ + "PDF": ["ReportLab>=1.2", "RXP"], + "reST": ["docutils>=0.3"], + } + ) + +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 "pip install" +command line.) + +Extras can be used by a project's `entry points`_ to specify dynamic +dependencies. For example, if Project A includes a "rst2pdf" script, it might +declare it like this, so that the "PDF" requirements are only resolved if the +"rst2pdf" script is run:: + + setup( + name="Project-A", + ... + entry_points={ + "console_scripts": [ + "rst2pdf = project_a.tools.pdfgen [PDF]", + "rst2html = project_a.tools.htmlgen", + # more script entry points ... + ], + } + ) + +Projects can also use another project's extras when specifying dependencies. +For example, if project B needs "project A" with PDF support installed, it +might declare the dependency like this:: + + 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. + +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 could change its +setup to this:: + + 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. + +.. _Platform Specific Dependencies: + + +Declaring platform specific dependencies +---------------------------------------- + +Sometimes a project might require a dependency to run on a specific platform. +This could to a package that back ports a module so that it can be used in +older python versions. Or it could be a package that is required to run on a +specific operating system. This will allow a project to work on multiple +different platforms without installing dependencies that are not required for +a platform that is installing the project. + +For example, here is a project that uses the ``enum`` module and ``pywin32``:: + + setup( + name="Project", + ... + install_requires=[ + "enum34;python_version<'3.4'", + "pywin32 >= 1.0;platform_system=='Windows'" + ] + ) + +Since the ``enum`` module was added in Python 3.4, it should only be installed +if the python version is earlier. Since ``pywin32`` will only be used on +windows, it should only be installed when the operating system is Windows. +Specifying version requirements for the dependencies is supported as normal. + +The environmental markers that may be used for testing platform types are +detailed in `PEP 508`_. + +.. _PEP 508: https://www.python.org/dev/peps/pep-0508/ + +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 offers three ways to specify data files to be included in your +packages. First, you can simply use the ``include_package_data`` keyword, +e.g.:: + + from setuptools import setup, find_packages + setup( + ... + include_package_data=True + ) + +This tells setuptools to install any data files it finds in your packages. +The data files must be specified via the distutils' ``MANIFEST.in`` file. +(They can also be tracked by a revision control system, using an appropriate +plugin. See the section below on `Adding Support for Revision Control +Systems`_ for information on how to write such plugins.) + +If you want finer-grained control over what files are included (for example, +if you have documentation files in your package directories and want to exclude +them from installation), then you can also use the ``package_data`` keyword, +e.g.:: + + 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:: + + setup.py + src/ + mypkg/ + __init__.py + mypkg.txt + data/ + somefile.dat + otherdata.dat + +The setuptools setup file might look like this:: + + 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. + +If datafiles are contained in a subdirectory of a package that isn't a package +itself (no ``__init__.py``), then the subdirectory names (or ``*``) are required +in the ``package_data`` argument (as shown above with ``"data/*.dat"``). + +When building an ``sdist``, the datafiles are also drawn from the +``package_name.egg-info/SOURCES.txt`` file, so make sure that this is removed if +the ``setup.py`` ``package_data`` list is updated before calling ``setup.py``. + +(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 `some documentation for the feature`__ available on the +python.org website. If using the setuptools-specific ``include_package_data`` +argument, files specified by ``package_data`` will *not* be automatically +added to the manifest unless they are listed in the MANIFEST.in file.) + +__ https://docs.python.org/3/distutils/setupscript.html#installing-package-data + +Sometimes, the ``include_package_data`` or ``package_data`` options alone +aren't sufficient to precisely define what files you want included. For +example, you may want to include package README files in your revision control +system and source distributions, but exclude them from being installed. So, +setuptools offers an ``exclude_package_data`` option as well, that allows you +to do things like this:: + + 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 + + include_package_data=True, # include everything in source control + + # ...but exclude README.txt from all packages + exclude_package_data={"": ["README.txt"]}, + ) + +The ``exclude_package_data`` option is a dictionary mapping package names to +lists of wildcard patterns, just like the ``package_data`` option. And, just +as with that option, a key of ``""`` will apply the given pattern(s) to all +packages. However, any files that match these patterns will be *excluded* +from installation, even if they were listed in ``package_data`` or were +included as a result of using ``include_package_data``. + +In summary, the three options allow you to: + +``include_package_data`` + Accept all data files and directories matched by ``MANIFEST.in``. + +``package_data`` + Specify additional patterns to match files that may or may + not be matched by ``MANIFEST.in`` or found in source control. + +``exclude_package_data`` + Specify patterns for data files and directories that should *not* be + included when a package is installed, even if they would otherwise have + been included due to the use of the preceding options. + +NOTE: Due to the way the distutils build process works, a data file that you +include in your project and then stop including may be "orphaned" in your +project's build directories, requiring you to run ``setup.py clean --all`` to +fully remove them. This may also be important for your users and contributors +if they track intermediate revisions of your project using Subversion; be sure +to let them know when you make changes that remove files from inclusion so they +can run ``setup.py clean --all``. + +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 :ref:`ResourceManager 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 `Importlib Resources`_ for +a quick example of converting code that uses ``__file__`` to use +``pkg_resources`` instead. + +.. _Importlib Resources: https://docs.python.org/3/library/importlib.html#module-importlib.resources + + +Non-Package Data Files +---------------------- + +Historically, ``setuptools`` by way of ``easy_install`` would encapsulate data +files from the distribution into the egg (see `the old docs +`_). As eggs are deprecated and pip-based installs +fall back to the platform-specific location for installing data files, there is +no supported facility to reliably retrieve these resources. + +Instead, the PyPA recommends that any data files you wish to be accessible at +run time be included in the package. + + +Automatic Resource Extraction +----------------------------- + +If you are using tools that expect your resources to be "real" files, or your +project includes non-extension native libraries or other files that your C +extensions expect to be able to access, you may need to list those files in +the ``eager_resources`` argument to ``setup()``, so that the files will be +extracted together, whenever a C extension in the project is imported. + +This is especially important if your project includes shared libraries *other* +than distutils-built C extensions, and those shared libraries use file +extensions other than ``.dll``, ``.so``, or ``.dylib``, which are the +extensions that setuptools 0.6a8 and higher automatically detects as shared +libraries and adds to the ``native_libs.txt`` file for you. Any shared +libraries whose names do not end with one of those extensions should be listed +as ``eager_resources``, because they need to be present in the filesystem when +he C extensions that link to them are used. + +The ``pkg_resources`` runtime for compressed packages will automatically +extract *all* C extensions and ``eager_resources`` at the same time, whenever +*any* C extension or eager resource is requested via the ``resource_filename()`` +API. (C extensions are imported using ``resource_filename()`` internally.) +This ensures that C extensions will see all of the "real" files that they +expect to see. + +Note also that you can list directory resource names in ``eager_resources`` as +well, in which case the directory's contents (including subdirectories) will be +extracted whenever any C extension or eager resource is requested. + +Please note that if you're not sure whether you need to use this argument, you +don't! It's really intended to support projects with lots of non-Python +dependencies and as a last resort for crufty projects that can't otherwise +handle being compressed. If your package is pure Python, Python plus data +files, or Python plus C, you really don't need this. You've got to be using +either C or an external program that needs "real" files in your project before +there's any possibility of ``eager_resources`` being relevant to your project. + + +Extensible Applications and Frameworks +====================================== + + +.. _Entry Points: + +Dynamic Discovery of Services and Plugins +----------------------------------------- + +``setuptools`` supports creating libraries that "plug in" to extensible +applications and frameworks, by letting you register "entry points" in your +project that can be imported by the application or framework. + +For example, suppose that a blogging tool wants to support plugins +that provide translation for various file types to the blog's output format. +The framework might define an "entry point group" called ``blogtool.parsers``, +and then allow plugins to register entry points for the file extensions they +support. + +This would allow people to create distributions that contain one or more +parsers for different file types, and then the blogging tool would be able to +find the parsers at runtime by looking up an entry point for the file +extension (or mime type, or however it wants to). + +Note that if the blogging tool includes parsers for certain file formats, it +can register these as entry points in its own setup script, which means it +doesn't have to special-case its built-in formats. They can just be treated +the same as any other plugin's entry points would be. + +If you're creating a project that plugs in to an existing application or +framework, you'll need to know what entry points or entry point groups are +defined by that application or framework. Then, you can register entry points +in your setup script. Here are a few examples of ways you might register an +``.rst`` file parser entry point in the ``blogtool.parsers`` entry point group, +for our hypothetical blogging tool:: + + setup( + # ... + entry_points={"blogtool.parsers": ".rst = some_module:SomeClass"} + ) + + setup( + # ... + entry_points={"blogtool.parsers": [".rst = some_module:a_func"]} + ) + + setup( + # ... + entry_points=""" + [blogtool.parsers] + .rst = some.nested.module:SomeClass.some_classmethod [reST] + """, + extras_require=dict(reST="Docutils>=0.3.5") + ) + +The ``entry_points`` argument to ``setup()`` accepts either a string with +``.ini``-style sections, or a dictionary mapping entry point group names to +either strings or lists of strings containing entry point specifiers. An +entry point specifier consists of a name and value, separated by an ``=`` +sign. The value consists of a dotted module name, optionally followed by a +``:`` and a dotted identifier naming an object within the module. It can +also include a bracketed list of "extras" that are required for the entry +point to be used. When the invoking application or framework requests loading +of an entry point, any requirements implied by the associated extras will be +passed to ``pkg_resources.require()``, so that an appropriate error message +can be displayed if the needed package(s) are missing. (Of course, the +invoking app or framework can ignore such errors if it wants to make an entry +point optional if a requirement isn't installed.) + +Defining Additional Metadata +---------------------------- + +Some extensible applications and frameworks may need to define their own kinds +of metadata to include in eggs, which they can then access using the +``pkg_resources`` metadata APIs. Ordinarily, this is done by having plugin +developers include additional files in their ``ProjectName.egg-info`` +directory. However, since it can be tedious to create such files by hand, you +may want to create a distutils extension that will create the necessary files +from arguments to ``setup()``, in much the same way that ``setuptools`` does +for many of the ``setup()`` arguments it adds. See the section below on +`Creating distutils Extensions`_ for more details, especially the subsection on +`Adding new EGG-INFO Files`_. + + +"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``, 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. + +If you have enabled the ``use_2to3`` flag, then of course the ``.egg-link`` +will not link directly to your source code when run under Python 3, since +that source code would be made for Python 2 and not work under Python 3. +Instead the ``setup.py develop`` will build Python 3 code under the ``build`` +directory, and link there. This means that after doing code changes you will +have to run ``setup.py build`` before these changes are picked up by your +Python 3 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. + +Note that you can also apply setuptools commands to non-setuptools projects, +using commands like this:: + + python -c "import setuptools; with open('setup.py') as f: exec(compile(f.read(), 'setup.py', 'exec'))" develop + +That is, you can simply list the normal setup commands and options following +the quoted part. + + +Distributing a ``setuptools``-based project +=========================================== + +Detailed instructions to distribute a setuptools project can be found at +`Packaging project tutorials`_. + +.. _Packaging project tutorials: https://packaging.python.org/tutorials/packaging-projects/#generating-distribution-archives + +Before you begin, make sure you have the latest versions of setuptools and wheel:: + + pip install --upgrade setuptools wheel + +To build a setuptools project, run this command from the same directory where +setup.py is located:: + + setup.py sdist bdist_wheel + +This will generate distribution archives in the `dist` directory. + +Before you upload the generated archives make sure you're registered on +https://test.pypi.org/account/register/. You will also need to verify your email +to be able to upload any packages. +You should install twine to be able to upload packages:: + + pip install --upgrade twine + +Now, to upload these archives, run:: + + twine upload --repository-url https://test.pypi.org/legacy/ dist/* + +To install your newly uploaded package ``example_pkg``, you can use pip:: + + pip install --index-url https://test.pypi.org/simple/ example_pkg + +If you have issues at any point, please refer to `Packaging project tutorials`_ +for clarification. + + +Setting the ``zip_safe`` flag +----------------------------- + +For some use cases (such as bundling as part of a larger application), Python +packages may be run directly from a zip file. +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. + +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`` to try to guess +whether your project can work as a zipfile. + +.. _Namespace Packages: + +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 then 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. The argument should list the namespace packages that the egg +participates in. For example, the ZopeInterface project might do this:: + + 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. When these projects are +installed and used, Python will see them both as part of a "virtual" ``zope`` +package, even though they will be installed in different locations. + +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 +*must* contain the line:: + + __import__("pkg_resources").declare_namespace(__name__) + +This code ensures that the namespace package machinery is operating and that +the current package is registered as a namespace package. + +You must NOT include any other code and data in a namespace package's +``__init__.py``. Even though it may appear to work during development, or when +projects are installed as ``.egg`` files, it will not work when the projects +are installed using "system" packaging tools -- in such cases the +``__init__.py`` files will not be installed, let alone executed. + +You must include the ``declare_namespace()`` line in the ``__init__.py`` of +*every* project that has contents for the namespace package in question, in +order to ensure that the namespace will be declared regardless of which +project's copy of ``__init__.py`` is loaded first. If the first loaded +``__init__.py`` doesn't declare it, it will never *be* declared, because no +other copies will ever be loaded! + +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: + +* A manually-specified pre-release tag, such as "build" or "dev", or a + manually-specified post-release tag, such as a build or revision number + (``--tag-build=STRING, -bSTRING``) + +* An 8-character representation of the build date (``--tag-date, -d``), as + a postrelease tag + +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, before you release your project, be sure to see the section above on +`Specifying Your Project's Version`_ for more information about how pre- and +post-release tags affect how version numbers are interpreted. This is +important in order to make sure that dependency processing tools will know +which versions of your project are newer than others.) + +Finally, 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:: + + 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 script or 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 with pluggable endpoints for looking up files to include. If you are +using a revision control system, and your source distributions only need to +include files that you're tracking in revision control, use a corresponding +plugin instead of writing a ``MANIFEST.in`` file. See the section below on +`Adding Support for Revision Control Systems`_ for information on plugins. + +If you need to include automatically generated files, or files that are kept in +an unsupported revision control system, you'll need to create a ``MANIFEST.in`` +file to specify any files that the default file location algorithm doesn't +catch. See the distutils documentation for more information on the format of +the ``MANIFEST.in`` file. + +But, be sure to ignore any part of the distutils documentation that deals with +``MANIFEST`` or how it's generated from ``MANIFEST.in``; setuptools shields you +from these issues and doesn't work the same way in any case. Unlike the +distutils, setuptools regenerates the source distribution manifest file +every time you build a source distribution, and it builds it inside the +project's ``.egg-info`` directory, out of the way of your main project +directory. You therefore need not worry about whether it is up-to-date or not. + +Indeed, because setuptools' approach to determining the contents of a source +distribution is so much simpler, its ``sdist`` command omits nearly all of +the options that the distutils' more complex ``sdist`` process requires. For +all practical purposes, you'll probably use only the ``--formats`` option, if +you use any option at all. + + +Making "Official" (Non-Snapshot) Releases +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When you make an official release, creating source or binary distributions, +you will need to override the tag settings from ``setup.cfg``, so that you +don't end up registering versions like ``foobar-0.7a1.dev-r34832``. This is +easy to do if you are developing on the trunk and using tags or branches for +your releases - just make the change to ``setup.cfg`` after branching or +tagging the release, so the trunk will still produce development snapshots. + +Alternately, if you are not branching for releases, you can override the +default version options on the command line, using something like:: + + setup.py egg_info -Db "" sdist bdist_egg + +The first part of this command (``egg_info -Db ""``) will override the +configured tag information, before creating source and binary eggs. Thus, these +commands will use the plain version from your ``setup.py``, without adding the +build designation string. + +Of course, if you will be doing this a lot, you may wish to create a personal +alias for this operation, e.g.:: + + setup.py alias -u release egg_info -Db "" + +You can then use it like this:: + + setup.py release sdist bdist_egg + +Or of course you can create more elaborate aliases that do all of the above. +See the sections below on the `egg_info`_ and `alias`_ commands for more ideas. + +Distributing Extensions compiled with Cython +-------------------------------------------- + +``setuptools`` will detect at build time whether Cython is installed or not. +If Cython is not found ``setuptools`` will ignore pyx files. + +To ensure Cython is available, include Cython in the build-requires section +of your pyproject.toml:: + + [build-system] + requires=[..., "cython"] + +Built with pip 10 or later, that declaration is sufficient to include Cython +in the build. For broader compatibility, declare the dependency in your +setup-requires of setup.cfg:: + + [options] + setup_requires = + ... + cython + +As long as Cython is present in the build environment, ``setuptools`` includes +transparent support for building Cython extensions, as +long as extensions are defined using ``setuptools.Extension``. + +If you follow these rules, you can safely list ``.pyx`` files as the source +of your ``Extension`` objects in the setup script. If it is, then ``setuptools`` +will use it. + +Of course, for this to work, your source distributions must include the C +code generated by Cython, 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 a revision +control system will be able to build it even if they don't have Cython +installed, and that your source releases will be similarly usable with or +without Cython. + +-------------------------------- +Extending and Reusing Setuptools +-------------------------------- + +Creating ``distutils`` Extensions +================================= + +It can be hard to add new commands or setup arguments to the distutils. But +the ``setuptools`` package makes it a bit easier, by allowing you to distribute +a distutils extension as a separate project, and then have projects that need +the extension just refer to it in their ``setup_requires`` argument. + +With ``setuptools``, your distutils extension projects can hook in new +commands and ``setup()`` arguments just by defining "entry points". These +are mappings from command or argument names to a specification of where to +import a handler from. (See the section on `Dynamic Discovery of Services and +Plugins`_ above for some more background on entry points.) + + +Adding Commands +--------------- + +You can add new ``setup`` commands by defining entry points in the +``distutils.commands`` group. For example, if you wanted to add a ``foo`` +command, you might add something like this to your distutils extension +project's setup script:: + + setup( + # ... + entry_points={ + "distutils.commands": [ + "foo = mypackage.some_module:foo", + ], + }, + ) + +(Assuming, of course, that the ``foo`` class in ``mypackage.some_module`` is +a ``setuptools.Command`` subclass.) + +Once a project containing such entry points has been activated on ``sys.path``, +(e.g. by running "install" or "develop" with a site-packages installation +directory) the command(s) will be available to any ``setuptools``-based setup +scripts. It is not necessary to use the ``--command-packages`` option or +to monkeypatch the ``distutils.command`` package to install your commands; +``setuptools`` automatically adds a wrapper to the distutils to search for +entry points in the active distributions on ``sys.path``. In fact, this is +how setuptools' own commands are installed: the setuptools project's setup +script defines entry points for them! + +Adding ``setup()`` Arguments +---------------------------- + +.. warning:: Adding arguments to setup is discouraged as such arguments + are only supported through imperative execution and not supported through + declarative config. + +Sometimes, your commands may need additional arguments to the ``setup()`` +call. You can enable this by defining entry points in the +``distutils.setup_keywords`` group. For example, if you wanted a ``setup()`` +argument called ``bar_baz``, you might add something like this to your +distutils extension project's setup script:: + + setup( + # ... + entry_points={ + "distutils.commands": [ + "foo = mypackage.some_module:foo", + ], + "distutils.setup_keywords": [ + "bar_baz = mypackage.some_module:validate_bar_baz", + ], + }, + ) + +The idea here is that the entry point defines a function that will be called +to validate the ``setup()`` argument, if it's supplied. The ``Distribution`` +object will have the initial value of the attribute set to ``None``, and the +validation function will only be called if the ``setup()`` call sets it to +a non-None value. Here's an example validation function:: + + def assert_bool(dist, attr, value): + """Verify that value is True, False, 0, or 1""" + if bool(value) != value: + raise DistutilsSetupError( + "%r must be a boolean value (got %r)" % (attr,value) + ) + +Your function should accept three arguments: the ``Distribution`` object, +the attribute name, and the attribute value. It should raise a +``DistutilsSetupError`` (from the ``distutils.errors`` module) if the argument +is invalid. Remember, your function will only be called with non-None values, +and the default value of arguments defined this way is always None. So, your +commands should always be prepared for the possibility that the attribute will +be ``None`` when they access it later. + +If more than one active distribution defines an entry point for the same +``setup()`` argument, *all* of them will be called. This allows multiple +distutils extensions to define a common argument, as long as they agree on +what values of that argument are valid. + +Also note that as with commands, it is not necessary to subclass or monkeypatch +the distutils ``Distribution`` class in order to add your arguments; it is +sufficient to define the entry points in your extension, as long as any setup +script using your extension lists your project in its ``setup_requires`` +argument. + + +Customizing Distribution Options +-------------------------------- + +Plugins may wish to extend or alter the options on a Distribution object to +suit the purposes of that project. For example, a tool that infers the +``Distribution.version`` from SCM-metadata may need to hook into the +option finalization. To enable this feature, Setuptools offers an entry +point "setuptools.finalize_distribution_options". That entry point must +be a callable taking one argument (the Distribution instance). + +If the callable has an ``.order`` property, that value will be used to +determine the order in which the hook is called. Lower numbers are called +first and the default is zero (0). + +Plugins may read, alter, and set properties on the distribution, but each +plugin is encouraged to load the configuration/settings for their behavior +independently. + + +Adding new EGG-INFO Files +------------------------- + +Some extensible applications or frameworks may want to allow third parties to +develop plugins with application or framework-specific metadata included in +the plugins' EGG-INFO directory, for easy access via the ``pkg_resources`` +metadata API. The easiest way to allow this is to create a distutils extension +to be used from the plugin projects' setup scripts (via ``setup_requires``) +that defines a new setup keyword, and then uses that data to write an EGG-INFO +file when the ``egg_info`` command is run. + +The ``egg_info`` command looks for extension points in an ``egg_info.writers`` +group, and calls them to write the files. Here's a simple example of a +distutils extension defining a setup argument ``foo_bar``, which is a list of +lines that will be written to ``foo_bar.txt`` in the EGG-INFO directory of any +project that uses the argument:: + + setup( + # ... + entry_points={ + "distutils.setup_keywords": [ + "foo_bar = setuptools.dist:assert_string_list", + ], + "egg_info.writers": [ + "foo_bar.txt = setuptools.command.egg_info:write_arg", + ], + }, + ) + +This simple example makes use of two utility functions defined by setuptools +for its own use: a routine to validate that a setup keyword is a sequence of +strings, and another one that looks up a setup argument and writes it to +a file. Here's what the writer utility looks like:: + + def write_arg(cmd, basename, filename): + argname = os.path.splitext(basename)[0] + value = getattr(cmd.distribution, argname, None) + if value is not None: + value = "\n".join(value) + "\n" + cmd.write_or_delete_file(argname, filename, value) + +As you can see, ``egg_info.writers`` entry points must be a function taking +three arguments: a ``egg_info`` command instance, the basename of the file to +write (e.g. ``foo_bar.txt``), and the actual full filename that should be +written to. + +In general, writer functions should honor the command object's ``dry_run`` +setting when writing files, and use the ``distutils.log`` object to do any +console output. The easiest way to conform to this requirement is to use +the ``cmd`` object's ``write_file()``, ``delete_file()``, and +``write_or_delete_file()`` methods exclusively for your file operations. See +those methods' docstrings for more details. + +Adding Support for Revision Control Systems +------------------------------------------------- + +If the files you want to include in the source distribution are tracked using +Git, Mercurial or SVN, you can use the following packages to achieve that: + +- Git and Mercurial: `setuptools_scm `_ +- SVN: `setuptools_svn `_ + +If you would like to create a plugin for ``setuptools`` to find files tracked +by another revision control system, you can do so by adding an entry point to +the ``setuptools.file_finders`` group. The entry point should be a function +accepting a single directory name, and should yield all the filenames within +that directory (and any subdirectories thereof) that are under revision +control. + +For example, if you were going to create a plugin for a revision control system +called "foobar", you would write a function something like this: + +.. code-block:: python + + def find_files_for_foobar(dirname): + # loop to yield paths that start with `dirname` + +And you would register it in a setup script using something like this:: + + entry_points={ + "setuptools.file_finders": [ + "foobar = my_foobar_module:find_files_for_foobar", + ] + } + +Then, anyone who wants to use your plugin can simply install it, and their +local setuptools installation will be able to find the necessary files. + +It is not necessary to distribute source control plugins with projects that +simply use the other source control system, or to specify the plugins in +``setup_requires``. When you create a source distribution with the ``sdist`` +command, setuptools automatically records what files were found in the +``SOURCES.txt`` file. That way, recipients of source distributions don't need +to have revision control at all. However, if someone is working on a package +by checking out with that system, they will need the same plugin(s) that the +original author is using. + +A few important points for writing revision control file finders: + +* Your finder function MUST return relative paths, created by appending to the + passed-in directory name. Absolute paths are NOT allowed, nor are relative + paths that reference a parent directory of the passed-in directory. + +* Your finder function MUST accept an empty string as the directory name, + meaning the current directory. You MUST NOT convert this to a dot; just + yield relative paths. So, yielding a subdirectory named ``some/dir`` under + the current directory should NOT be rendered as ``./some/dir`` or + ``/somewhere/some/dir``, but *always* as simply ``some/dir`` + +* Your finder function SHOULD NOT raise any errors, and SHOULD deal gracefully + with the absence of needed programs (i.e., ones belonging to the revision + control system itself. It *may*, however, use ``distutils.log.warn()`` to + inform the user of the missing program(s). \ No newline at end of file -- cgit v1.2.1 From 39206c05f07bc8ef754b789f2bcad3404f32df98 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Mon, 11 May 2020 14:48:05 -0400 Subject: docs: add functionality entry in userguide index --- docs/userguide/index.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/index.txt b/docs/userguide/index.txt index 901aad42..7e6b7f8a 100644 --- a/docs/userguide/index.txt +++ b/docs/userguide/index.txt @@ -14,5 +14,6 @@ ordinary Python packages based on the ``distutils``. :maxdepth: 1 Quickstart + Functionalities keyword reference - Command reference \ No newline at end of file + Command reference -- cgit v1.2.1 From 086c2a3fc52f508bc69b2ee4846aea39c646d887 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Mon, 11 May 2020 14:50:26 -0400 Subject: docs: migrate declarative config to separate file cut and paste from setuptools.txt --- docs/userguide/declarative_config.txt | 240 ++++++++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 docs/userguide/declarative_config.txt (limited to 'docs/userguide') diff --git a/docs/userguide/declarative_config.txt b/docs/userguide/declarative_config.txt new file mode 100644 index 00000000..b40d3a4a --- /dev/null +++ b/docs/userguide/declarative_config.txt @@ -0,0 +1,240 @@ +----------------------------------------- +Configuring setup() using setup.cfg files +----------------------------------------- + +.. note:: New in 30.3.0 (8 Dec 2016). + +.. important:: + If compatibility with legacy builds (i.e. those not using the :pep:`517` + build API) is desired, a ``setup.py`` file containing a ``setup()`` function + call is still required even if your configuration resides in ``setup.cfg``. + +``Setuptools`` allows using configuration files (usually :file:`setup.cfg`) +to define a package’s metadata and other options that are normally supplied +to the ``setup()`` function (declarative config). + +This approach not only allows automation scenarios but also reduces +boilerplate code in some cases. + +.. note:: + + This implementation has limited compatibility with the distutils2-like + ``setup.cfg`` sections used by the ``pbr`` and ``d2to1`` packages. + + Namely: only metadata-related keys from ``metadata`` section are supported + (except for ``description-file``); keys from ``files``, ``entry_points`` + and ``backwards_compat`` are not supported. + + +.. code-block:: ini + + [metadata] + name = my_package + version = attr: src.VERSION + description = My package description + long_description = file: README.rst, CHANGELOG.rst, LICENSE.rst + keywords = one, two + license = BSD 3-Clause License + classifiers = + Framework :: Django + License :: OSI Approved :: BSD License + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.5 + + [options] + zip_safe = False + include_package_data = True + packages = find: + scripts = + bin/first.py + bin/second.py + install_requires = + requests + importlib; python_version == "2.6" + + [options.package_data] + * = *.txt, *.rst + hello = *.msg + + [options.extras_require] + pdf = ReportLab>=1.2; RXP + rest = docutils>=0.3; pack ==1.1, ==1.3 + + [options.packages.find] + exclude = + src.subpackage1 + src.subpackage2 + + [options.data_files] + /etc/my_package = + site.d/00_default.conf + host.d/00_default.conf + data = data/img/logo.png, data/svg/icon.svg + +Metadata and options are set in the config sections of the same name. + +* Keys are the same as the keyword arguments one provides to the ``setup()`` + function. + +* Complex values can be written comma-separated or placed one per line + in *dangling* config values. The following are equivalent: + + .. code-block:: ini + + [metadata] + keywords = one, two + + [metadata] + keywords = + one + two + +* In some cases, complex values can be provided in dedicated subsections for + clarity. + +* Some keys allow ``file:``, ``attr:``, and ``find:`` and ``find_namespace:`` directives in + order to cover common usecases. + +* Unknown keys are ignored. + + +Using a ``src/`` layout +======================= + +One commonly used package configuration has all the module source code in a +subdirectory (often called the ``src/`` layout), like this:: + + ├── src + │   └── mypackage + │   ├── __init__.py + │   └── mod1.py + ├── setup.py + └── setup.cfg + +You can set up your ``setup.cfg`` to automatically find all your packages in +the subdirectory like this: + +.. code-block:: ini + + # This example contains just the necessary options for a src-layout, set up + # the rest of the file as described above. + + [options] + package_dir= + =src + packages=find: + + [options.packages.find] + where=src + +Specifying values +================= + +Some values are treated as simple strings, some allow more logic. + +Type names used below: + +* ``str`` - simple string +* ``list-comma`` - dangling list or string of comma-separated values +* ``list-semi`` - dangling list or string of semicolon-separated values +* ``bool`` - ``True`` is 1, yes, true +* ``dict`` - list-comma where keys are separated from values by ``=`` +* ``section`` - values are read from a dedicated (sub)section + + +Special directives: + +* ``attr:`` - Value is read from a module attribute. ``attr:`` supports + callables and iterables; unsupported types are cast using ``str()``. +* ``file:`` - Value is read from a list of files and then concatenated + + +.. note:: + The ``file:`` directive is sandboxed and won't reach anything outside + the directory containing ``setup.py``. + + +Metadata +-------- + +.. note:: + The aliases given below are supported for compatibility reasons, + but their use is not advised. + +============================== ================= ================= =============== ===== +Key Aliases Type Minimum Version Notes +============================== ================= ================= =============== ===== +name str +version attr:, file:, str 39.2.0 (1) +url home-page str +download_url download-url str +project_urls dict 38.3.0 +author str +author_email author-email str +maintainer str +maintainer_email maintainer-email str +classifiers classifier file:, list-comma +license str +license_file str +license_files list-comma +description summary file:, str +long_description long-description file:, str +long_description_content_type str 38.6.0 +keywords list-comma +platforms platform list-comma +provides list-comma +requires list-comma +obsoletes list-comma +============================== ================= ================= =============== ===== + +.. note:: + A version loaded using the ``file:`` directive must comply with PEP 440. + It is easy to accidentally put something other than a valid version + string in such a file, so validation is stricter in this case. + +Notes: +1. The `version` file attribute has only been supported since 39.2.0. + +Options +------- + +======================= =================================== =============== ===== +Key Type Minimum Version Notes +======================= =================================== =============== ===== +zip_safe bool +setup_requires list-semi +install_requires list-semi +extras_require section +python_requires str +entry_points file:, section +use_2to3 bool +use_2to3_fixers list-comma +use_2to3_exclude_fixers list-comma +convert_2to3_doctests list-comma +scripts list-comma +eager_resources list-comma +dependency_links list-comma +tests_require list-semi +include_package_data bool +packages find:, find_namespace:, list-comma +package_dir dict +package_data section (1) +exclude_package_data section +namespace_packages list-comma +py_modules list-comma +data_files dict 40.6.0 +======================= =================================== =============== ===== + +.. note:: + + **packages** - The ``find:`` and ``find_namespace:`` directive can be further configured + in a dedicated subsection ``options.packages.find``. This subsection + accepts the same keys as the `setuptools.find_packages` and the + `setuptools.find_namespace_packages` function: + ``where``, ``include``, and ``exclude``. + + **find_namespace directive** - The ``find_namespace:`` directive is supported since Python >=3.3. + +Notes: +1. In the `package_data` section, a key named with a single asterisk (`*`) +refers to all packages, in lieu of the empty string used in `setup.py`. \ No newline at end of file -- cgit v1.2.1 From 0a0d6f19e799c53d37a8ce5fffc8cc5cee660712 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Mon, 11 May 2020 14:51:09 -0400 Subject: docs: add entry to userguide index --- docs/userguide/index.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'docs/userguide') diff --git a/docs/userguide/index.txt b/docs/userguide/index.txt index 7e6b7f8a..4d7bb2a7 100644 --- a/docs/userguide/index.txt +++ b/docs/userguide/index.txt @@ -15,5 +15,6 @@ ordinary Python packages based on the ``distutils``. Quickstart Functionalities + Declarative config keyword reference Command reference -- cgit v1.2.1 From c12db0915b4e3f0fae91d2a99dab467602c06dd6 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Wed, 13 May 2020 10:55:55 -0400 Subject: docs: migrated section for versioning from quickstart.txt to functionalities.txt --- docs/userguide/functionalities.txt | 87 +++++++++++++++++++++++++++++++++++++- docs/userguide/quickstart.txt | 84 ------------------------------------ 2 files changed, 86 insertions(+), 85 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/functionalities.txt b/docs/userguide/functionalities.txt index a310da97..7bd3ae8a 100644 --- a/docs/userguide/functionalities.txt +++ b/docs/userguide/functionalities.txt @@ -1335,4 +1335,89 @@ A few important points for writing revision control file finders: * Your finder function SHOULD NOT raise any errors, and SHOULD deal gracefully with the absence of needed programs (i.e., ones belonging to the revision control system itself. It *may*, however, use ``distutils.log.warn()`` to - inform the user of the missing program(s). \ No newline at end of file + inform the user of the missing program(s). + +Specifying Your Project's Version +--------------------------------- + +Setuptools can work well with most versioning schemes; there are, however, a +few special things to watch out for, in order to ensure that setuptools and +other tools can always tell what version of your package is newer than another +version. Knowing these things will also help you correctly specify what +versions of other projects your project depends on. + +A version consists of an alternating series of release numbers and pre-release +or post-release tags. A release number is a series of digits punctuated by +dots, such as ``2.4`` or ``0.5``. Each series of digits is treated +numerically, so releases ``2.1`` and ``2.1.0`` are different ways to spell the +same release number, denoting the first subrelease of release 2. But ``2.10`` +is the *tenth* subrelease of release 2, and so is a different and newer release +from ``2.1`` or ``2.1.0``. Leading zeros within a series of digits are also +ignored, so ``2.01`` is the same as ``2.1``, and different from ``2.0.1``. + +Following a release number, you can have either a pre-release or post-release +tag. Pre-release tags make a version be considered *older* than the version +they are appended to. So, revision ``2.4`` is *newer* than revision ``2.4c1``, +which in turn is newer than ``2.4b1`` or ``2.4a1``. Postrelease tags make +a version be considered *newer* than the version they are appended to. So, +revisions like ``2.4-1`` and ``2.4pl3`` are newer than ``2.4``, but are *older* +than ``2.4.1`` (which has a higher release number). + +A pre-release tag is a series of letters that are alphabetically before +"final". Some examples of prerelease tags would include ``alpha``, ``beta``, +``a``, ``c``, ``dev``, and so on. You do not have to place a dot or dash +before the prerelease tag if it's immediately after a number, but it's okay to +do so if you prefer. Thus, ``2.4c1`` and ``2.4.c1`` and ``2.4-c1`` all +represent release candidate 1 of version ``2.4``, and are treated as identical +by setuptools. + +In addition, there are three special prerelease tags that are treated as if +they were the letter ``c``: ``pre``, ``preview``, and ``rc``. So, version +``2.4rc1``, ``2.4pre1`` and ``2.4preview1`` are all the exact same version as +``2.4c1``, and are treated as identical by setuptools. + +A post-release tag is either a series of letters that are alphabetically +greater than or equal to "final", or a dash (``-``). Post-release tags are +generally used to separate patch numbers, port numbers, build numbers, revision +numbers, or date stamps from the release number. For example, the version +``2.4-r1263`` might denote Subversion revision 1263 of a post-release patch of +version ``2.4``. Or you might use ``2.4-20051127`` to denote a date-stamped +post-release. + +Notice that after each pre or post-release tag, you are free to place another +release number, followed again by more pre- or post-release tags. For example, +``0.6a9.dev-r41475`` could denote Subversion revision 41475 of the in- +development version of the ninth alpha of release 0.6. Notice that ``dev`` is +a pre-release tag, so this version is a *lower* version number than ``0.6a9``, +which would be the actual ninth alpha of release 0.6. But the ``-r41475`` is +a post-release tag, so this version is *newer* than ``0.6a9.dev``. + +For the most part, setuptools' interpretation of version numbers is intuitive, +but here are a few tips that will keep you out of trouble in the corner cases: + +* Don't stick adjoining pre-release tags together without a dot or number + between them. Version ``1.9adev`` is the ``adev`` prerelease of ``1.9``, + *not* a development pre-release of ``1.9a``. Use ``.dev`` instead, as in + ``1.9a.dev``, or separate the prerelease tags with a number, as in + ``1.9a0dev``. ``1.9a.dev``, ``1.9a0dev``, and even ``1.9.a.dev`` are + identical versions from setuptools' point of view, so you can use whatever + scheme you prefer. + +* If you want to be certain that your chosen numbering scheme works the way + you think it will, you can use the ``pkg_resources.parse_version()`` function + to compare different version numbers:: + + >>> from pkg_resources import parse_version + >>> parse_version("1.9.a.dev") == parse_version("1.9a0dev") + True + >>> parse_version("2.1-rc2") < parse_version("2.1") + True + >>> parse_version("0.6a9dev-r41475") < parse_version("0.6a9") + True + +Once you've decided on a version numbering scheme for your project, you can +have setuptools automatically tag your in-development releases with various +pre- or post-release tags. See the following sections for more details: + +* `Tagging and "Daily Build" or "Snapshot" Releases`_ +* The `egg_info`_ command \ No newline at end of file diff --git a/docs/userguide/quickstart.txt b/docs/userguide/quickstart.txt index 4df50bc5..f2e1a951 100644 --- a/docs/userguide/quickstart.txt +++ b/docs/userguide/quickstart.txt @@ -79,87 +79,3 @@ arguments do (except for the metadata ones), and the various ways you might use them in your own project(s). -Specifying Your Project's Version ---------------------------------- - -Setuptools can work well with most versioning schemes; there are, however, a -few special things to watch out for, in order to ensure that setuptools and -other tools can always tell what version of your package is newer than another -version. Knowing these things will also help you correctly specify what -versions of other projects your project depends on. - -A version consists of an alternating series of release numbers and pre-release -or post-release tags. A release number is a series of digits punctuated by -dots, such as ``2.4`` or ``0.5``. Each series of digits is treated -numerically, so releases ``2.1`` and ``2.1.0`` are different ways to spell the -same release number, denoting the first subrelease of release 2. But ``2.10`` -is the *tenth* subrelease of release 2, and so is a different and newer release -from ``2.1`` or ``2.1.0``. Leading zeros within a series of digits are also -ignored, so ``2.01`` is the same as ``2.1``, and different from ``2.0.1``. - -Following a release number, you can have either a pre-release or post-release -tag. Pre-release tags make a version be considered *older* than the version -they are appended to. So, revision ``2.4`` is *newer* than revision ``2.4c1``, -which in turn is newer than ``2.4b1`` or ``2.4a1``. Postrelease tags make -a version be considered *newer* than the version they are appended to. So, -revisions like ``2.4-1`` and ``2.4pl3`` are newer than ``2.4``, but are *older* -than ``2.4.1`` (which has a higher release number). - -A pre-release tag is a series of letters that are alphabetically before -"final". Some examples of prerelease tags would include ``alpha``, ``beta``, -``a``, ``c``, ``dev``, and so on. You do not have to place a dot or dash -before the prerelease tag if it's immediately after a number, but it's okay to -do so if you prefer. Thus, ``2.4c1`` and ``2.4.c1`` and ``2.4-c1`` all -represent release candidate 1 of version ``2.4``, and are treated as identical -by setuptools. - -In addition, there are three special prerelease tags that are treated as if -they were the letter ``c``: ``pre``, ``preview``, and ``rc``. So, version -``2.4rc1``, ``2.4pre1`` and ``2.4preview1`` are all the exact same version as -``2.4c1``, and are treated as identical by setuptools. - -A post-release tag is either a series of letters that are alphabetically -greater than or equal to "final", or a dash (``-``). Post-release tags are -generally used to separate patch numbers, port numbers, build numbers, revision -numbers, or date stamps from the release number. For example, the version -``2.4-r1263`` might denote Subversion revision 1263 of a post-release patch of -version ``2.4``. Or you might use ``2.4-20051127`` to denote a date-stamped -post-release. - -Notice that after each pre or post-release tag, you are free to place another -release number, followed again by more pre- or post-release tags. For example, -``0.6a9.dev-r41475`` could denote Subversion revision 41475 of the in- -development version of the ninth alpha of release 0.6. Notice that ``dev`` is -a pre-release tag, so this version is a *lower* version number than ``0.6a9``, -which would be the actual ninth alpha of release 0.6. But the ``-r41475`` is -a post-release tag, so this version is *newer* than ``0.6a9.dev``. - -For the most part, setuptools' interpretation of version numbers is intuitive, -but here are a few tips that will keep you out of trouble in the corner cases: - -* Don't stick adjoining pre-release tags together without a dot or number - between them. Version ``1.9adev`` is the ``adev`` prerelease of ``1.9``, - *not* a development pre-release of ``1.9a``. Use ``.dev`` instead, as in - ``1.9a.dev``, or separate the prerelease tags with a number, as in - ``1.9a0dev``. ``1.9a.dev``, ``1.9a0dev``, and even ``1.9.a.dev`` are - identical versions from setuptools' point of view, so you can use whatever - scheme you prefer. - -* If you want to be certain that your chosen numbering scheme works the way - you think it will, you can use the ``pkg_resources.parse_version()`` function - to compare different version numbers:: - - >>> from pkg_resources import parse_version - >>> parse_version("1.9.a.dev") == parse_version("1.9a0dev") - True - >>> parse_version("2.1-rc2") < parse_version("2.1") - True - >>> parse_version("0.6a9dev-r41475") < parse_version("0.6a9") - True - -Once you've decided on a version numbering scheme for your project, you can -have setuptools automatically tag your in-development releases with various -pre- or post-release tags. See the following sections for more details: - -* `Tagging and "Daily Build" or "Snapshot" Releases`_ -* The `egg_info`_ command \ No newline at end of file -- cgit v1.2.1 From e50590a6961a91765ef00aaea447d3be8948666f Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Wed, 13 May 2020 10:57:42 -0400 Subject: docs: removed unnecessary transition paragraph so that the quickstart is cleaner for now. Might add more text later --- docs/userguide/quickstart.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.txt b/docs/userguide/quickstart.txt index f2e1a951..535227a0 100644 --- a/docs/userguide/quickstart.txt +++ b/docs/userguide/quickstart.txt @@ -74,8 +74,6 @@ dependencies, and perhaps some data files and scripts:: # could also include long_description, download_url, 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). + -- cgit v1.2.1 From 7d3317dee0a6ef6f1474e8f6d07b3a4cfe40a084 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Wed, 13 May 2020 11:28:36 -0400 Subject: docs: migrated section egg-secutable section moved from userguide/functionalities to deprecated/functionalities --- docs/userguide/functionalities.txt | 32 -------------------------------- 1 file changed, 32 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/functionalities.txt b/docs/userguide/functionalities.txt index 7bd3ae8a..5946662a 100644 --- a/docs/userguide/functionalities.txt +++ b/docs/userguide/functionalities.txt @@ -155,39 +155,7 @@ will be added to ``sys.path`` when the script is run. For more information on on "entry points" in general, see the section below on `Dynamic Discovery of Services and Plugins`_. -"Eggsecutable" Scripts ----------------------- - -.. deprecated:: 45.3.0 - -Occasionally, there are situations where it's desirable to make an ``.egg`` -file directly executable. You can do this by including an entry point such -as the following:: - - setup( - # other arguments here... - entry_points={ - "setuptools.installation": [ - "eggsecutable = my_package.some_module:main_func", - ] - } - ) -Any eggs built from the above setup script will include a short executable -prelude that imports and calls ``main_func()`` from ``my_package.some_module``. -The prelude can be run on Unix-like platforms (including Mac and Linux) by -invoking the egg with ``/bin/sh``, or by enabling execute permissions on the -``.egg`` file. For the executable prelude to run, the appropriate version of -Python must be available via the ``PATH`` environment variable, under its -"long" name. That is, if the egg is built for Python 2.3, there must be a -``python2.3`` executable present in a directory on ``PATH``. - -IMPORTANT NOTE: Eggs with an "eggsecutable" header cannot be renamed, or -invoked via symlinks. They *must* be invoked using their original filename, in -order to ensure that, once running, ``pkg_resources`` will know what project -and version is in use. The header script will check this and exit with an -error if the ``.egg`` file has been renamed or is invoked via a symlink that -changes its base name. Declaring Dependencies ====================== -- cgit v1.2.1 From 5fe67153b8799fe51407c91b18c7a3acf1d40b0e Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 10:54:50 -0400 Subject: docs: WIP rewrite functionalities such that each section is comprised of a quick intro and example that illustrate the use of that functionality and provide a link to a more detailed explanation. --- docs/userguide/functionalities_rewrite.txt | 143 +++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 docs/userguide/functionalities_rewrite.txt (limited to 'docs/userguide') diff --git a/docs/userguide/functionalities_rewrite.txt b/docs/userguide/functionalities_rewrite.txt new file mode 100644 index 00000000..657a732d --- /dev/null +++ b/docs/userguide/functionalities_rewrite.txt @@ -0,0 +1,143 @@ +======================================================== +Using setuptools to package and distribute your project +======================================================== + +``setuptools`` offers a variety of functionalities that make it easy to +build and distribute your python package. Here we provide an overview on +the commonly used ones. + +Automatic package discovery +=========================== + +For simple projects, it's usually easy enough to manually add packages to +the ``packages`` argument of ``setup()``. However, for very large projects +, it can be a big burden to keep the package list updated. setuptools therefore +provides two tools to ease the burden. + +``find_packages()`` takes a source directory and two lists of package name +patterns to exclude and include. It then walks the target directory, filtering +by inclusion patterns, and finds Python packages (any directory). Packages are only +recognized if they include an ``__init__.py`` file. Finally, exclusion +patterns are applied to remove matching packages. + +Inclusion and 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. + +Regardless of the parameters, 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. + + + +Entry points and automatic script creation +=========================================== + +Setuptools support automatic creation of scripts upon installation, that runs +code within your package if you specify them with the ``entry_point`` keyword. +This is what allows you to run commands like ``pip install`` instead of having +to type ``python -m pip install``. To accomplish this, consider the following +example:: + + setup( + #.... + entry_points={ + "console_scripts": [ + "foo = my_package.some_module:main_func", + "bar = other_module:some_func", + ], + "gui_scripts": [ + "baz = my_package_gui:start_func", + ] + } + ) + +When this project is installed on non-Windows platforms (using "setup.py +install", "setup.py develop", or with pip), a set of ``foo``, ``bar``, +and ``baz`` scripts will be installed that import ``main_func`` and +``some_func`` from the specified modules. On Windows, a set of ``foo.exe``, +``bar.exe``, and ``baz.exe`` launchers are +created, alongside a set of ``foo.py``, ``bar.py``, and ``baz.pyw`` files. The +``.exe`` wrappers find and execute the right version of Python to run the +``.py`` or ``.pyw`` file. + +For detailed usage, including managing the additional or optional dependencies, +go to :ref:`entry_point`. + +Dependency management +===================== + +``setuptools`` supports automatically installing dependencies when a package is +installed. 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:: + + setup( + #... + install_requires = "docutils >= 0.3" + ) + +When your project is installed, either by using pip, ``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. + +For more advanced use, see :ref:`dependencies` + +Including Data Files +==================== + +Development mode +================ + +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. + +To do this, use the ``setup.py develop`` command. It works very similarly to +``setup.py install``, 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. + +for more information, go to :ref:`development_mode` + +Distributing a ``setuptools``-based project +=========================================== +Before you begin, make sure you have the latest versions of setuptools and wheel:: + + pip install --upgrade setuptools wheel + +To build a setuptools project, run this command from the same directory where +setup.py is located:: + + setup.py sdist bdist_wheel + +This will generate distribution archives in the `dist` directory. + +Before you upload the generated archives make sure you're registered on +https://test.pypi.org/account/register/. You will also need to verify your email +to be able to upload any packages. +You should install twine to be able to upload packages:: + + pip install --upgrade twine + +Now, to upload these archives, run:: + + twine upload --repository-url https://test.pypi.org/legacy/ dist/* + +To install your newly uploaded package ``example_pkg``, you can use pip:: + + pip install --index-url https://test.pypi.org/simple/ example_pkg + +The next following sections will walk you through all of the available functions +``setuptools`` offers in excrutiating details (including those already mentioned) +for more advanced use. -- cgit v1.2.1 From a6acf0b59d5401766ae63b1d1f7030724606646e Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 11:15:42 -0400 Subject: docs: update functionalities.txt outline is completed, now to fill the donut holes --- docs/userguide/functionalities_rewrite.txt | 61 ++++++++++++++---------------- 1 file changed, 29 insertions(+), 32 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/functionalities_rewrite.txt b/docs/userguide/functionalities_rewrite.txt index 657a732d..1cd3dee9 100644 --- a/docs/userguide/functionalities_rewrite.txt +++ b/docs/userguide/functionalities_rewrite.txt @@ -12,29 +12,23 @@ Automatic package discovery For simple projects, it's usually easy enough to manually add packages to the ``packages`` argument of ``setup()``. However, for very large projects , it can be a big burden to keep the package list updated. setuptools therefore -provides two tools to ease the burden. +provides tools to ease the burden. ``find_packages()`` takes a source directory and two lists of package name patterns to exclude and include. It then walks the target directory, filtering -by inclusion patterns, and finds Python packages (any directory). Packages are only -recognized if they include an ``__init__.py`` file. Finally, exclusion -patterns are applied to remove matching packages. +by inclusion patterns, and return a list of Python packages (any directory). +Finally, exclusion patterns are applied to remove matching packages. -Inclusion and 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. - -Regardless of the parameters, 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. +For example:: + #... + from setuptools import find_packages() + setup( + #..., + packages = find_packages() + ) +For more details and advanced use, go to :ref:`package_discovery` Entry points and automatic script creation =========================================== @@ -50,25 +44,13 @@ example:: entry_points={ "console_scripts": [ "foo = my_package.some_module:main_func", - "bar = other_module:some_func", ], - "gui_scripts": [ - "baz = my_package_gui:start_func", - ] } ) -When this project is installed on non-Windows platforms (using "setup.py -install", "setup.py develop", or with pip), a set of ``foo``, ``bar``, -and ``baz`` scripts will be installed that import ``main_func`` and -``some_func`` from the specified modules. On Windows, a set of ``foo.exe``, -``bar.exe``, and ``baz.exe`` launchers are -created, alongside a set of ``foo.py``, ``bar.py``, and ``baz.pyw`` files. The -``.exe`` wrappers find and execute the right version of Python to run the -``.py`` or ``.pyw`` file. - -For detailed usage, including managing the additional or optional dependencies, -go to :ref:`entry_point`. +When this project is installed, a ``foo`` script will be installed and will +invoke the ``main_func`` when called by the user. For detailed usage, including +managing the additional or optional dependencies, go to :ref:`entry_point`. Dependency management ===================== @@ -92,6 +74,21 @@ For more advanced use, see :ref:`dependencies` Including Data Files ==================== +The distutils have traditionally allowed installation of "data files", which +are placed in a platform-specific location. Setuptools offers three ways to +specify data files to be included in your packages. For the simpliest use, you +can simply use the ``include_package_data`` keyword e.g.:: + + setup( + ... + include_package_data=True + ) + +This tells setuptools to install any data files it finds in your packages. +The data files must be specified via the distutils' ``MANIFEST.in`` file. + +For more details, see :ref:`datafiles` + Development mode ================ -- cgit v1.2.1 From 54314cbde4db3d559f158dd4c9f02c249f0f6db5 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 11:16:48 -0400 Subject: docs: put the remaining functionalities into misce those that don't need to put into a dedicated file are now inside the miscellaneous.txt --- docs/userguide/functionalities.txt | 1391 ------------------------------------ docs/userguide/miscellaneous.txt | 1391 ++++++++++++++++++++++++++++++++++++ 2 files changed, 1391 insertions(+), 1391 deletions(-) delete mode 100644 docs/userguide/functionalities.txt create mode 100644 docs/userguide/miscellaneous.txt (limited to 'docs/userguide') diff --git a/docs/userguide/functionalities.txt b/docs/userguide/functionalities.txt deleted file mode 100644 index 5946662a..00000000 --- a/docs/userguide/functionalities.txt +++ /dev/null @@ -1,1391 +0,0 @@ -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 two lists of package name -patterns to exclude and include. 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, filtering by inclusion -patterns, and finds Python packages (any directory). Packages are only -recognized if they include an ``__init__.py`` file. Finally, exclusion -patterns are applied to remove matching packages. - -Inclusion and 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:: - - 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 parameters, 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. - -``find_namespace_packages()`` ------------------------------ -In Python 3.3+, ``setuptools`` also provides the ``find_namespace_packages`` variant -of ``find_packages``, which has the same function signature as -``find_packages``, but works with `PEP 420`_ compliant implicit namespace -packages. Here is a minimal setup script using ``find_namespace_packages``:: - - from setuptools import setup, find_namespace_packages - setup( - name="HelloWorld", - version="0.1", - packages=find_namespace_packages(), - ) - - -Keep in mind that according to PEP 420, you may have to either re-organize your -codebase a bit or define a few exclusions, as the definition of an implicit -namespace package is quite lenient, so for a project organized like so:: - - - ├── namespace - │   └── mypackage - │   ├── __init__.py - │   └── mod1.py - ├── setup.py - └── tests - └── test_mod1.py - -A naive ``find_namespace_packages()`` would install both ``namespace.mypackage`` and a -top-level package called ``tests``! One way to avoid this problem is to use the -``include`` keyword to whitelist the packages to include, like so:: - - from setuptools import setup, find_namespace_packages - - setup( - name="namespace.mypackage", - version="0.1", - packages=find_namespace_packages(include=["namespace.*"]) - ) - -Another option is to use the "src" layout, where all package code is placed in -the ``src`` directory, like so:: - - - ├── setup.py - ├── src - │   └── namespace - │   └── mypackage - │   ├── __init__.py - │   └── mod1.py - └── tests - └── test_mod1.py - -With this layout, the package directory is specified as ``src``, as such:: - - setup(name="namespace.mypackage", - version="0.1", - package_dir={"": "src"}, - packages=find_namespace_packages(where="src")) - -.. _PEP 420: https://www.python.org/dev/peps/pep-0420/ - -Automatic Script Creation -========================= - -Packaging and installing scripts can be a bit awkward with the distutils. For -one thing, there's no easy way to have a script's filename match local -conventions on both Windows and POSIX platforms. For another, you often have -to create a separate file just for the "main" script, when your actual "main" -is a function in a module somewhere. And even in Python 2.4, using the ``-m`` -option only works for actual ``.py`` files that aren't installed in a package. - -``setuptools`` fixes all of these problems by automatically generating scripts -for you with the correct extension, and on Windows it will even create an -``.exe`` file so that users don't have to change their ``PATHEXT`` settings. -The way to use this feature is to define "entry points" in your setup script -that indicate what function the generated script should import and run. For -example, to create two console scripts called ``foo`` and ``bar``, and a GUI -script called ``baz``, you might do something like this:: - - setup( - # other arguments here... - entry_points={ - "console_scripts": [ - "foo = my_package.some_module:main_func", - "bar = other_module:some_func", - ], - "gui_scripts": [ - "baz = my_package_gui:start_func", - ] - } - ) - -When this project is installed on non-Windows platforms (using "setup.py -install", "setup.py develop", or with pip), a set of ``foo``, ``bar``, -and ``baz`` scripts will be installed that import ``main_func`` and -``some_func`` from the specified modules. The functions you specify are -called with no arguments, and their return value is passed to -``sys.exit()``, so you can return an errorlevel or message to print to -stderr. - -On Windows, a set of ``foo.exe``, ``bar.exe``, and ``baz.exe`` launchers are -created, alongside a set of ``foo.py``, ``bar.py``, and ``baz.pyw`` files. The -``.exe`` wrappers find and execute the right version of Python to run the -``.py`` or ``.pyw`` file. - -You may define as many "console script" and "gui script" entry points as you -like, and each one can optionally specify "extras" that it depends on, that -will be added to ``sys.path`` when the script is run. For more information on -"extras", see the section below on `Declaring Extras`_. For more information -on "entry points" in general, see the section below on `Dynamic Discovery of -Services and Plugins`_. - - - -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 pip 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 ``-``. - -Version specifiers for a given project are internally sorted into ascending -version order, and used to establish what ranges of versions are acceptable. -Adjacent redundant conditions are also consolidated (e.g. ``">1, >2"`` becomes -``">2"``, and ``"<2,<3"`` becomes ``"<2"``). ``"!="`` versions are excised from -the ranges they fall within. A project's version is then checked for -membership in the resulting ranges. (Note that providing conflicting conditions -for the same version (e.g. "<2,>=2" or "==2,!=2") is meaningless and may -therefore produce bizarre results.) - -Here are some example requirement specifiers:: - - 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 pip, ``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. - -2. 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). - -3. 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``.) - -Dependencies that aren't in PyPI --------------------------------- - -.. warning:: - Dependency links support has been dropped by pip starting with version - 19.0 (released 2019-01-22). - -If your project depends on packages that don't exist on PyPI, you may still be -able to depend on them, as long as they are available for download as: - -- an egg, in the standard distutils ``sdist`` format, -- a single ``.py`` file, or -- a VCS repository (Subversion, Mercurial, or Git). - -You just need to add some URLs to the ``dependency_links`` argument to -``setup()``. - -The URLs must be either: - -1. direct download URLs, -2. the URLs of web pages that contain direct download links, or -3. the repository's URL - -In general, it's better to link to web pages, because it is usually less -complex to update a web page than to release a new version of your project. -You can also use a SourceForge ``showfiles.php`` link in the case where a -package you depend on is distributed via SourceForge. - -If you depend on a package that's distributed as a single ``.py`` file, you -must include an ``"#egg=project-version"`` suffix to the URL, to give a project -name and version number. (Be sure to escape any dashes in the name or version -by replacing them with underscores.) EasyInstall will recognize this suffix -and automatically create a trivial ``setup.py`` to wrap the single ``.py`` file -as an egg. - -In the case of a VCS checkout, you should also append ``#egg=project-version`` -in order to identify for what package that checkout should be used. You can -append ``@REV`` to the URL's path (before the fragment) to specify a revision. -Additionally, you can also force the VCS being used by prepending the URL with -a certain prefix. Currently available are: - -- ``svn+URL`` for Subversion, -- ``git+URL`` for Git, and -- ``hg+URL`` for Mercurial - -A more complete example would be: - - ``vcs+proto://host/path@revision#egg=project-version`` - -Be careful with the version. It should match the one inside the project files. -If you want to disregard the version, you have to omit it both in the -``requires`` and in the URL's fragment. - -This will do a checkout (or a clone, in Git and Mercurial parlance) to a -temporary folder and run ``setup.py bdist_egg``. - -The ``dependency_links`` option takes the form of a list of URL strings. For -example, this will cause a search of the specified page for eggs or source -distributions, if the package's dependencies aren't already installed:: - - setup( - ... - dependency_links=[ - "http://peak.telecommunity.com/snapshots/" - ], - ) - - -.. _Declaring Extras: - - -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:: - - setup( - name="Project-A", - ... - extras_require={ - "PDF": ["ReportLab>=1.2", "RXP"], - "reST": ["docutils>=0.3"], - } - ) - -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 "pip install" -command line.) - -Extras can be used by a project's `entry points`_ to specify dynamic -dependencies. For example, if Project A includes a "rst2pdf" script, it might -declare it like this, so that the "PDF" requirements are only resolved if the -"rst2pdf" script is run:: - - setup( - name="Project-A", - ... - entry_points={ - "console_scripts": [ - "rst2pdf = project_a.tools.pdfgen [PDF]", - "rst2html = project_a.tools.htmlgen", - # more script entry points ... - ], - } - ) - -Projects can also use another project's extras when specifying dependencies. -For example, if project B needs "project A" with PDF support installed, it -might declare the dependency like this:: - - 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. - -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 could change its -setup to this:: - - 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. - -.. _Platform Specific Dependencies: - - -Declaring platform specific dependencies ----------------------------------------- - -Sometimes a project might require a dependency to run on a specific platform. -This could to a package that back ports a module so that it can be used in -older python versions. Or it could be a package that is required to run on a -specific operating system. This will allow a project to work on multiple -different platforms without installing dependencies that are not required for -a platform that is installing the project. - -For example, here is a project that uses the ``enum`` module and ``pywin32``:: - - setup( - name="Project", - ... - install_requires=[ - "enum34;python_version<'3.4'", - "pywin32 >= 1.0;platform_system=='Windows'" - ] - ) - -Since the ``enum`` module was added in Python 3.4, it should only be installed -if the python version is earlier. Since ``pywin32`` will only be used on -windows, it should only be installed when the operating system is Windows. -Specifying version requirements for the dependencies is supported as normal. - -The environmental markers that may be used for testing platform types are -detailed in `PEP 508`_. - -.. _PEP 508: https://www.python.org/dev/peps/pep-0508/ - -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 offers three ways to specify data files to be included in your -packages. First, you can simply use the ``include_package_data`` keyword, -e.g.:: - - from setuptools import setup, find_packages - setup( - ... - include_package_data=True - ) - -This tells setuptools to install any data files it finds in your packages. -The data files must be specified via the distutils' ``MANIFEST.in`` file. -(They can also be tracked by a revision control system, using an appropriate -plugin. See the section below on `Adding Support for Revision Control -Systems`_ for information on how to write such plugins.) - -If you want finer-grained control over what files are included (for example, -if you have documentation files in your package directories and want to exclude -them from installation), then you can also use the ``package_data`` keyword, -e.g.:: - - 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:: - - setup.py - src/ - mypkg/ - __init__.py - mypkg.txt - data/ - somefile.dat - otherdata.dat - -The setuptools setup file might look like this:: - - 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. - -If datafiles are contained in a subdirectory of a package that isn't a package -itself (no ``__init__.py``), then the subdirectory names (or ``*``) are required -in the ``package_data`` argument (as shown above with ``"data/*.dat"``). - -When building an ``sdist``, the datafiles are also drawn from the -``package_name.egg-info/SOURCES.txt`` file, so make sure that this is removed if -the ``setup.py`` ``package_data`` list is updated before calling ``setup.py``. - -(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 `some documentation for the feature`__ available on the -python.org website. If using the setuptools-specific ``include_package_data`` -argument, files specified by ``package_data`` will *not* be automatically -added to the manifest unless they are listed in the MANIFEST.in file.) - -__ https://docs.python.org/3/distutils/setupscript.html#installing-package-data - -Sometimes, the ``include_package_data`` or ``package_data`` options alone -aren't sufficient to precisely define what files you want included. For -example, you may want to include package README files in your revision control -system and source distributions, but exclude them from being installed. So, -setuptools offers an ``exclude_package_data`` option as well, that allows you -to do things like this:: - - 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 - - include_package_data=True, # include everything in source control - - # ...but exclude README.txt from all packages - exclude_package_data={"": ["README.txt"]}, - ) - -The ``exclude_package_data`` option is a dictionary mapping package names to -lists of wildcard patterns, just like the ``package_data`` option. And, just -as with that option, a key of ``""`` will apply the given pattern(s) to all -packages. However, any files that match these patterns will be *excluded* -from installation, even if they were listed in ``package_data`` or were -included as a result of using ``include_package_data``. - -In summary, the three options allow you to: - -``include_package_data`` - Accept all data files and directories matched by ``MANIFEST.in``. - -``package_data`` - Specify additional patterns to match files that may or may - not be matched by ``MANIFEST.in`` or found in source control. - -``exclude_package_data`` - Specify patterns for data files and directories that should *not* be - included when a package is installed, even if they would otherwise have - been included due to the use of the preceding options. - -NOTE: Due to the way the distutils build process works, a data file that you -include in your project and then stop including may be "orphaned" in your -project's build directories, requiring you to run ``setup.py clean --all`` to -fully remove them. This may also be important for your users and contributors -if they track intermediate revisions of your project using Subversion; be sure -to let them know when you make changes that remove files from inclusion so they -can run ``setup.py clean --all``. - -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 :ref:`ResourceManager 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 `Importlib Resources`_ for -a quick example of converting code that uses ``__file__`` to use -``pkg_resources`` instead. - -.. _Importlib Resources: https://docs.python.org/3/library/importlib.html#module-importlib.resources - - -Non-Package Data Files ----------------------- - -Historically, ``setuptools`` by way of ``easy_install`` would encapsulate data -files from the distribution into the egg (see `the old docs -`_). As eggs are deprecated and pip-based installs -fall back to the platform-specific location for installing data files, there is -no supported facility to reliably retrieve these resources. - -Instead, the PyPA recommends that any data files you wish to be accessible at -run time be included in the package. - - -Automatic Resource Extraction ------------------------------ - -If you are using tools that expect your resources to be "real" files, or your -project includes non-extension native libraries or other files that your C -extensions expect to be able to access, you may need to list those files in -the ``eager_resources`` argument to ``setup()``, so that the files will be -extracted together, whenever a C extension in the project is imported. - -This is especially important if your project includes shared libraries *other* -than distutils-built C extensions, and those shared libraries use file -extensions other than ``.dll``, ``.so``, or ``.dylib``, which are the -extensions that setuptools 0.6a8 and higher automatically detects as shared -libraries and adds to the ``native_libs.txt`` file for you. Any shared -libraries whose names do not end with one of those extensions should be listed -as ``eager_resources``, because they need to be present in the filesystem when -he C extensions that link to them are used. - -The ``pkg_resources`` runtime for compressed packages will automatically -extract *all* C extensions and ``eager_resources`` at the same time, whenever -*any* C extension or eager resource is requested via the ``resource_filename()`` -API. (C extensions are imported using ``resource_filename()`` internally.) -This ensures that C extensions will see all of the "real" files that they -expect to see. - -Note also that you can list directory resource names in ``eager_resources`` as -well, in which case the directory's contents (including subdirectories) will be -extracted whenever any C extension or eager resource is requested. - -Please note that if you're not sure whether you need to use this argument, you -don't! It's really intended to support projects with lots of non-Python -dependencies and as a last resort for crufty projects that can't otherwise -handle being compressed. If your package is pure Python, Python plus data -files, or Python plus C, you really don't need this. You've got to be using -either C or an external program that needs "real" files in your project before -there's any possibility of ``eager_resources`` being relevant to your project. - - -Extensible Applications and Frameworks -====================================== - - -.. _Entry Points: - -Dynamic Discovery of Services and Plugins ------------------------------------------ - -``setuptools`` supports creating libraries that "plug in" to extensible -applications and frameworks, by letting you register "entry points" in your -project that can be imported by the application or framework. - -For example, suppose that a blogging tool wants to support plugins -that provide translation for various file types to the blog's output format. -The framework might define an "entry point group" called ``blogtool.parsers``, -and then allow plugins to register entry points for the file extensions they -support. - -This would allow people to create distributions that contain one or more -parsers for different file types, and then the blogging tool would be able to -find the parsers at runtime by looking up an entry point for the file -extension (or mime type, or however it wants to). - -Note that if the blogging tool includes parsers for certain file formats, it -can register these as entry points in its own setup script, which means it -doesn't have to special-case its built-in formats. They can just be treated -the same as any other plugin's entry points would be. - -If you're creating a project that plugs in to an existing application or -framework, you'll need to know what entry points or entry point groups are -defined by that application or framework. Then, you can register entry points -in your setup script. Here are a few examples of ways you might register an -``.rst`` file parser entry point in the ``blogtool.parsers`` entry point group, -for our hypothetical blogging tool:: - - setup( - # ... - entry_points={"blogtool.parsers": ".rst = some_module:SomeClass"} - ) - - setup( - # ... - entry_points={"blogtool.parsers": [".rst = some_module:a_func"]} - ) - - setup( - # ... - entry_points=""" - [blogtool.parsers] - .rst = some.nested.module:SomeClass.some_classmethod [reST] - """, - extras_require=dict(reST="Docutils>=0.3.5") - ) - -The ``entry_points`` argument to ``setup()`` accepts either a string with -``.ini``-style sections, or a dictionary mapping entry point group names to -either strings or lists of strings containing entry point specifiers. An -entry point specifier consists of a name and value, separated by an ``=`` -sign. The value consists of a dotted module name, optionally followed by a -``:`` and a dotted identifier naming an object within the module. It can -also include a bracketed list of "extras" that are required for the entry -point to be used. When the invoking application or framework requests loading -of an entry point, any requirements implied by the associated extras will be -passed to ``pkg_resources.require()``, so that an appropriate error message -can be displayed if the needed package(s) are missing. (Of course, the -invoking app or framework can ignore such errors if it wants to make an entry -point optional if a requirement isn't installed.) - -Defining Additional Metadata ----------------------------- - -Some extensible applications and frameworks may need to define their own kinds -of metadata to include in eggs, which they can then access using the -``pkg_resources`` metadata APIs. Ordinarily, this is done by having plugin -developers include additional files in their ``ProjectName.egg-info`` -directory. However, since it can be tedious to create such files by hand, you -may want to create a distutils extension that will create the necessary files -from arguments to ``setup()``, in much the same way that ``setuptools`` does -for many of the ``setup()`` arguments it adds. See the section below on -`Creating distutils Extensions`_ for more details, especially the subsection on -`Adding new EGG-INFO Files`_. - - -"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``, 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. - -If you have enabled the ``use_2to3`` flag, then of course the ``.egg-link`` -will not link directly to your source code when run under Python 3, since -that source code would be made for Python 2 and not work under Python 3. -Instead the ``setup.py develop`` will build Python 3 code under the ``build`` -directory, and link there. This means that after doing code changes you will -have to run ``setup.py build`` before these changes are picked up by your -Python 3 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. - -Note that you can also apply setuptools commands to non-setuptools projects, -using commands like this:: - - python -c "import setuptools; with open('setup.py') as f: exec(compile(f.read(), 'setup.py', 'exec'))" develop - -That is, you can simply list the normal setup commands and options following -the quoted part. - - -Distributing a ``setuptools``-based project -=========================================== - -Detailed instructions to distribute a setuptools project can be found at -`Packaging project tutorials`_. - -.. _Packaging project tutorials: https://packaging.python.org/tutorials/packaging-projects/#generating-distribution-archives - -Before you begin, make sure you have the latest versions of setuptools and wheel:: - - pip install --upgrade setuptools wheel - -To build a setuptools project, run this command from the same directory where -setup.py is located:: - - setup.py sdist bdist_wheel - -This will generate distribution archives in the `dist` directory. - -Before you upload the generated archives make sure you're registered on -https://test.pypi.org/account/register/. You will also need to verify your email -to be able to upload any packages. -You should install twine to be able to upload packages:: - - pip install --upgrade twine - -Now, to upload these archives, run:: - - twine upload --repository-url https://test.pypi.org/legacy/ dist/* - -To install your newly uploaded package ``example_pkg``, you can use pip:: - - pip install --index-url https://test.pypi.org/simple/ example_pkg - -If you have issues at any point, please refer to `Packaging project tutorials`_ -for clarification. - - -Setting the ``zip_safe`` flag ------------------------------ - -For some use cases (such as bundling as part of a larger application), Python -packages may be run directly from a zip file. -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. - -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`` to try to guess -whether your project can work as a zipfile. - -.. _Namespace Packages: - -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 then 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. The argument should list the namespace packages that the egg -participates in. For example, the ZopeInterface project might do this:: - - 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. When these projects are -installed and used, Python will see them both as part of a "virtual" ``zope`` -package, even though they will be installed in different locations. - -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 -*must* contain the line:: - - __import__("pkg_resources").declare_namespace(__name__) - -This code ensures that the namespace package machinery is operating and that -the current package is registered as a namespace package. - -You must NOT include any other code and data in a namespace package's -``__init__.py``. Even though it may appear to work during development, or when -projects are installed as ``.egg`` files, it will not work when the projects -are installed using "system" packaging tools -- in such cases the -``__init__.py`` files will not be installed, let alone executed. - -You must include the ``declare_namespace()`` line in the ``__init__.py`` of -*every* project that has contents for the namespace package in question, in -order to ensure that the namespace will be declared regardless of which -project's copy of ``__init__.py`` is loaded first. If the first loaded -``__init__.py`` doesn't declare it, it will never *be* declared, because no -other copies will ever be loaded! - -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: - -* A manually-specified pre-release tag, such as "build" or "dev", or a - manually-specified post-release tag, such as a build or revision number - (``--tag-build=STRING, -bSTRING``) - -* An 8-character representation of the build date (``--tag-date, -d``), as - a postrelease tag - -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, before you release your project, be sure to see the section above on -`Specifying Your Project's Version`_ for more information about how pre- and -post-release tags affect how version numbers are interpreted. This is -important in order to make sure that dependency processing tools will know -which versions of your project are newer than others.) - -Finally, 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:: - - 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 script or 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 with pluggable endpoints for looking up files to include. If you are -using a revision control system, and your source distributions only need to -include files that you're tracking in revision control, use a corresponding -plugin instead of writing a ``MANIFEST.in`` file. See the section below on -`Adding Support for Revision Control Systems`_ for information on plugins. - -If you need to include automatically generated files, or files that are kept in -an unsupported revision control system, you'll need to create a ``MANIFEST.in`` -file to specify any files that the default file location algorithm doesn't -catch. See the distutils documentation for more information on the format of -the ``MANIFEST.in`` file. - -But, be sure to ignore any part of the distutils documentation that deals with -``MANIFEST`` or how it's generated from ``MANIFEST.in``; setuptools shields you -from these issues and doesn't work the same way in any case. Unlike the -distutils, setuptools regenerates the source distribution manifest file -every time you build a source distribution, and it builds it inside the -project's ``.egg-info`` directory, out of the way of your main project -directory. You therefore need not worry about whether it is up-to-date or not. - -Indeed, because setuptools' approach to determining the contents of a source -distribution is so much simpler, its ``sdist`` command omits nearly all of -the options that the distutils' more complex ``sdist`` process requires. For -all practical purposes, you'll probably use only the ``--formats`` option, if -you use any option at all. - - -Making "Official" (Non-Snapshot) Releases -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When you make an official release, creating source or binary distributions, -you will need to override the tag settings from ``setup.cfg``, so that you -don't end up registering versions like ``foobar-0.7a1.dev-r34832``. This is -easy to do if you are developing on the trunk and using tags or branches for -your releases - just make the change to ``setup.cfg`` after branching or -tagging the release, so the trunk will still produce development snapshots. - -Alternately, if you are not branching for releases, you can override the -default version options on the command line, using something like:: - - setup.py egg_info -Db "" sdist bdist_egg - -The first part of this command (``egg_info -Db ""``) will override the -configured tag information, before creating source and binary eggs. Thus, these -commands will use the plain version from your ``setup.py``, without adding the -build designation string. - -Of course, if you will be doing this a lot, you may wish to create a personal -alias for this operation, e.g.:: - - setup.py alias -u release egg_info -Db "" - -You can then use it like this:: - - setup.py release sdist bdist_egg - -Or of course you can create more elaborate aliases that do all of the above. -See the sections below on the `egg_info`_ and `alias`_ commands for more ideas. - -Distributing Extensions compiled with Cython --------------------------------------------- - -``setuptools`` will detect at build time whether Cython is installed or not. -If Cython is not found ``setuptools`` will ignore pyx files. - -To ensure Cython is available, include Cython in the build-requires section -of your pyproject.toml:: - - [build-system] - requires=[..., "cython"] - -Built with pip 10 or later, that declaration is sufficient to include Cython -in the build. For broader compatibility, declare the dependency in your -setup-requires of setup.cfg:: - - [options] - setup_requires = - ... - cython - -As long as Cython is present in the build environment, ``setuptools`` includes -transparent support for building Cython extensions, as -long as extensions are defined using ``setuptools.Extension``. - -If you follow these rules, you can safely list ``.pyx`` files as the source -of your ``Extension`` objects in the setup script. If it is, then ``setuptools`` -will use it. - -Of course, for this to work, your source distributions must include the C -code generated by Cython, 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 a revision -control system will be able to build it even if they don't have Cython -installed, and that your source releases will be similarly usable with or -without Cython. - --------------------------------- -Extending and Reusing Setuptools --------------------------------- - -Creating ``distutils`` Extensions -================================= - -It can be hard to add new commands or setup arguments to the distutils. But -the ``setuptools`` package makes it a bit easier, by allowing you to distribute -a distutils extension as a separate project, and then have projects that need -the extension just refer to it in their ``setup_requires`` argument. - -With ``setuptools``, your distutils extension projects can hook in new -commands and ``setup()`` arguments just by defining "entry points". These -are mappings from command or argument names to a specification of where to -import a handler from. (See the section on `Dynamic Discovery of Services and -Plugins`_ above for some more background on entry points.) - - -Adding Commands ---------------- - -You can add new ``setup`` commands by defining entry points in the -``distutils.commands`` group. For example, if you wanted to add a ``foo`` -command, you might add something like this to your distutils extension -project's setup script:: - - setup( - # ... - entry_points={ - "distutils.commands": [ - "foo = mypackage.some_module:foo", - ], - }, - ) - -(Assuming, of course, that the ``foo`` class in ``mypackage.some_module`` is -a ``setuptools.Command`` subclass.) - -Once a project containing such entry points has been activated on ``sys.path``, -(e.g. by running "install" or "develop" with a site-packages installation -directory) the command(s) will be available to any ``setuptools``-based setup -scripts. It is not necessary to use the ``--command-packages`` option or -to monkeypatch the ``distutils.command`` package to install your commands; -``setuptools`` automatically adds a wrapper to the distutils to search for -entry points in the active distributions on ``sys.path``. In fact, this is -how setuptools' own commands are installed: the setuptools project's setup -script defines entry points for them! - -Adding ``setup()`` Arguments ----------------------------- - -.. warning:: Adding arguments to setup is discouraged as such arguments - are only supported through imperative execution and not supported through - declarative config. - -Sometimes, your commands may need additional arguments to the ``setup()`` -call. You can enable this by defining entry points in the -``distutils.setup_keywords`` group. For example, if you wanted a ``setup()`` -argument called ``bar_baz``, you might add something like this to your -distutils extension project's setup script:: - - setup( - # ... - entry_points={ - "distutils.commands": [ - "foo = mypackage.some_module:foo", - ], - "distutils.setup_keywords": [ - "bar_baz = mypackage.some_module:validate_bar_baz", - ], - }, - ) - -The idea here is that the entry point defines a function that will be called -to validate the ``setup()`` argument, if it's supplied. The ``Distribution`` -object will have the initial value of the attribute set to ``None``, and the -validation function will only be called if the ``setup()`` call sets it to -a non-None value. Here's an example validation function:: - - def assert_bool(dist, attr, value): - """Verify that value is True, False, 0, or 1""" - if bool(value) != value: - raise DistutilsSetupError( - "%r must be a boolean value (got %r)" % (attr,value) - ) - -Your function should accept three arguments: the ``Distribution`` object, -the attribute name, and the attribute value. It should raise a -``DistutilsSetupError`` (from the ``distutils.errors`` module) if the argument -is invalid. Remember, your function will only be called with non-None values, -and the default value of arguments defined this way is always None. So, your -commands should always be prepared for the possibility that the attribute will -be ``None`` when they access it later. - -If more than one active distribution defines an entry point for the same -``setup()`` argument, *all* of them will be called. This allows multiple -distutils extensions to define a common argument, as long as they agree on -what values of that argument are valid. - -Also note that as with commands, it is not necessary to subclass or monkeypatch -the distutils ``Distribution`` class in order to add your arguments; it is -sufficient to define the entry points in your extension, as long as any setup -script using your extension lists your project in its ``setup_requires`` -argument. - - -Customizing Distribution Options --------------------------------- - -Plugins may wish to extend or alter the options on a Distribution object to -suit the purposes of that project. For example, a tool that infers the -``Distribution.version`` from SCM-metadata may need to hook into the -option finalization. To enable this feature, Setuptools offers an entry -point "setuptools.finalize_distribution_options". That entry point must -be a callable taking one argument (the Distribution instance). - -If the callable has an ``.order`` property, that value will be used to -determine the order in which the hook is called. Lower numbers are called -first and the default is zero (0). - -Plugins may read, alter, and set properties on the distribution, but each -plugin is encouraged to load the configuration/settings for their behavior -independently. - - -Adding new EGG-INFO Files -------------------------- - -Some extensible applications or frameworks may want to allow third parties to -develop plugins with application or framework-specific metadata included in -the plugins' EGG-INFO directory, for easy access via the ``pkg_resources`` -metadata API. The easiest way to allow this is to create a distutils extension -to be used from the plugin projects' setup scripts (via ``setup_requires``) -that defines a new setup keyword, and then uses that data to write an EGG-INFO -file when the ``egg_info`` command is run. - -The ``egg_info`` command looks for extension points in an ``egg_info.writers`` -group, and calls them to write the files. Here's a simple example of a -distutils extension defining a setup argument ``foo_bar``, which is a list of -lines that will be written to ``foo_bar.txt`` in the EGG-INFO directory of any -project that uses the argument:: - - setup( - # ... - entry_points={ - "distutils.setup_keywords": [ - "foo_bar = setuptools.dist:assert_string_list", - ], - "egg_info.writers": [ - "foo_bar.txt = setuptools.command.egg_info:write_arg", - ], - }, - ) - -This simple example makes use of two utility functions defined by setuptools -for its own use: a routine to validate that a setup keyword is a sequence of -strings, and another one that looks up a setup argument and writes it to -a file. Here's what the writer utility looks like:: - - def write_arg(cmd, basename, filename): - argname = os.path.splitext(basename)[0] - value = getattr(cmd.distribution, argname, None) - if value is not None: - value = "\n".join(value) + "\n" - cmd.write_or_delete_file(argname, filename, value) - -As you can see, ``egg_info.writers`` entry points must be a function taking -three arguments: a ``egg_info`` command instance, the basename of the file to -write (e.g. ``foo_bar.txt``), and the actual full filename that should be -written to. - -In general, writer functions should honor the command object's ``dry_run`` -setting when writing files, and use the ``distutils.log`` object to do any -console output. The easiest way to conform to this requirement is to use -the ``cmd`` object's ``write_file()``, ``delete_file()``, and -``write_or_delete_file()`` methods exclusively for your file operations. See -those methods' docstrings for more details. - -Adding Support for Revision Control Systems -------------------------------------------------- - -If the files you want to include in the source distribution are tracked using -Git, Mercurial or SVN, you can use the following packages to achieve that: - -- Git and Mercurial: `setuptools_scm `_ -- SVN: `setuptools_svn `_ - -If you would like to create a plugin for ``setuptools`` to find files tracked -by another revision control system, you can do so by adding an entry point to -the ``setuptools.file_finders`` group. The entry point should be a function -accepting a single directory name, and should yield all the filenames within -that directory (and any subdirectories thereof) that are under revision -control. - -For example, if you were going to create a plugin for a revision control system -called "foobar", you would write a function something like this: - -.. code-block:: python - - def find_files_for_foobar(dirname): - # loop to yield paths that start with `dirname` - -And you would register it in a setup script using something like this:: - - entry_points={ - "setuptools.file_finders": [ - "foobar = my_foobar_module:find_files_for_foobar", - ] - } - -Then, anyone who wants to use your plugin can simply install it, and their -local setuptools installation will be able to find the necessary files. - -It is not necessary to distribute source control plugins with projects that -simply use the other source control system, or to specify the plugins in -``setup_requires``. When you create a source distribution with the ``sdist`` -command, setuptools automatically records what files were found in the -``SOURCES.txt`` file. That way, recipients of source distributions don't need -to have revision control at all. However, if someone is working on a package -by checking out with that system, they will need the same plugin(s) that the -original author is using. - -A few important points for writing revision control file finders: - -* Your finder function MUST return relative paths, created by appending to the - passed-in directory name. Absolute paths are NOT allowed, nor are relative - paths that reference a parent directory of the passed-in directory. - -* Your finder function MUST accept an empty string as the directory name, - meaning the current directory. You MUST NOT convert this to a dot; just - yield relative paths. So, yielding a subdirectory named ``some/dir`` under - the current directory should NOT be rendered as ``./some/dir`` or - ``/somewhere/some/dir``, but *always* as simply ``some/dir`` - -* Your finder function SHOULD NOT raise any errors, and SHOULD deal gracefully - with the absence of needed programs (i.e., ones belonging to the revision - control system itself. It *may*, however, use ``distutils.log.warn()`` to - inform the user of the missing program(s). - -Specifying Your Project's Version ---------------------------------- - -Setuptools can work well with most versioning schemes; there are, however, a -few special things to watch out for, in order to ensure that setuptools and -other tools can always tell what version of your package is newer than another -version. Knowing these things will also help you correctly specify what -versions of other projects your project depends on. - -A version consists of an alternating series of release numbers and pre-release -or post-release tags. A release number is a series of digits punctuated by -dots, such as ``2.4`` or ``0.5``. Each series of digits is treated -numerically, so releases ``2.1`` and ``2.1.0`` are different ways to spell the -same release number, denoting the first subrelease of release 2. But ``2.10`` -is the *tenth* subrelease of release 2, and so is a different and newer release -from ``2.1`` or ``2.1.0``. Leading zeros within a series of digits are also -ignored, so ``2.01`` is the same as ``2.1``, and different from ``2.0.1``. - -Following a release number, you can have either a pre-release or post-release -tag. Pre-release tags make a version be considered *older* than the version -they are appended to. So, revision ``2.4`` is *newer* than revision ``2.4c1``, -which in turn is newer than ``2.4b1`` or ``2.4a1``. Postrelease tags make -a version be considered *newer* than the version they are appended to. So, -revisions like ``2.4-1`` and ``2.4pl3`` are newer than ``2.4``, but are *older* -than ``2.4.1`` (which has a higher release number). - -A pre-release tag is a series of letters that are alphabetically before -"final". Some examples of prerelease tags would include ``alpha``, ``beta``, -``a``, ``c``, ``dev``, and so on. You do not have to place a dot or dash -before the prerelease tag if it's immediately after a number, but it's okay to -do so if you prefer. Thus, ``2.4c1`` and ``2.4.c1`` and ``2.4-c1`` all -represent release candidate 1 of version ``2.4``, and are treated as identical -by setuptools. - -In addition, there are three special prerelease tags that are treated as if -they were the letter ``c``: ``pre``, ``preview``, and ``rc``. So, version -``2.4rc1``, ``2.4pre1`` and ``2.4preview1`` are all the exact same version as -``2.4c1``, and are treated as identical by setuptools. - -A post-release tag is either a series of letters that are alphabetically -greater than or equal to "final", or a dash (``-``). Post-release tags are -generally used to separate patch numbers, port numbers, build numbers, revision -numbers, or date stamps from the release number. For example, the version -``2.4-r1263`` might denote Subversion revision 1263 of a post-release patch of -version ``2.4``. Or you might use ``2.4-20051127`` to denote a date-stamped -post-release. - -Notice that after each pre or post-release tag, you are free to place another -release number, followed again by more pre- or post-release tags. For example, -``0.6a9.dev-r41475`` could denote Subversion revision 41475 of the in- -development version of the ninth alpha of release 0.6. Notice that ``dev`` is -a pre-release tag, so this version is a *lower* version number than ``0.6a9``, -which would be the actual ninth alpha of release 0.6. But the ``-r41475`` is -a post-release tag, so this version is *newer* than ``0.6a9.dev``. - -For the most part, setuptools' interpretation of version numbers is intuitive, -but here are a few tips that will keep you out of trouble in the corner cases: - -* Don't stick adjoining pre-release tags together without a dot or number - between them. Version ``1.9adev`` is the ``adev`` prerelease of ``1.9``, - *not* a development pre-release of ``1.9a``. Use ``.dev`` instead, as in - ``1.9a.dev``, or separate the prerelease tags with a number, as in - ``1.9a0dev``. ``1.9a.dev``, ``1.9a0dev``, and even ``1.9.a.dev`` are - identical versions from setuptools' point of view, so you can use whatever - scheme you prefer. - -* If you want to be certain that your chosen numbering scheme works the way - you think it will, you can use the ``pkg_resources.parse_version()`` function - to compare different version numbers:: - - >>> from pkg_resources import parse_version - >>> parse_version("1.9.a.dev") == parse_version("1.9a0dev") - True - >>> parse_version("2.1-rc2") < parse_version("2.1") - True - >>> parse_version("0.6a9dev-r41475") < parse_version("0.6a9") - True - -Once you've decided on a version numbering scheme for your project, you can -have setuptools automatically tag your in-development releases with various -pre- or post-release tags. See the following sections for more details: - -* `Tagging and "Daily Build" or "Snapshot" Releases`_ -* The `egg_info`_ command \ No newline at end of file diff --git a/docs/userguide/miscellaneous.txt b/docs/userguide/miscellaneous.txt new file mode 100644 index 00000000..5946662a --- /dev/null +++ b/docs/userguide/miscellaneous.txt @@ -0,0 +1,1391 @@ +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 two lists of package name +patterns to exclude and include. 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, filtering by inclusion +patterns, and finds Python packages (any directory). Packages are only +recognized if they include an ``__init__.py`` file. Finally, exclusion +patterns are applied to remove matching packages. + +Inclusion and 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:: + + 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 parameters, 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. + +``find_namespace_packages()`` +----------------------------- +In Python 3.3+, ``setuptools`` also provides the ``find_namespace_packages`` variant +of ``find_packages``, which has the same function signature as +``find_packages``, but works with `PEP 420`_ compliant implicit namespace +packages. Here is a minimal setup script using ``find_namespace_packages``:: + + from setuptools import setup, find_namespace_packages + setup( + name="HelloWorld", + version="0.1", + packages=find_namespace_packages(), + ) + + +Keep in mind that according to PEP 420, you may have to either re-organize your +codebase a bit or define a few exclusions, as the definition of an implicit +namespace package is quite lenient, so for a project organized like so:: + + + ├── namespace + │   └── mypackage + │   ├── __init__.py + │   └── mod1.py + ├── setup.py + └── tests + └── test_mod1.py + +A naive ``find_namespace_packages()`` would install both ``namespace.mypackage`` and a +top-level package called ``tests``! One way to avoid this problem is to use the +``include`` keyword to whitelist the packages to include, like so:: + + from setuptools import setup, find_namespace_packages + + setup( + name="namespace.mypackage", + version="0.1", + packages=find_namespace_packages(include=["namespace.*"]) + ) + +Another option is to use the "src" layout, where all package code is placed in +the ``src`` directory, like so:: + + + ├── setup.py + ├── src + │   └── namespace + │   └── mypackage + │   ├── __init__.py + │   └── mod1.py + └── tests + └── test_mod1.py + +With this layout, the package directory is specified as ``src``, as such:: + + setup(name="namespace.mypackage", + version="0.1", + package_dir={"": "src"}, + packages=find_namespace_packages(where="src")) + +.. _PEP 420: https://www.python.org/dev/peps/pep-0420/ + +Automatic Script Creation +========================= + +Packaging and installing scripts can be a bit awkward with the distutils. For +one thing, there's no easy way to have a script's filename match local +conventions on both Windows and POSIX platforms. For another, you often have +to create a separate file just for the "main" script, when your actual "main" +is a function in a module somewhere. And even in Python 2.4, using the ``-m`` +option only works for actual ``.py`` files that aren't installed in a package. + +``setuptools`` fixes all of these problems by automatically generating scripts +for you with the correct extension, and on Windows it will even create an +``.exe`` file so that users don't have to change their ``PATHEXT`` settings. +The way to use this feature is to define "entry points" in your setup script +that indicate what function the generated script should import and run. For +example, to create two console scripts called ``foo`` and ``bar``, and a GUI +script called ``baz``, you might do something like this:: + + setup( + # other arguments here... + entry_points={ + "console_scripts": [ + "foo = my_package.some_module:main_func", + "bar = other_module:some_func", + ], + "gui_scripts": [ + "baz = my_package_gui:start_func", + ] + } + ) + +When this project is installed on non-Windows platforms (using "setup.py +install", "setup.py develop", or with pip), a set of ``foo``, ``bar``, +and ``baz`` scripts will be installed that import ``main_func`` and +``some_func`` from the specified modules. The functions you specify are +called with no arguments, and their return value is passed to +``sys.exit()``, so you can return an errorlevel or message to print to +stderr. + +On Windows, a set of ``foo.exe``, ``bar.exe``, and ``baz.exe`` launchers are +created, alongside a set of ``foo.py``, ``bar.py``, and ``baz.pyw`` files. The +``.exe`` wrappers find and execute the right version of Python to run the +``.py`` or ``.pyw`` file. + +You may define as many "console script" and "gui script" entry points as you +like, and each one can optionally specify "extras" that it depends on, that +will be added to ``sys.path`` when the script is run. For more information on +"extras", see the section below on `Declaring Extras`_. For more information +on "entry points" in general, see the section below on `Dynamic Discovery of +Services and Plugins`_. + + + +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 pip 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 ``-``. + +Version specifiers for a given project are internally sorted into ascending +version order, and used to establish what ranges of versions are acceptable. +Adjacent redundant conditions are also consolidated (e.g. ``">1, >2"`` becomes +``">2"``, and ``"<2,<3"`` becomes ``"<2"``). ``"!="`` versions are excised from +the ranges they fall within. A project's version is then checked for +membership in the resulting ranges. (Note that providing conflicting conditions +for the same version (e.g. "<2,>=2" or "==2,!=2") is meaningless and may +therefore produce bizarre results.) + +Here are some example requirement specifiers:: + + 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 pip, ``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. + +2. 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). + +3. 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``.) + +Dependencies that aren't in PyPI +-------------------------------- + +.. warning:: + Dependency links support has been dropped by pip starting with version + 19.0 (released 2019-01-22). + +If your project depends on packages that don't exist on PyPI, you may still be +able to depend on them, as long as they are available for download as: + +- an egg, in the standard distutils ``sdist`` format, +- a single ``.py`` file, or +- a VCS repository (Subversion, Mercurial, or Git). + +You just need to add some URLs to the ``dependency_links`` argument to +``setup()``. + +The URLs must be either: + +1. direct download URLs, +2. the URLs of web pages that contain direct download links, or +3. the repository's URL + +In general, it's better to link to web pages, because it is usually less +complex to update a web page than to release a new version of your project. +You can also use a SourceForge ``showfiles.php`` link in the case where a +package you depend on is distributed via SourceForge. + +If you depend on a package that's distributed as a single ``.py`` file, you +must include an ``"#egg=project-version"`` suffix to the URL, to give a project +name and version number. (Be sure to escape any dashes in the name or version +by replacing them with underscores.) EasyInstall will recognize this suffix +and automatically create a trivial ``setup.py`` to wrap the single ``.py`` file +as an egg. + +In the case of a VCS checkout, you should also append ``#egg=project-version`` +in order to identify for what package that checkout should be used. You can +append ``@REV`` to the URL's path (before the fragment) to specify a revision. +Additionally, you can also force the VCS being used by prepending the URL with +a certain prefix. Currently available are: + +- ``svn+URL`` for Subversion, +- ``git+URL`` for Git, and +- ``hg+URL`` for Mercurial + +A more complete example would be: + + ``vcs+proto://host/path@revision#egg=project-version`` + +Be careful with the version. It should match the one inside the project files. +If you want to disregard the version, you have to omit it both in the +``requires`` and in the URL's fragment. + +This will do a checkout (or a clone, in Git and Mercurial parlance) to a +temporary folder and run ``setup.py bdist_egg``. + +The ``dependency_links`` option takes the form of a list of URL strings. For +example, this will cause a search of the specified page for eggs or source +distributions, if the package's dependencies aren't already installed:: + + setup( + ... + dependency_links=[ + "http://peak.telecommunity.com/snapshots/" + ], + ) + + +.. _Declaring Extras: + + +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:: + + setup( + name="Project-A", + ... + extras_require={ + "PDF": ["ReportLab>=1.2", "RXP"], + "reST": ["docutils>=0.3"], + } + ) + +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 "pip install" +command line.) + +Extras can be used by a project's `entry points`_ to specify dynamic +dependencies. For example, if Project A includes a "rst2pdf" script, it might +declare it like this, so that the "PDF" requirements are only resolved if the +"rst2pdf" script is run:: + + setup( + name="Project-A", + ... + entry_points={ + "console_scripts": [ + "rst2pdf = project_a.tools.pdfgen [PDF]", + "rst2html = project_a.tools.htmlgen", + # more script entry points ... + ], + } + ) + +Projects can also use another project's extras when specifying dependencies. +For example, if project B needs "project A" with PDF support installed, it +might declare the dependency like this:: + + 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. + +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 could change its +setup to this:: + + 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. + +.. _Platform Specific Dependencies: + + +Declaring platform specific dependencies +---------------------------------------- + +Sometimes a project might require a dependency to run on a specific platform. +This could to a package that back ports a module so that it can be used in +older python versions. Or it could be a package that is required to run on a +specific operating system. This will allow a project to work on multiple +different platforms without installing dependencies that are not required for +a platform that is installing the project. + +For example, here is a project that uses the ``enum`` module and ``pywin32``:: + + setup( + name="Project", + ... + install_requires=[ + "enum34;python_version<'3.4'", + "pywin32 >= 1.0;platform_system=='Windows'" + ] + ) + +Since the ``enum`` module was added in Python 3.4, it should only be installed +if the python version is earlier. Since ``pywin32`` will only be used on +windows, it should only be installed when the operating system is Windows. +Specifying version requirements for the dependencies is supported as normal. + +The environmental markers that may be used for testing platform types are +detailed in `PEP 508`_. + +.. _PEP 508: https://www.python.org/dev/peps/pep-0508/ + +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 offers three ways to specify data files to be included in your +packages. First, you can simply use the ``include_package_data`` keyword, +e.g.:: + + from setuptools import setup, find_packages + setup( + ... + include_package_data=True + ) + +This tells setuptools to install any data files it finds in your packages. +The data files must be specified via the distutils' ``MANIFEST.in`` file. +(They can also be tracked by a revision control system, using an appropriate +plugin. See the section below on `Adding Support for Revision Control +Systems`_ for information on how to write such plugins.) + +If you want finer-grained control over what files are included (for example, +if you have documentation files in your package directories and want to exclude +them from installation), then you can also use the ``package_data`` keyword, +e.g.:: + + 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:: + + setup.py + src/ + mypkg/ + __init__.py + mypkg.txt + data/ + somefile.dat + otherdata.dat + +The setuptools setup file might look like this:: + + 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. + +If datafiles are contained in a subdirectory of a package that isn't a package +itself (no ``__init__.py``), then the subdirectory names (or ``*``) are required +in the ``package_data`` argument (as shown above with ``"data/*.dat"``). + +When building an ``sdist``, the datafiles are also drawn from the +``package_name.egg-info/SOURCES.txt`` file, so make sure that this is removed if +the ``setup.py`` ``package_data`` list is updated before calling ``setup.py``. + +(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 `some documentation for the feature`__ available on the +python.org website. If using the setuptools-specific ``include_package_data`` +argument, files specified by ``package_data`` will *not* be automatically +added to the manifest unless they are listed in the MANIFEST.in file.) + +__ https://docs.python.org/3/distutils/setupscript.html#installing-package-data + +Sometimes, the ``include_package_data`` or ``package_data`` options alone +aren't sufficient to precisely define what files you want included. For +example, you may want to include package README files in your revision control +system and source distributions, but exclude them from being installed. So, +setuptools offers an ``exclude_package_data`` option as well, that allows you +to do things like this:: + + 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 + + include_package_data=True, # include everything in source control + + # ...but exclude README.txt from all packages + exclude_package_data={"": ["README.txt"]}, + ) + +The ``exclude_package_data`` option is a dictionary mapping package names to +lists of wildcard patterns, just like the ``package_data`` option. And, just +as with that option, a key of ``""`` will apply the given pattern(s) to all +packages. However, any files that match these patterns will be *excluded* +from installation, even if they were listed in ``package_data`` or were +included as a result of using ``include_package_data``. + +In summary, the three options allow you to: + +``include_package_data`` + Accept all data files and directories matched by ``MANIFEST.in``. + +``package_data`` + Specify additional patterns to match files that may or may + not be matched by ``MANIFEST.in`` or found in source control. + +``exclude_package_data`` + Specify patterns for data files and directories that should *not* be + included when a package is installed, even if they would otherwise have + been included due to the use of the preceding options. + +NOTE: Due to the way the distutils build process works, a data file that you +include in your project and then stop including may be "orphaned" in your +project's build directories, requiring you to run ``setup.py clean --all`` to +fully remove them. This may also be important for your users and contributors +if they track intermediate revisions of your project using Subversion; be sure +to let them know when you make changes that remove files from inclusion so they +can run ``setup.py clean --all``. + +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 :ref:`ResourceManager 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 `Importlib Resources`_ for +a quick example of converting code that uses ``__file__`` to use +``pkg_resources`` instead. + +.. _Importlib Resources: https://docs.python.org/3/library/importlib.html#module-importlib.resources + + +Non-Package Data Files +---------------------- + +Historically, ``setuptools`` by way of ``easy_install`` would encapsulate data +files from the distribution into the egg (see `the old docs +`_). As eggs are deprecated and pip-based installs +fall back to the platform-specific location for installing data files, there is +no supported facility to reliably retrieve these resources. + +Instead, the PyPA recommends that any data files you wish to be accessible at +run time be included in the package. + + +Automatic Resource Extraction +----------------------------- + +If you are using tools that expect your resources to be "real" files, or your +project includes non-extension native libraries or other files that your C +extensions expect to be able to access, you may need to list those files in +the ``eager_resources`` argument to ``setup()``, so that the files will be +extracted together, whenever a C extension in the project is imported. + +This is especially important if your project includes shared libraries *other* +than distutils-built C extensions, and those shared libraries use file +extensions other than ``.dll``, ``.so``, or ``.dylib``, which are the +extensions that setuptools 0.6a8 and higher automatically detects as shared +libraries and adds to the ``native_libs.txt`` file for you. Any shared +libraries whose names do not end with one of those extensions should be listed +as ``eager_resources``, because they need to be present in the filesystem when +he C extensions that link to them are used. + +The ``pkg_resources`` runtime for compressed packages will automatically +extract *all* C extensions and ``eager_resources`` at the same time, whenever +*any* C extension or eager resource is requested via the ``resource_filename()`` +API. (C extensions are imported using ``resource_filename()`` internally.) +This ensures that C extensions will see all of the "real" files that they +expect to see. + +Note also that you can list directory resource names in ``eager_resources`` as +well, in which case the directory's contents (including subdirectories) will be +extracted whenever any C extension or eager resource is requested. + +Please note that if you're not sure whether you need to use this argument, you +don't! It's really intended to support projects with lots of non-Python +dependencies and as a last resort for crufty projects that can't otherwise +handle being compressed. If your package is pure Python, Python plus data +files, or Python plus C, you really don't need this. You've got to be using +either C or an external program that needs "real" files in your project before +there's any possibility of ``eager_resources`` being relevant to your project. + + +Extensible Applications and Frameworks +====================================== + + +.. _Entry Points: + +Dynamic Discovery of Services and Plugins +----------------------------------------- + +``setuptools`` supports creating libraries that "plug in" to extensible +applications and frameworks, by letting you register "entry points" in your +project that can be imported by the application or framework. + +For example, suppose that a blogging tool wants to support plugins +that provide translation for various file types to the blog's output format. +The framework might define an "entry point group" called ``blogtool.parsers``, +and then allow plugins to register entry points for the file extensions they +support. + +This would allow people to create distributions that contain one or more +parsers for different file types, and then the blogging tool would be able to +find the parsers at runtime by looking up an entry point for the file +extension (or mime type, or however it wants to). + +Note that if the blogging tool includes parsers for certain file formats, it +can register these as entry points in its own setup script, which means it +doesn't have to special-case its built-in formats. They can just be treated +the same as any other plugin's entry points would be. + +If you're creating a project that plugs in to an existing application or +framework, you'll need to know what entry points or entry point groups are +defined by that application or framework. Then, you can register entry points +in your setup script. Here are a few examples of ways you might register an +``.rst`` file parser entry point in the ``blogtool.parsers`` entry point group, +for our hypothetical blogging tool:: + + setup( + # ... + entry_points={"blogtool.parsers": ".rst = some_module:SomeClass"} + ) + + setup( + # ... + entry_points={"blogtool.parsers": [".rst = some_module:a_func"]} + ) + + setup( + # ... + entry_points=""" + [blogtool.parsers] + .rst = some.nested.module:SomeClass.some_classmethod [reST] + """, + extras_require=dict(reST="Docutils>=0.3.5") + ) + +The ``entry_points`` argument to ``setup()`` accepts either a string with +``.ini``-style sections, or a dictionary mapping entry point group names to +either strings or lists of strings containing entry point specifiers. An +entry point specifier consists of a name and value, separated by an ``=`` +sign. The value consists of a dotted module name, optionally followed by a +``:`` and a dotted identifier naming an object within the module. It can +also include a bracketed list of "extras" that are required for the entry +point to be used. When the invoking application or framework requests loading +of an entry point, any requirements implied by the associated extras will be +passed to ``pkg_resources.require()``, so that an appropriate error message +can be displayed if the needed package(s) are missing. (Of course, the +invoking app or framework can ignore such errors if it wants to make an entry +point optional if a requirement isn't installed.) + +Defining Additional Metadata +---------------------------- + +Some extensible applications and frameworks may need to define their own kinds +of metadata to include in eggs, which they can then access using the +``pkg_resources`` metadata APIs. Ordinarily, this is done by having plugin +developers include additional files in their ``ProjectName.egg-info`` +directory. However, since it can be tedious to create such files by hand, you +may want to create a distutils extension that will create the necessary files +from arguments to ``setup()``, in much the same way that ``setuptools`` does +for many of the ``setup()`` arguments it adds. See the section below on +`Creating distutils Extensions`_ for more details, especially the subsection on +`Adding new EGG-INFO Files`_. + + +"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``, 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. + +If you have enabled the ``use_2to3`` flag, then of course the ``.egg-link`` +will not link directly to your source code when run under Python 3, since +that source code would be made for Python 2 and not work under Python 3. +Instead the ``setup.py develop`` will build Python 3 code under the ``build`` +directory, and link there. This means that after doing code changes you will +have to run ``setup.py build`` before these changes are picked up by your +Python 3 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. + +Note that you can also apply setuptools commands to non-setuptools projects, +using commands like this:: + + python -c "import setuptools; with open('setup.py') as f: exec(compile(f.read(), 'setup.py', 'exec'))" develop + +That is, you can simply list the normal setup commands and options following +the quoted part. + + +Distributing a ``setuptools``-based project +=========================================== + +Detailed instructions to distribute a setuptools project can be found at +`Packaging project tutorials`_. + +.. _Packaging project tutorials: https://packaging.python.org/tutorials/packaging-projects/#generating-distribution-archives + +Before you begin, make sure you have the latest versions of setuptools and wheel:: + + pip install --upgrade setuptools wheel + +To build a setuptools project, run this command from the same directory where +setup.py is located:: + + setup.py sdist bdist_wheel + +This will generate distribution archives in the `dist` directory. + +Before you upload the generated archives make sure you're registered on +https://test.pypi.org/account/register/. You will also need to verify your email +to be able to upload any packages. +You should install twine to be able to upload packages:: + + pip install --upgrade twine + +Now, to upload these archives, run:: + + twine upload --repository-url https://test.pypi.org/legacy/ dist/* + +To install your newly uploaded package ``example_pkg``, you can use pip:: + + pip install --index-url https://test.pypi.org/simple/ example_pkg + +If you have issues at any point, please refer to `Packaging project tutorials`_ +for clarification. + + +Setting the ``zip_safe`` flag +----------------------------- + +For some use cases (such as bundling as part of a larger application), Python +packages may be run directly from a zip file. +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. + +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`` to try to guess +whether your project can work as a zipfile. + +.. _Namespace Packages: + +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 then 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. The argument should list the namespace packages that the egg +participates in. For example, the ZopeInterface project might do this:: + + 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. When these projects are +installed and used, Python will see them both as part of a "virtual" ``zope`` +package, even though they will be installed in different locations. + +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 +*must* contain the line:: + + __import__("pkg_resources").declare_namespace(__name__) + +This code ensures that the namespace package machinery is operating and that +the current package is registered as a namespace package. + +You must NOT include any other code and data in a namespace package's +``__init__.py``. Even though it may appear to work during development, or when +projects are installed as ``.egg`` files, it will not work when the projects +are installed using "system" packaging tools -- in such cases the +``__init__.py`` files will not be installed, let alone executed. + +You must include the ``declare_namespace()`` line in the ``__init__.py`` of +*every* project that has contents for the namespace package in question, in +order to ensure that the namespace will be declared regardless of which +project's copy of ``__init__.py`` is loaded first. If the first loaded +``__init__.py`` doesn't declare it, it will never *be* declared, because no +other copies will ever be loaded! + +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: + +* A manually-specified pre-release tag, such as "build" or "dev", or a + manually-specified post-release tag, such as a build or revision number + (``--tag-build=STRING, -bSTRING``) + +* An 8-character representation of the build date (``--tag-date, -d``), as + a postrelease tag + +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, before you release your project, be sure to see the section above on +`Specifying Your Project's Version`_ for more information about how pre- and +post-release tags affect how version numbers are interpreted. This is +important in order to make sure that dependency processing tools will know +which versions of your project are newer than others.) + +Finally, 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:: + + 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 script or 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 with pluggable endpoints for looking up files to include. If you are +using a revision control system, and your source distributions only need to +include files that you're tracking in revision control, use a corresponding +plugin instead of writing a ``MANIFEST.in`` file. See the section below on +`Adding Support for Revision Control Systems`_ for information on plugins. + +If you need to include automatically generated files, or files that are kept in +an unsupported revision control system, you'll need to create a ``MANIFEST.in`` +file to specify any files that the default file location algorithm doesn't +catch. See the distutils documentation for more information on the format of +the ``MANIFEST.in`` file. + +But, be sure to ignore any part of the distutils documentation that deals with +``MANIFEST`` or how it's generated from ``MANIFEST.in``; setuptools shields you +from these issues and doesn't work the same way in any case. Unlike the +distutils, setuptools regenerates the source distribution manifest file +every time you build a source distribution, and it builds it inside the +project's ``.egg-info`` directory, out of the way of your main project +directory. You therefore need not worry about whether it is up-to-date or not. + +Indeed, because setuptools' approach to determining the contents of a source +distribution is so much simpler, its ``sdist`` command omits nearly all of +the options that the distutils' more complex ``sdist`` process requires. For +all practical purposes, you'll probably use only the ``--formats`` option, if +you use any option at all. + + +Making "Official" (Non-Snapshot) Releases +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When you make an official release, creating source or binary distributions, +you will need to override the tag settings from ``setup.cfg``, so that you +don't end up registering versions like ``foobar-0.7a1.dev-r34832``. This is +easy to do if you are developing on the trunk and using tags or branches for +your releases - just make the change to ``setup.cfg`` after branching or +tagging the release, so the trunk will still produce development snapshots. + +Alternately, if you are not branching for releases, you can override the +default version options on the command line, using something like:: + + setup.py egg_info -Db "" sdist bdist_egg + +The first part of this command (``egg_info -Db ""``) will override the +configured tag information, before creating source and binary eggs. Thus, these +commands will use the plain version from your ``setup.py``, without adding the +build designation string. + +Of course, if you will be doing this a lot, you may wish to create a personal +alias for this operation, e.g.:: + + setup.py alias -u release egg_info -Db "" + +You can then use it like this:: + + setup.py release sdist bdist_egg + +Or of course you can create more elaborate aliases that do all of the above. +See the sections below on the `egg_info`_ and `alias`_ commands for more ideas. + +Distributing Extensions compiled with Cython +-------------------------------------------- + +``setuptools`` will detect at build time whether Cython is installed or not. +If Cython is not found ``setuptools`` will ignore pyx files. + +To ensure Cython is available, include Cython in the build-requires section +of your pyproject.toml:: + + [build-system] + requires=[..., "cython"] + +Built with pip 10 or later, that declaration is sufficient to include Cython +in the build. For broader compatibility, declare the dependency in your +setup-requires of setup.cfg:: + + [options] + setup_requires = + ... + cython + +As long as Cython is present in the build environment, ``setuptools`` includes +transparent support for building Cython extensions, as +long as extensions are defined using ``setuptools.Extension``. + +If you follow these rules, you can safely list ``.pyx`` files as the source +of your ``Extension`` objects in the setup script. If it is, then ``setuptools`` +will use it. + +Of course, for this to work, your source distributions must include the C +code generated by Cython, 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 a revision +control system will be able to build it even if they don't have Cython +installed, and that your source releases will be similarly usable with or +without Cython. + +-------------------------------- +Extending and Reusing Setuptools +-------------------------------- + +Creating ``distutils`` Extensions +================================= + +It can be hard to add new commands or setup arguments to the distutils. But +the ``setuptools`` package makes it a bit easier, by allowing you to distribute +a distutils extension as a separate project, and then have projects that need +the extension just refer to it in their ``setup_requires`` argument. + +With ``setuptools``, your distutils extension projects can hook in new +commands and ``setup()`` arguments just by defining "entry points". These +are mappings from command or argument names to a specification of where to +import a handler from. (See the section on `Dynamic Discovery of Services and +Plugins`_ above for some more background on entry points.) + + +Adding Commands +--------------- + +You can add new ``setup`` commands by defining entry points in the +``distutils.commands`` group. For example, if you wanted to add a ``foo`` +command, you might add something like this to your distutils extension +project's setup script:: + + setup( + # ... + entry_points={ + "distutils.commands": [ + "foo = mypackage.some_module:foo", + ], + }, + ) + +(Assuming, of course, that the ``foo`` class in ``mypackage.some_module`` is +a ``setuptools.Command`` subclass.) + +Once a project containing such entry points has been activated on ``sys.path``, +(e.g. by running "install" or "develop" with a site-packages installation +directory) the command(s) will be available to any ``setuptools``-based setup +scripts. It is not necessary to use the ``--command-packages`` option or +to monkeypatch the ``distutils.command`` package to install your commands; +``setuptools`` automatically adds a wrapper to the distutils to search for +entry points in the active distributions on ``sys.path``. In fact, this is +how setuptools' own commands are installed: the setuptools project's setup +script defines entry points for them! + +Adding ``setup()`` Arguments +---------------------------- + +.. warning:: Adding arguments to setup is discouraged as such arguments + are only supported through imperative execution and not supported through + declarative config. + +Sometimes, your commands may need additional arguments to the ``setup()`` +call. You can enable this by defining entry points in the +``distutils.setup_keywords`` group. For example, if you wanted a ``setup()`` +argument called ``bar_baz``, you might add something like this to your +distutils extension project's setup script:: + + setup( + # ... + entry_points={ + "distutils.commands": [ + "foo = mypackage.some_module:foo", + ], + "distutils.setup_keywords": [ + "bar_baz = mypackage.some_module:validate_bar_baz", + ], + }, + ) + +The idea here is that the entry point defines a function that will be called +to validate the ``setup()`` argument, if it's supplied. The ``Distribution`` +object will have the initial value of the attribute set to ``None``, and the +validation function will only be called if the ``setup()`` call sets it to +a non-None value. Here's an example validation function:: + + def assert_bool(dist, attr, value): + """Verify that value is True, False, 0, or 1""" + if bool(value) != value: + raise DistutilsSetupError( + "%r must be a boolean value (got %r)" % (attr,value) + ) + +Your function should accept three arguments: the ``Distribution`` object, +the attribute name, and the attribute value. It should raise a +``DistutilsSetupError`` (from the ``distutils.errors`` module) if the argument +is invalid. Remember, your function will only be called with non-None values, +and the default value of arguments defined this way is always None. So, your +commands should always be prepared for the possibility that the attribute will +be ``None`` when they access it later. + +If more than one active distribution defines an entry point for the same +``setup()`` argument, *all* of them will be called. This allows multiple +distutils extensions to define a common argument, as long as they agree on +what values of that argument are valid. + +Also note that as with commands, it is not necessary to subclass or monkeypatch +the distutils ``Distribution`` class in order to add your arguments; it is +sufficient to define the entry points in your extension, as long as any setup +script using your extension lists your project in its ``setup_requires`` +argument. + + +Customizing Distribution Options +-------------------------------- + +Plugins may wish to extend or alter the options on a Distribution object to +suit the purposes of that project. For example, a tool that infers the +``Distribution.version`` from SCM-metadata may need to hook into the +option finalization. To enable this feature, Setuptools offers an entry +point "setuptools.finalize_distribution_options". That entry point must +be a callable taking one argument (the Distribution instance). + +If the callable has an ``.order`` property, that value will be used to +determine the order in which the hook is called. Lower numbers are called +first and the default is zero (0). + +Plugins may read, alter, and set properties on the distribution, but each +plugin is encouraged to load the configuration/settings for their behavior +independently. + + +Adding new EGG-INFO Files +------------------------- + +Some extensible applications or frameworks may want to allow third parties to +develop plugins with application or framework-specific metadata included in +the plugins' EGG-INFO directory, for easy access via the ``pkg_resources`` +metadata API. The easiest way to allow this is to create a distutils extension +to be used from the plugin projects' setup scripts (via ``setup_requires``) +that defines a new setup keyword, and then uses that data to write an EGG-INFO +file when the ``egg_info`` command is run. + +The ``egg_info`` command looks for extension points in an ``egg_info.writers`` +group, and calls them to write the files. Here's a simple example of a +distutils extension defining a setup argument ``foo_bar``, which is a list of +lines that will be written to ``foo_bar.txt`` in the EGG-INFO directory of any +project that uses the argument:: + + setup( + # ... + entry_points={ + "distutils.setup_keywords": [ + "foo_bar = setuptools.dist:assert_string_list", + ], + "egg_info.writers": [ + "foo_bar.txt = setuptools.command.egg_info:write_arg", + ], + }, + ) + +This simple example makes use of two utility functions defined by setuptools +for its own use: a routine to validate that a setup keyword is a sequence of +strings, and another one that looks up a setup argument and writes it to +a file. Here's what the writer utility looks like:: + + def write_arg(cmd, basename, filename): + argname = os.path.splitext(basename)[0] + value = getattr(cmd.distribution, argname, None) + if value is not None: + value = "\n".join(value) + "\n" + cmd.write_or_delete_file(argname, filename, value) + +As you can see, ``egg_info.writers`` entry points must be a function taking +three arguments: a ``egg_info`` command instance, the basename of the file to +write (e.g. ``foo_bar.txt``), and the actual full filename that should be +written to. + +In general, writer functions should honor the command object's ``dry_run`` +setting when writing files, and use the ``distutils.log`` object to do any +console output. The easiest way to conform to this requirement is to use +the ``cmd`` object's ``write_file()``, ``delete_file()``, and +``write_or_delete_file()`` methods exclusively for your file operations. See +those methods' docstrings for more details. + +Adding Support for Revision Control Systems +------------------------------------------------- + +If the files you want to include in the source distribution are tracked using +Git, Mercurial or SVN, you can use the following packages to achieve that: + +- Git and Mercurial: `setuptools_scm `_ +- SVN: `setuptools_svn `_ + +If you would like to create a plugin for ``setuptools`` to find files tracked +by another revision control system, you can do so by adding an entry point to +the ``setuptools.file_finders`` group. The entry point should be a function +accepting a single directory name, and should yield all the filenames within +that directory (and any subdirectories thereof) that are under revision +control. + +For example, if you were going to create a plugin for a revision control system +called "foobar", you would write a function something like this: + +.. code-block:: python + + def find_files_for_foobar(dirname): + # loop to yield paths that start with `dirname` + +And you would register it in a setup script using something like this:: + + entry_points={ + "setuptools.file_finders": [ + "foobar = my_foobar_module:find_files_for_foobar", + ] + } + +Then, anyone who wants to use your plugin can simply install it, and their +local setuptools installation will be able to find the necessary files. + +It is not necessary to distribute source control plugins with projects that +simply use the other source control system, or to specify the plugins in +``setup_requires``. When you create a source distribution with the ``sdist`` +command, setuptools automatically records what files were found in the +``SOURCES.txt`` file. That way, recipients of source distributions don't need +to have revision control at all. However, if someone is working on a package +by checking out with that system, they will need the same plugin(s) that the +original author is using. + +A few important points for writing revision control file finders: + +* Your finder function MUST return relative paths, created by appending to the + passed-in directory name. Absolute paths are NOT allowed, nor are relative + paths that reference a parent directory of the passed-in directory. + +* Your finder function MUST accept an empty string as the directory name, + meaning the current directory. You MUST NOT convert this to a dot; just + yield relative paths. So, yielding a subdirectory named ``some/dir`` under + the current directory should NOT be rendered as ``./some/dir`` or + ``/somewhere/some/dir``, but *always* as simply ``some/dir`` + +* Your finder function SHOULD NOT raise any errors, and SHOULD deal gracefully + with the absence of needed programs (i.e., ones belonging to the revision + control system itself. It *may*, however, use ``distutils.log.warn()`` to + inform the user of the missing program(s). + +Specifying Your Project's Version +--------------------------------- + +Setuptools can work well with most versioning schemes; there are, however, a +few special things to watch out for, in order to ensure that setuptools and +other tools can always tell what version of your package is newer than another +version. Knowing these things will also help you correctly specify what +versions of other projects your project depends on. + +A version consists of an alternating series of release numbers and pre-release +or post-release tags. A release number is a series of digits punctuated by +dots, such as ``2.4`` or ``0.5``. Each series of digits is treated +numerically, so releases ``2.1`` and ``2.1.0`` are different ways to spell the +same release number, denoting the first subrelease of release 2. But ``2.10`` +is the *tenth* subrelease of release 2, and so is a different and newer release +from ``2.1`` or ``2.1.0``. Leading zeros within a series of digits are also +ignored, so ``2.01`` is the same as ``2.1``, and different from ``2.0.1``. + +Following a release number, you can have either a pre-release or post-release +tag. Pre-release tags make a version be considered *older* than the version +they are appended to. So, revision ``2.4`` is *newer* than revision ``2.4c1``, +which in turn is newer than ``2.4b1`` or ``2.4a1``. Postrelease tags make +a version be considered *newer* than the version they are appended to. So, +revisions like ``2.4-1`` and ``2.4pl3`` are newer than ``2.4``, but are *older* +than ``2.4.1`` (which has a higher release number). + +A pre-release tag is a series of letters that are alphabetically before +"final". Some examples of prerelease tags would include ``alpha``, ``beta``, +``a``, ``c``, ``dev``, and so on. You do not have to place a dot or dash +before the prerelease tag if it's immediately after a number, but it's okay to +do so if you prefer. Thus, ``2.4c1`` and ``2.4.c1`` and ``2.4-c1`` all +represent release candidate 1 of version ``2.4``, and are treated as identical +by setuptools. + +In addition, there are three special prerelease tags that are treated as if +they were the letter ``c``: ``pre``, ``preview``, and ``rc``. So, version +``2.4rc1``, ``2.4pre1`` and ``2.4preview1`` are all the exact same version as +``2.4c1``, and are treated as identical by setuptools. + +A post-release tag is either a series of letters that are alphabetically +greater than or equal to "final", or a dash (``-``). Post-release tags are +generally used to separate patch numbers, port numbers, build numbers, revision +numbers, or date stamps from the release number. For example, the version +``2.4-r1263`` might denote Subversion revision 1263 of a post-release patch of +version ``2.4``. Or you might use ``2.4-20051127`` to denote a date-stamped +post-release. + +Notice that after each pre or post-release tag, you are free to place another +release number, followed again by more pre- or post-release tags. For example, +``0.6a9.dev-r41475`` could denote Subversion revision 41475 of the in- +development version of the ninth alpha of release 0.6. Notice that ``dev`` is +a pre-release tag, so this version is a *lower* version number than ``0.6a9``, +which would be the actual ninth alpha of release 0.6. But the ``-r41475`` is +a post-release tag, so this version is *newer* than ``0.6a9.dev``. + +For the most part, setuptools' interpretation of version numbers is intuitive, +but here are a few tips that will keep you out of trouble in the corner cases: + +* Don't stick adjoining pre-release tags together without a dot or number + between them. Version ``1.9adev`` is the ``adev`` prerelease of ``1.9``, + *not* a development pre-release of ``1.9a``. Use ``.dev`` instead, as in + ``1.9a.dev``, or separate the prerelease tags with a number, as in + ``1.9a0dev``. ``1.9a.dev``, ``1.9a0dev``, and even ``1.9.a.dev`` are + identical versions from setuptools' point of view, so you can use whatever + scheme you prefer. + +* If you want to be certain that your chosen numbering scheme works the way + you think it will, you can use the ``pkg_resources.parse_version()`` function + to compare different version numbers:: + + >>> from pkg_resources import parse_version + >>> parse_version("1.9.a.dev") == parse_version("1.9a0dev") + True + >>> parse_version("2.1-rc2") < parse_version("2.1") + True + >>> parse_version("0.6a9dev-r41475") < parse_version("0.6a9") + True + +Once you've decided on a version numbering scheme for your project, you can +have setuptools automatically tag your in-development releases with various +pre- or post-release tags. See the following sections for more details: + +* `Tagging and "Daily Build" or "Snapshot" Releases`_ +* The `egg_info`_ command \ No newline at end of file -- cgit v1.2.1 From 88f248944a6033d1781a49a57997cd4932e28746 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 11:20:15 -0400 Subject: docs: merge function walkthrough into quickstart --- docs/userguide/functionalities_rewrite.txt | 131 ----------------------------- docs/userguide/quickstart.txt | 131 +++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 131 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/functionalities_rewrite.txt b/docs/userguide/functionalities_rewrite.txt index 1cd3dee9..d0997ca6 100644 --- a/docs/userguide/functionalities_rewrite.txt +++ b/docs/userguide/functionalities_rewrite.txt @@ -6,135 +6,4 @@ Using setuptools to package and distribute your project build and distribute your python package. Here we provide an overview on the commonly used ones. -Automatic package discovery -=========================== -For simple projects, it's usually easy enough to manually add packages to -the ``packages`` argument of ``setup()``. However, for very large projects -, it can be a big burden to keep the package list updated. setuptools therefore -provides tools to ease the burden. - -``find_packages()`` takes a source directory and two lists of package name -patterns to exclude and include. It then walks the target directory, filtering -by inclusion patterns, and return a list of Python packages (any directory). -Finally, exclusion patterns are applied to remove matching packages. - -For example:: - #... - from setuptools import find_packages() - - setup( - #..., - packages = find_packages() - ) - -For more details and advanced use, go to :ref:`package_discovery` - -Entry points and automatic script creation -=========================================== - -Setuptools support automatic creation of scripts upon installation, that runs -code within your package if you specify them with the ``entry_point`` keyword. -This is what allows you to run commands like ``pip install`` instead of having -to type ``python -m pip install``. To accomplish this, consider the following -example:: - - setup( - #.... - entry_points={ - "console_scripts": [ - "foo = my_package.some_module:main_func", - ], - } - ) - -When this project is installed, a ``foo`` script will be installed and will -invoke the ``main_func`` when called by the user. For detailed usage, including -managing the additional or optional dependencies, go to :ref:`entry_point`. - -Dependency management -===================== - -``setuptools`` supports automatically installing dependencies when a package is -installed. 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:: - - setup( - #... - install_requires = "docutils >= 0.3" - ) - -When your project is installed, either by using pip, ``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. - -For more advanced use, see :ref:`dependencies` - -Including Data Files -==================== - -The distutils have traditionally allowed installation of "data files", which -are placed in a platform-specific location. Setuptools offers three ways to -specify data files to be included in your packages. For the simpliest use, you -can simply use the ``include_package_data`` keyword e.g.:: - - setup( - ... - include_package_data=True - ) - -This tells setuptools to install any data files it finds in your packages. -The data files must be specified via the distutils' ``MANIFEST.in`` file. - -For more details, see :ref:`datafiles` - -Development mode -================ - -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. - -To do this, use the ``setup.py develop`` command. It works very similarly to -``setup.py install``, 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. - -for more information, go to :ref:`development_mode` - -Distributing a ``setuptools``-based project -=========================================== -Before you begin, make sure you have the latest versions of setuptools and wheel:: - - pip install --upgrade setuptools wheel - -To build a setuptools project, run this command from the same directory where -setup.py is located:: - - setup.py sdist bdist_wheel - -This will generate distribution archives in the `dist` directory. - -Before you upload the generated archives make sure you're registered on -https://test.pypi.org/account/register/. You will also need to verify your email -to be able to upload any packages. -You should install twine to be able to upload packages:: - - pip install --upgrade twine - -Now, to upload these archives, run:: - - twine upload --repository-url https://test.pypi.org/legacy/ dist/* - -To install your newly uploaded package ``example_pkg``, you can use pip:: - - pip install --index-url https://test.pypi.org/simple/ example_pkg - -The next following sections will walk you through all of the available functions -``setuptools`` offers in excrutiating details (including those already mentioned) -for more advanced use. diff --git a/docs/userguide/quickstart.txt b/docs/userguide/quickstart.txt index 535227a0..4a851ee3 100644 --- a/docs/userguide/quickstart.txt +++ b/docs/userguide/quickstart.txt @@ -74,6 +74,137 @@ dependencies, and perhaps some data files and scripts:: # could also include long_description, download_url, etc. ) +Automatic package discovery +=========================== +For simple projects, it's usually easy enough to manually add packages to +the ``packages`` argument of ``setup()``. However, for very large projects +, it can be a big burden to keep the package list updated. setuptools therefore +provides tools to ease the burden. + +``find_packages()`` takes a source directory and two lists of package name +patterns to exclude and include. It then walks the target directory, filtering +by inclusion patterns, and return a list of Python packages (any directory). +Finally, exclusion patterns are applied to remove matching packages. + +For example:: + #... + from setuptools import find_packages() + + setup( + #..., + packages = find_packages() + ) + +For more details and advanced use, go to :ref:`package_discovery` + +Entry points and automatic script creation +=========================================== + +Setuptools support automatic creation of scripts upon installation, that runs +code within your package if you specify them with the ``entry_point`` keyword. +This is what allows you to run commands like ``pip install`` instead of having +to type ``python -m pip install``. To accomplish this, consider the following +example:: + + setup( + #.... + entry_points={ + "console_scripts": [ + "foo = my_package.some_module:main_func", + ], + } + ) + +When this project is installed, a ``foo`` script will be installed and will +invoke the ``main_func`` when called by the user. For detailed usage, including +managing the additional or optional dependencies, go to :ref:`entry_point`. + +Dependency management +===================== + +``setuptools`` supports automatically installing dependencies when a package is +installed. 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:: + + setup( + #... + install_requires = "docutils >= 0.3" + ) + +When your project is installed, either by using pip, ``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. + +For more advanced use, see :ref:`dependencies` + +Including Data Files +==================== + +The distutils have traditionally allowed installation of "data files", which +are placed in a platform-specific location. Setuptools offers three ways to +specify data files to be included in your packages. For the simpliest use, you +can simply use the ``include_package_data`` keyword e.g.:: + + setup( + ... + include_package_data=True + ) + +This tells setuptools to install any data files it finds in your packages. +The data files must be specified via the distutils' ``MANIFEST.in`` file. + +For more details, see :ref:`datafiles` + +Development mode +================ + +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. + +To do this, use the ``setup.py develop`` command. It works very similarly to +``setup.py install``, 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. + +for more information, go to :ref:`development_mode` + +Distributing a ``setuptools``-based project +=========================================== +Before you begin, make sure you have the latest versions of setuptools and wheel:: + + pip install --upgrade setuptools wheel + +To build a setuptools project, run this command from the same directory where +setup.py is located:: + + setup.py sdist bdist_wheel + +This will generate distribution archives in the `dist` directory. + +Before you upload the generated archives make sure you're registered on +https://test.pypi.org/account/register/. You will also need to verify your email +to be able to upload any packages. +You should install twine to be able to upload packages:: + + pip install --upgrade twine + +Now, to upload these archives, run:: + + twine upload --repository-url https://test.pypi.org/legacy/ dist/* + +To install your newly uploaded package ``example_pkg``, you can use pip:: + + pip install --index-url https://test.pypi.org/simple/ example_pkg + +The next following sections will walk you through all of the available functions +``setuptools`` offers in excrutiating details (including those already mentioned) +for more advanced use. -- cgit v1.2.1 From 5d0859f38e2524cc4e5dd4f8492cd37622dc58a1 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 11:27:02 -0400 Subject: docs: update userguide index --- docs/userguide/index.txt | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/index.txt b/docs/userguide/index.txt index 4d7bb2a7..0fa32fd2 100644 --- a/docs/userguide/index.txt +++ b/docs/userguide/index.txt @@ -13,8 +13,14 @@ ordinary Python packages based on the ``distutils``. .. toctree:: :maxdepth: 1 - Quickstart - Functionalities - Declarative config - keyword reference - Command reference + quickstart + package_discovery + entry_point + dependencies_management + datafiles + development_mode + distribution + extension + declarative_config + keywords + commands -- cgit v1.2.1 From c0794ed0d6dbeec85e366984db1496747aaaefc1 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 12:36:20 -0400 Subject: docs: udpate title of quickstart --- docs/userguide/quickstart.txt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.txt b/docs/userguide/quickstart.txt index 4a851ee3..fb40b12a 100644 --- a/docs/userguide/quickstart.txt +++ b/docs/userguide/quickstart.txt @@ -1,5 +1,9 @@ -Installing ``setuptools`` -========================= +========================== +``setuptools`` Quickstart +========================== + +Installation +============ .. _Installing Packages: https://packaging.python.org/tutorials/installing-packages/ @@ -12,8 +16,8 @@ Refer to `Installing Packages`_ guide for more information. Basic Use ========= -For basic use of setuptools, just import things from setuptools instead of -the distutils. Here's a minimal setup script using setuptools:: +For basic use of setuptools, just import things from setuptools. Here's a +minimal setup script using setuptools:: from setuptools import setup, find_packages setup( -- cgit v1.2.1 From 6c6568dbf406597ffd6bd1e77ec3081b70992f7c Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 12:36:37 -0400 Subject: docs: dedicate file for package discovery --- docs/userguide/package_discovery.txt | 169 +++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 docs/userguide/package_discovery.txt (limited to 'docs/userguide') diff --git a/docs/userguide/package_discovery.txt b/docs/userguide/package_discovery.txt new file mode 100644 index 00000000..722f6fcd --- /dev/null +++ b/docs/userguide/package_discovery.txt @@ -0,0 +1,169 @@ +=================== +Package Discovery +=================== + + + +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 two lists of package name +patterns to exclude and include. 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, filtering by inclusion +patterns, and finds Python packages (any directory). Packages are only +recognized if they include an ``__init__.py`` file. Finally, exclusion +patterns are applied to remove matching packages. + +Inclusion and 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:: + + 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 parameters, 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. + +``find_namespace_packages()`` +----------------------------- +In Python 3.3+, ``setuptools`` also provides the ``find_namespace_packages`` variant +of ``find_packages``, which has the same function signature as +``find_packages``, but works with `PEP 420`_ compliant implicit namespace +packages. Here is a minimal setup script using ``find_namespace_packages``:: + + from setuptools import setup, find_namespace_packages + setup( + name="HelloWorld", + version="0.1", + packages=find_namespace_packages(), + ) + + +Keep in mind that according to PEP 420, you may have to either re-organize your +codebase a bit or define a few exclusions, as the definition of an implicit +namespace package is quite lenient, so for a project organized like so:: + + + ├── namespace + │   └── mypackage + │   ├── __init__.py + │   └── mod1.py + ├── setup.py + └── tests + └── test_mod1.py + +A naive ``find_namespace_packages()`` would install both ``namespace.mypackage`` and a +top-level package called ``tests``! One way to avoid this problem is to use the +``include`` keyword to whitelist the packages to include, like so:: + + from setuptools import setup, find_namespace_packages + + setup( + name="namespace.mypackage", + version="0.1", + packages=find_namespace_packages(include=["namespace.*"]) + ) + +Another option is to use the "src" layout, where all package code is placed in +the ``src`` directory, like so:: + + + ├── setup.py + ├── src + │   └── namespace + │   └── mypackage + │   ├── __init__.py + │   └── mod1.py + └── tests + └── test_mod1.py + +With this layout, the package directory is specified as ``src``, as such:: + + setup(name="namespace.mypackage", + version="0.1", + package_dir={"": "src"}, + packages=find_namespace_packages(where="src")) + +.. _PEP 420: https://www.python.org/dev/peps/pep-0420/ + + +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 then 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. The argument should list the namespace packages that the egg +participates in. For example, the ZopeInterface project might do this:: + + 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. When these projects are +installed and used, Python will see them both as part of a "virtual" ``zope`` +package, even though they will be installed in different locations. + +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 +*must* contain the line:: + + __import__("pkg_resources").declare_namespace(__name__) + +This code ensures that the namespace package machinery is operating and that +the current package is registered as a namespace package. + +You must NOT include any other code and data in a namespace package's +``__init__.py``. Even though it may appear to work during development, or when +projects are installed as ``.egg`` files, it will not work when the projects +are installed using "system" packaging tools -- in such cases the +``__init__.py`` files will not be installed, let alone executed. + +You must include the ``declare_namespace()`` line in the ``__init__.py`` of +*every* project that has contents for the namespace package in question, in +order to ensure that the namespace will be declared regardless of which +project's copy of ``__init__.py`` is loaded first. If the first loaded +``__init__.py`` doesn't declare it, it will never *be* declared, because no +other copies will ever be loaded! \ No newline at end of file -- cgit v1.2.1 From 127cfdfb9a01cfe12a7e6d8bf81aa04c56c2d5f1 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 12:37:17 -0400 Subject: docs: udpate package_discovery.txt --- docs/userguide/package_discovery.txt | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/package_discovery.txt b/docs/userguide/package_discovery.txt index 722f6fcd..8ba12cdf 100644 --- a/docs/userguide/package_discovery.txt +++ b/docs/userguide/package_discovery.txt @@ -2,15 +2,27 @@ Package Discovery =================== +``Setuptools`` provide powerful tools to handle package discovery, including +support for namespace package. The following explain how you include package +in your ``setup`` script:: + + setup( + packages = ['mypkg1', 'mypkg2'] + ) + +To speed things up, we introduce two functions provided by setuptools:: + + from setuptools import find_packages + +or:: + + from setuptools import find_namespace_packages 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. +Let's start with the first tool. ``find_packages()`` takes a source directory and two lists of package name patterns to exclude and include. If omitted, the source directory defaults to @@ -166,4 +178,4 @@ You must include the ``declare_namespace()`` line in the ``__init__.py`` of order to ensure that the namespace will be declared regardless of which project's copy of ``__init__.py`` is loaded first. If the first loaded ``__init__.py`` doesn't declare it, it will never *be* declared, because no -other copies will ever be loaded! \ No newline at end of file +other copies will ever be loaded! -- cgit v1.2.1 From 092aec60cb0a947a4030c9fd7c231e6c82ff88e5 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 12:38:09 -0400 Subject: docs: dedicate a file for entry points --- docs/userguide/entry_point.txt | 115 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 docs/userguide/entry_point.txt (limited to 'docs/userguide') diff --git a/docs/userguide/entry_point.txt b/docs/userguide/entry_point.txt new file mode 100644 index 00000000..18211a72 --- /dev/null +++ b/docs/userguide/entry_point.txt @@ -0,0 +1,115 @@ +========================================== +Entry Points and Automatic Script Creation +========================================== + +Packaging and installing scripts can be a bit awkward with the distutils. For +one thing, there's no easy way to have a script's filename match local +conventions on both Windows and POSIX platforms. For another, you often have +to create a separate file just for the "main" script, when your actual "main" +is a function in a module somewhere. And even in Python 2.4, using the ``-m`` +option only works for actual ``.py`` files that aren't installed in a package. + +``setuptools`` fixes all of these problems by automatically generating scripts +for you with the correct extension, and on Windows it will even create an +``.exe`` file so that users don't have to change their ``PATHEXT`` settings. +The way to use this feature is to define "entry points" in your setup script +that indicate what function the generated script should import and run. For +example, to create two console scripts called ``foo`` and ``bar``, and a GUI +script called ``baz``, you might do something like this:: + + setup( + # other arguments here... + entry_points={ + "console_scripts": [ + "foo = my_package.some_module:main_func", + "bar = other_module:some_func", + ], + "gui_scripts": [ + "baz = my_package_gui:start_func", + ] + } + ) + +When this project is installed on non-Windows platforms (using "setup.py +install", "setup.py develop", or with pip), a set of ``foo``, ``bar``, +and ``baz`` scripts will be installed that import ``main_func`` and +``some_func`` from the specified modules. The functions you specify are +called with no arguments, and their return value is passed to +``sys.exit()``, so you can return an errorlevel or message to print to +stderr. + +On Windows, a set of ``foo.exe``, ``bar.exe``, and ``baz.exe`` launchers are +created, alongside a set of ``foo.py``, ``bar.py``, and ``baz.pyw`` files. The +``.exe`` wrappers find and execute the right version of Python to run the +``.py`` or ``.pyw`` file. + +You may define as many "console script" and "gui script" entry points as you +like, and each one can optionally specify "extras" that it depends on, that +will be added to ``sys.path`` when the script is run. For more information on +"extras", see the section below on `Declaring Extras`_. For more information +on "entry points" in general, see the section below on `Dynamic Discovery of +Services and Plugins`_. + + +Dynamic Discovery of Services and Plugins +----------------------------------------- + +``setuptools`` supports creating libraries that "plug in" to extensible +applications and frameworks, by letting you register "entry points" in your +project that can be imported by the application or framework. + +For example, suppose that a blogging tool wants to support plugins +that provide translation for various file types to the blog's output format. +The framework might define an "entry point group" called ``blogtool.parsers``, +and then allow plugins to register entry points for the file extensions they +support. + +This would allow people to create distributions that contain one or more +parsers for different file types, and then the blogging tool would be able to +find the parsers at runtime by looking up an entry point for the file +extension (or mime type, or however it wants to). + +Note that if the blogging tool includes parsers for certain file formats, it +can register these as entry points in its own setup script, which means it +doesn't have to special-case its built-in formats. They can just be treated +the same as any other plugin's entry points would be. + +If you're creating a project that plugs in to an existing application or +framework, you'll need to know what entry points or entry point groups are +defined by that application or framework. Then, you can register entry points +in your setup script. Here are a few examples of ways you might register an +``.rst`` file parser entry point in the ``blogtool.parsers`` entry point group, +for our hypothetical blogging tool:: + + setup( + # ... + entry_points={"blogtool.parsers": ".rst = some_module:SomeClass"} + ) + + setup( + # ... + entry_points={"blogtool.parsers": [".rst = some_module:a_func"]} + ) + + setup( + # ... + entry_points=""" + [blogtool.parsers] + .rst = some.nested.module:SomeClass.some_classmethod [reST] + """, + extras_require=dict(reST="Docutils>=0.3.5") + ) + +The ``entry_points`` argument to ``setup()`` accepts either a string with +``.ini``-style sections, or a dictionary mapping entry point group names to +either strings or lists of strings containing entry point specifiers. An +entry point specifier consists of a name and value, separated by an ``=`` +sign. The value consists of a dotted module name, optionally followed by a +``:`` and a dotted identifier naming an object within the module. It can +also include a bracketed list of "extras" that are required for the entry +point to be used. When the invoking application or framework requests loading +of an entry point, any requirements implied by the associated extras will be +passed to ``pkg_resources.require()``, so that an appropriate error message +can be displayed if the needed package(s) are missing. (Of course, the +invoking app or framework can ignore such errors if it wants to make an entry +point optional if a requirement isn't installed.) \ No newline at end of file -- cgit v1.2.1 From 385b40d5640ea8262245411eb0c43f67af4eb2a4 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 12:39:30 -0400 Subject: docs: update userguide index to match filename --- docs/userguide/index.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/index.txt b/docs/userguide/index.txt index 0fa32fd2..ae9c9d77 100644 --- a/docs/userguide/index.txt +++ b/docs/userguide/index.txt @@ -16,8 +16,8 @@ ordinary Python packages based on the ``distutils``. quickstart package_discovery entry_point - dependencies_management - datafiles + dependency_management + data_files development_mode distribution extension -- cgit v1.2.1 From 34f1fa1b86a63f3021ccb7f842220d8b011c9e1d Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 12:39:48 -0400 Subject: docs: dedicate a file for dependency management --- docs/userguide/dependency_management.txt | 255 +++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 docs/userguide/dependency_management.txt (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.txt b/docs/userguide/dependency_management.txt new file mode 100644 index 00000000..18ba952f --- /dev/null +++ b/docs/userguide/dependency_management.txt @@ -0,0 +1,255 @@ +===================================== +Dependencies Management in Setuptools +===================================== + +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 pip 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 ``-``. + +Version specifiers for a given project are internally sorted into ascending +version order, and used to establish what ranges of versions are acceptable. +Adjacent redundant conditions are also consolidated (e.g. ``">1, >2"`` becomes +``">2"``, and ``"<2,<3"`` becomes ``"<2"``). ``"!="`` versions are excised from +the ranges they fall within. A project's version is then checked for +membership in the resulting ranges. (Note that providing conflicting conditions +for the same version (e.g. "<2,>=2" or "==2,!=2") is meaningless and may +therefore produce bizarre results.) + +Here are some example requirement specifiers:: + + 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 pip, ``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. + +2. 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). + +3. 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``.) + +Dependencies that aren't in PyPI +-------------------------------- + +.. warning:: + Dependency links support has been dropped by pip starting with version + 19.0 (released 2019-01-22). + +If your project depends on packages that don't exist on PyPI, you may still be +able to depend on them, as long as they are available for download as: + +- an egg, in the standard distutils ``sdist`` format, +- a single ``.py`` file, or +- a VCS repository (Subversion, Mercurial, or Git). + +You just need to add some URLs to the ``dependency_links`` argument to +``setup()``. + +The URLs must be either: + +1. direct download URLs, +2. the URLs of web pages that contain direct download links, or +3. the repository's URL + +In general, it's better to link to web pages, because it is usually less +complex to update a web page than to release a new version of your project. +You can also use a SourceForge ``showfiles.php`` link in the case where a +package you depend on is distributed via SourceForge. + +If you depend on a package that's distributed as a single ``.py`` file, you +must include an ``"#egg=project-version"`` suffix to the URL, to give a project +name and version number. (Be sure to escape any dashes in the name or version +by replacing them with underscores.) EasyInstall will recognize this suffix +and automatically create a trivial ``setup.py`` to wrap the single ``.py`` file +as an egg. + +In the case of a VCS checkout, you should also append ``#egg=project-version`` +in order to identify for what package that checkout should be used. You can +append ``@REV`` to the URL's path (before the fragment) to specify a revision. +Additionally, you can also force the VCS being used by prepending the URL with +a certain prefix. Currently available are: + +- ``svn+URL`` for Subversion, +- ``git+URL`` for Git, and +- ``hg+URL`` for Mercurial + +A more complete example would be: + + ``vcs+proto://host/path@revision#egg=project-version`` + +Be careful with the version. It should match the one inside the project files. +If you want to disregard the version, you have to omit it both in the +``requires`` and in the URL's fragment. + +This will do a checkout (or a clone, in Git and Mercurial parlance) to a +temporary folder and run ``setup.py bdist_egg``. + +The ``dependency_links`` option takes the form of a list of URL strings. For +example, this will cause a search of the specified page for eggs or source +distributions, if the package's dependencies aren't already installed:: + + setup( + ... + dependency_links=[ + "http://peak.telecommunity.com/snapshots/" + ], + ) + + +.. _Declaring Extras: + + +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:: + + setup( + name="Project-A", + ... + extras_require={ + "PDF": ["ReportLab>=1.2", "RXP"], + "reST": ["docutils>=0.3"], + } + ) + +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 "pip install" +command line.) + +Extras can be used by a project's `entry points`_ to specify dynamic +dependencies. For example, if Project A includes a "rst2pdf" script, it might +declare it like this, so that the "PDF" requirements are only resolved if the +"rst2pdf" script is run:: + + setup( + name="Project-A", + ... + entry_points={ + "console_scripts": [ + "rst2pdf = project_a.tools.pdfgen [PDF]", + "rst2html = project_a.tools.htmlgen", + # more script entry points ... + ], + } + ) + +Projects can also use another project's extras when specifying dependencies. +For example, if project B needs "project A" with PDF support installed, it +might declare the dependency like this:: + + 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. + +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 could change its +setup to this:: + + 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. + +.. _Platform Specific Dependencies: + + +Declaring platform specific dependencies +---------------------------------------- + +Sometimes a project might require a dependency to run on a specific platform. +This could to a package that back ports a module so that it can be used in +older python versions. Or it could be a package that is required to run on a +specific operating system. This will allow a project to work on multiple +different platforms without installing dependencies that are not required for +a platform that is installing the project. + +For example, here is a project that uses the ``enum`` module and ``pywin32``:: + + setup( + name="Project", + ... + install_requires=[ + "enum34;python_version<'3.4'", + "pywin32 >= 1.0;platform_system=='Windows'" + ] + ) + +Since the ``enum`` module was added in Python 3.4, it should only be installed +if the python version is earlier. Since ``pywin32`` will only be used on +windows, it should only be installed when the operating system is Windows. +Specifying version requirements for the dependencies is supported as normal. + +The environmental markers that may be used for testing platform types are +detailed in `PEP 508`_. + +.. _PEP 508: https://www.python.org/dev/peps/pep-0508/ -- cgit v1.2.1 From bf6e567a736943ae5d54f21b59005b900c909a28 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 12:40:46 -0400 Subject: docs: udpate quickstart to match ref file --- docs/userguide/quickstart.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.txt b/docs/userguide/quickstart.txt index fb40b12a..e75d74e1 100644 --- a/docs/userguide/quickstart.txt +++ b/docs/userguide/quickstart.txt @@ -141,7 +141,7 @@ When your project is installed, either by using pip, ``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. -For more advanced use, see :ref:`dependencies` +For more advanced use, see :ref:`dependency_management` Including Data Files ==================== @@ -210,5 +210,3 @@ To install your newly uploaded package ``example_pkg``, you can use pip:: The next following sections will walk you through all of the available functions ``setuptools`` offers in excrutiating details (including those already mentioned) for more advanced use. - - -- cgit v1.2.1 From 503d22a209159b9ad990da7ecc5445496f8b2cd7 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 12:41:14 -0400 Subject: docs: dedicate a file for development mode --- docs/userguide/development_mode.txt | 60 +++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 docs/userguide/development_mode.txt (limited to 'docs/userguide') diff --git a/docs/userguide/development_mode.txt b/docs/userguide/development_mode.txt new file mode 100644 index 00000000..9d4e7581 --- /dev/null +++ b/docs/userguide/development_mode.txt @@ -0,0 +1,60 @@ +"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``, 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. + +If you have enabled the ``use_2to3`` flag, then of course the ``.egg-link`` +will not link directly to your source code when run under Python 3, since +that source code would be made for Python 2 and not work under Python 3. +Instead the ``setup.py develop`` will build Python 3 code under the ``build`` +directory, and link there. This means that after doing code changes you will +have to run ``setup.py build`` before these changes are picked up by your +Python 3 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. + +Note that you can also apply setuptools commands to non-setuptools projects, +using commands like this:: + + python -c "import setuptools; with open('setup.py') as f: exec(compile(f.read(), 'setup.py', 'exec'))" develop + +That is, you can simply list the normal setup commands and options following +the quoted part. \ No newline at end of file -- cgit v1.2.1 From 6f43f47eb62ec6ac0a63b6fd1487192b10b1438b Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 12:41:56 -0400 Subject: docs: update index to match filename --- docs/userguide/index.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/index.txt b/docs/userguide/index.txt index ae9c9d77..abee331a 100644 --- a/docs/userguide/index.txt +++ b/docs/userguide/index.txt @@ -17,7 +17,7 @@ ordinary Python packages based on the ``distutils``. package_discovery entry_point dependency_management - data_files + datafiles development_mode distribution extension -- cgit v1.2.1 From 7b4f1b0f23c445583d96e826a9040769dd8f5e49 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 12:42:13 -0400 Subject: docs: dedicate a file for datafiles support --- docs/userguide/datafiles.txt | 174 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 docs/userguide/datafiles.txt (limited to 'docs/userguide') diff --git a/docs/userguide/datafiles.txt b/docs/userguide/datafiles.txt new file mode 100644 index 00000000..315ec724 --- /dev/null +++ b/docs/userguide/datafiles.txt @@ -0,0 +1,174 @@ +==================== +Data Files Support +==================== + +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 offers three ways to specify data files to be included in your +packages. First, you can simply use the ``include_package_data`` keyword, +e.g.:: + + from setuptools import setup, find_packages + setup( + ... + include_package_data=True + ) + +This tells setuptools to install any data files it finds in your packages. +The data files must be specified via the distutils' ``MANIFEST.in`` file. +(They can also be tracked by a revision control system, using an appropriate +plugin. See the section below on `Adding Support for Revision Control +Systems`_ for information on how to write such plugins.) + +If you want finer-grained control over what files are included (for example, +if you have documentation files in your package directories and want to exclude +them from installation), then you can also use the ``package_data`` keyword, +e.g.:: + + 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:: + + setup.py + src/ + mypkg/ + __init__.py + mypkg.txt + data/ + somefile.dat + otherdata.dat + +The setuptools setup file might look like this:: + + 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. + +If datafiles are contained in a subdirectory of a package that isn't a package +itself (no ``__init__.py``), then the subdirectory names (or ``*``) are required +in the ``package_data`` argument (as shown above with ``"data/*.dat"``). + +When building an ``sdist``, the datafiles are also drawn from the +``package_name.egg-info/SOURCES.txt`` file, so make sure that this is removed if +the ``setup.py`` ``package_data`` list is updated before calling ``setup.py``. + +(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 `some documentation for the feature`__ available on the +python.org website. If using the setuptools-specific ``include_package_data`` +argument, files specified by ``package_data`` will *not* be automatically +added to the manifest unless they are listed in the MANIFEST.in file.) + +__ https://docs.python.org/3/distutils/setupscript.html#installing-package-data + +Sometimes, the ``include_package_data`` or ``package_data`` options alone +aren't sufficient to precisely define what files you want included. For +example, you may want to include package README files in your revision control +system and source distributions, but exclude them from being installed. So, +setuptools offers an ``exclude_package_data`` option as well, that allows you +to do things like this:: + + 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 + + include_package_data=True, # include everything in source control + + # ...but exclude README.txt from all packages + exclude_package_data={"": ["README.txt"]}, + ) + +The ``exclude_package_data`` option is a dictionary mapping package names to +lists of wildcard patterns, just like the ``package_data`` option. And, just +as with that option, a key of ``""`` will apply the given pattern(s) to all +packages. However, any files that match these patterns will be *excluded* +from installation, even if they were listed in ``package_data`` or were +included as a result of using ``include_package_data``. + +In summary, the three options allow you to: + +``include_package_data`` + Accept all data files and directories matched by ``MANIFEST.in``. + +``package_data`` + Specify additional patterns to match files that may or may + not be matched by ``MANIFEST.in`` or found in source control. + +``exclude_package_data`` + Specify patterns for data files and directories that should *not* be + included when a package is installed, even if they would otherwise have + been included due to the use of the preceding options. + +NOTE: Due to the way the distutils build process works, a data file that you +include in your project and then stop including may be "orphaned" in your +project's build directories, requiring you to run ``setup.py clean --all`` to +fully remove them. This may also be important for your users and contributors +if they track intermediate revisions of your project using Subversion; be sure +to let them know when you make changes that remove files from inclusion so they +can run ``setup.py clean --all``. + +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 :ref:`ResourceManager 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 `Importlib Resources`_ for +a quick example of converting code that uses ``__file__`` to use +``pkg_resources`` instead. + +.. _Importlib Resources: https://docs.python.org/3/library/importlib.html#module-importlib.resources + + +Non-Package Data Files +---------------------- + +Historically, ``setuptools`` by way of ``easy_install`` would encapsulate data +files from the distribution into the egg (see `the old docs +`_). As eggs are deprecated and pip-based installs +fall back to the platform-specific location for installing data files, there is +no supported facility to reliably retrieve these resources. + +Instead, the PyPA recommends that any data files you wish to be accessible at +run time be included in the package. \ No newline at end of file -- cgit v1.2.1 From 5be9afe13040473ec2e5765920af18c85a749157 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 12:43:22 -0400 Subject: docs: dedicate a file for distribution guide --- docs/userguide/distribution.txt | 240 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100644 docs/userguide/distribution.txt (limited to 'docs/userguide') diff --git a/docs/userguide/distribution.txt b/docs/userguide/distribution.txt new file mode 100644 index 00000000..77ea2660 --- /dev/null +++ b/docs/userguide/distribution.txt @@ -0,0 +1,240 @@ +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: + +* A manually-specified pre-release tag, such as "build" or "dev", or a + manually-specified post-release tag, such as a build or revision number + (``--tag-build=STRING, -bSTRING``) + +* An 8-character representation of the build date (``--tag-date, -d``), as + a postrelease tag + +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, before you release your project, be sure to see the section above on +`Specifying Your Project's Version`_ for more information about how pre- and +post-release tags affect how version numbers are interpreted. This is +important in order to make sure that dependency processing tools will know +which versions of your project are newer than others.) + +Finally, 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:: + + 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 script or 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 with pluggable endpoints for looking up files to include. If you are +using a revision control system, and your source distributions only need to +include files that you're tracking in revision control, use a corresponding +plugin instead of writing a ``MANIFEST.in`` file. See the section below on +`Adding Support for Revision Control Systems`_ for information on plugins. + +If you need to include automatically generated files, or files that are kept in +an unsupported revision control system, you'll need to create a ``MANIFEST.in`` +file to specify any files that the default file location algorithm doesn't +catch. See the distutils documentation for more information on the format of +the ``MANIFEST.in`` file. + +But, be sure to ignore any part of the distutils documentation that deals with +``MANIFEST`` or how it's generated from ``MANIFEST.in``; setuptools shields you +from these issues and doesn't work the same way in any case. Unlike the +distutils, setuptools regenerates the source distribution manifest file +every time you build a source distribution, and it builds it inside the +project's ``.egg-info`` directory, out of the way of your main project +directory. You therefore need not worry about whether it is up-to-date or not. + +Indeed, because setuptools' approach to determining the contents of a source +distribution is so much simpler, its ``sdist`` command omits nearly all of +the options that the distutils' more complex ``sdist`` process requires. For +all practical purposes, you'll probably use only the ``--formats`` option, if +you use any option at all. + + +Making "Official" (Non-Snapshot) Releases +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When you make an official release, creating source or binary distributions, +you will need to override the tag settings from ``setup.cfg``, so that you +don't end up registering versions like ``foobar-0.7a1.dev-r34832``. This is +easy to do if you are developing on the trunk and using tags or branches for +your releases - just make the change to ``setup.cfg`` after branching or +tagging the release, so the trunk will still produce development snapshots. + +Alternately, if you are not branching for releases, you can override the +default version options on the command line, using something like:: + + setup.py egg_info -Db "" sdist bdist_egg + +The first part of this command (``egg_info -Db ""``) will override the +configured tag information, before creating source and binary eggs. Thus, these +commands will use the plain version from your ``setup.py``, without adding the +build designation string. + +Of course, if you will be doing this a lot, you may wish to create a personal +alias for this operation, e.g.:: + + setup.py alias -u release egg_info -Db "" + +You can then use it like this:: + + setup.py release sdist bdist_egg + +Or of course you can create more elaborate aliases that do all of the above. +See the sections below on the `egg_info`_ and `alias`_ commands for more ideas. + +Distributing Extensions compiled with Cython +-------------------------------------------- + +``setuptools`` will detect at build time whether Cython is installed or not. +If Cython is not found ``setuptools`` will ignore pyx files. + +To ensure Cython is available, include Cython in the build-requires section +of your pyproject.toml:: + + [build-system] + requires=[..., "cython"] + +Built with pip 10 or later, that declaration is sufficient to include Cython +in the build. For broader compatibility, declare the dependency in your +setup-requires of setup.cfg:: + + [options] + setup_requires = + ... + cython + +As long as Cython is present in the build environment, ``setuptools`` includes +transparent support for building Cython extensions, as +long as extensions are defined using ``setuptools.Extension``. + +If you follow these rules, you can safely list ``.pyx`` files as the source +of your ``Extension`` objects in the setup script. If it is, then ``setuptools`` +will use it. + +Of course, for this to work, your source distributions must include the C +code generated by Cython, 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 a revision +control system will be able to build it even if they don't have Cython +installed, and that your source releases will be similarly usable with or +without Cython. + +Specifying Your Project's Version +--------------------------------- + +Setuptools can work well with most versioning schemes; there are, however, a +few special things to watch out for, in order to ensure that setuptools and +other tools can always tell what version of your package is newer than another +version. Knowing these things will also help you correctly specify what +versions of other projects your project depends on. + +A version consists of an alternating series of release numbers and pre-release +or post-release tags. A release number is a series of digits punctuated by +dots, such as ``2.4`` or ``0.5``. Each series of digits is treated +numerically, so releases ``2.1`` and ``2.1.0`` are different ways to spell the +same release number, denoting the first subrelease of release 2. But ``2.10`` +is the *tenth* subrelease of release 2, and so is a different and newer release +from ``2.1`` or ``2.1.0``. Leading zeros within a series of digits are also +ignored, so ``2.01`` is the same as ``2.1``, and different from ``2.0.1``. + +Following a release number, you can have either a pre-release or post-release +tag. Pre-release tags make a version be considered *older* than the version +they are appended to. So, revision ``2.4`` is *newer* than revision ``2.4c1``, +which in turn is newer than ``2.4b1`` or ``2.4a1``. Postrelease tags make +a version be considered *newer* than the version they are appended to. So, +revisions like ``2.4-1`` and ``2.4pl3`` are newer than ``2.4``, but are *older* +than ``2.4.1`` (which has a higher release number). + +A pre-release tag is a series of letters that are alphabetically before +"final". Some examples of prerelease tags would include ``alpha``, ``beta``, +``a``, ``c``, ``dev``, and so on. You do not have to place a dot or dash +before the prerelease tag if it's immediately after a number, but it's okay to +do so if you prefer. Thus, ``2.4c1`` and ``2.4.c1`` and ``2.4-c1`` all +represent release candidate 1 of version ``2.4``, and are treated as identical +by setuptools. + +In addition, there are three special prerelease tags that are treated as if +they were the letter ``c``: ``pre``, ``preview``, and ``rc``. So, version +``2.4rc1``, ``2.4pre1`` and ``2.4preview1`` are all the exact same version as +``2.4c1``, and are treated as identical by setuptools. + +A post-release tag is either a series of letters that are alphabetically +greater than or equal to "final", or a dash (``-``). Post-release tags are +generally used to separate patch numbers, port numbers, build numbers, revision +numbers, or date stamps from the release number. For example, the version +``2.4-r1263`` might denote Subversion revision 1263 of a post-release patch of +version ``2.4``. Or you might use ``2.4-20051127`` to denote a date-stamped +post-release. + +Notice that after each pre or post-release tag, you are free to place another +release number, followed again by more pre- or post-release tags. For example, +``0.6a9.dev-r41475`` could denote Subversion revision 41475 of the in- +development version of the ninth alpha of release 0.6. Notice that ``dev`` is +a pre-release tag, so this version is a *lower* version number than ``0.6a9``, +which would be the actual ninth alpha of release 0.6. But the ``-r41475`` is +a post-release tag, so this version is *newer* than ``0.6a9.dev``. + +For the most part, setuptools' interpretation of version numbers is intuitive, +but here are a few tips that will keep you out of trouble in the corner cases: + +* Don't stick adjoining pre-release tags together without a dot or number + between them. Version ``1.9adev`` is the ``adev`` prerelease of ``1.9``, + *not* a development pre-release of ``1.9a``. Use ``.dev`` instead, as in + ``1.9a.dev``, or separate the prerelease tags with a number, as in + ``1.9a0dev``. ``1.9a.dev``, ``1.9a0dev``, and even ``1.9.a.dev`` are + identical versions from setuptools' point of view, so you can use whatever + scheme you prefer. + +* If you want to be certain that your chosen numbering scheme works the way + you think it will, you can use the ``pkg_resources.parse_version()`` function + to compare different version numbers:: + + >>> from pkg_resources import parse_version + >>> parse_version("1.9.a.dev") == parse_version("1.9a0dev") + True + >>> parse_version("2.1-rc2") < parse_version("2.1") + True + >>> parse_version("0.6a9dev-r41475") < parse_version("0.6a9") + True + +Once you've decided on a version numbering scheme for your project, you can +have setuptools automatically tag your in-development releases with various +pre- or post-release tags. See the following sections for more details: + +* `Tagging and "Daily Build" or "Snapshot" Releases`_ +* The `egg_info`_ command \ No newline at end of file -- cgit v1.2.1 From a99713c017c77c215c278ad759796cdf928c89b7 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 12:44:13 -0400 Subject: docs: dedicate a file for extending setuptools --- docs/userguide/extension.txt | 235 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 docs/userguide/extension.txt (limited to 'docs/userguide') diff --git a/docs/userguide/extension.txt b/docs/userguide/extension.txt new file mode 100644 index 00000000..1e4846fc --- /dev/null +++ b/docs/userguide/extension.txt @@ -0,0 +1,235 @@ +Creating ``distutils`` Extensions +================================= + +It can be hard to add new commands or setup arguments to the distutils. But +the ``setuptools`` package makes it a bit easier, by allowing you to distribute +a distutils extension as a separate project, and then have projects that need +the extension just refer to it in their ``setup_requires`` argument. + +With ``setuptools``, your distutils extension projects can hook in new +commands and ``setup()`` arguments just by defining "entry points". These +are mappings from command or argument names to a specification of where to +import a handler from. (See the section on `Dynamic Discovery of Services and +Plugins`_ above for some more background on entry points.) + + +Adding Commands +--------------- + +You can add new ``setup`` commands by defining entry points in the +``distutils.commands`` group. For example, if you wanted to add a ``foo`` +command, you might add something like this to your distutils extension +project's setup script:: + + setup( + # ... + entry_points={ + "distutils.commands": [ + "foo = mypackage.some_module:foo", + ], + }, + ) + +(Assuming, of course, that the ``foo`` class in ``mypackage.some_module`` is +a ``setuptools.Command`` subclass.) + +Once a project containing such entry points has been activated on ``sys.path``, +(e.g. by running "install" or "develop" with a site-packages installation +directory) the command(s) will be available to any ``setuptools``-based setup +scripts. It is not necessary to use the ``--command-packages`` option or +to monkeypatch the ``distutils.command`` package to install your commands; +``setuptools`` automatically adds a wrapper to the distutils to search for +entry points in the active distributions on ``sys.path``. In fact, this is +how setuptools' own commands are installed: the setuptools project's setup +script defines entry points for them! + +Adding ``setup()`` Arguments +---------------------------- + +.. warning:: Adding arguments to setup is discouraged as such arguments + are only supported through imperative execution and not supported through + declarative config. + +Sometimes, your commands may need additional arguments to the ``setup()`` +call. You can enable this by defining entry points in the +``distutils.setup_keywords`` group. For example, if you wanted a ``setup()`` +argument called ``bar_baz``, you might add something like this to your +distutils extension project's setup script:: + + setup( + # ... + entry_points={ + "distutils.commands": [ + "foo = mypackage.some_module:foo", + ], + "distutils.setup_keywords": [ + "bar_baz = mypackage.some_module:validate_bar_baz", + ], + }, + ) + +The idea here is that the entry point defines a function that will be called +to validate the ``setup()`` argument, if it's supplied. The ``Distribution`` +object will have the initial value of the attribute set to ``None``, and the +validation function will only be called if the ``setup()`` call sets it to +a non-None value. Here's an example validation function:: + + def assert_bool(dist, attr, value): + """Verify that value is True, False, 0, or 1""" + if bool(value) != value: + raise DistutilsSetupError( + "%r must be a boolean value (got %r)" % (attr,value) + ) + +Your function should accept three arguments: the ``Distribution`` object, +the attribute name, and the attribute value. It should raise a +``DistutilsSetupError`` (from the ``distutils.errors`` module) if the argument +is invalid. Remember, your function will only be called with non-None values, +and the default value of arguments defined this way is always None. So, your +commands should always be prepared for the possibility that the attribute will +be ``None`` when they access it later. + +If more than one active distribution defines an entry point for the same +``setup()`` argument, *all* of them will be called. This allows multiple +distutils extensions to define a common argument, as long as they agree on +what values of that argument are valid. + +Also note that as with commands, it is not necessary to subclass or monkeypatch +the distutils ``Distribution`` class in order to add your arguments; it is +sufficient to define the entry points in your extension, as long as any setup +script using your extension lists your project in its ``setup_requires`` +argument. + + +Customizing Distribution Options +-------------------------------- + +Plugins may wish to extend or alter the options on a Distribution object to +suit the purposes of that project. For example, a tool that infers the +``Distribution.version`` from SCM-metadata may need to hook into the +option finalization. To enable this feature, Setuptools offers an entry +point "setuptools.finalize_distribution_options". That entry point must +be a callable taking one argument (the Distribution instance). + +If the callable has an ``.order`` property, that value will be used to +determine the order in which the hook is called. Lower numbers are called +first and the default is zero (0). + +Plugins may read, alter, and set properties on the distribution, but each +plugin is encouraged to load the configuration/settings for their behavior +independently. + + +Adding new EGG-INFO Files +------------------------- + +Some extensible applications or frameworks may want to allow third parties to +develop plugins with application or framework-specific metadata included in +the plugins' EGG-INFO directory, for easy access via the ``pkg_resources`` +metadata API. The easiest way to allow this is to create a distutils extension +to be used from the plugin projects' setup scripts (via ``setup_requires``) +that defines a new setup keyword, and then uses that data to write an EGG-INFO +file when the ``egg_info`` command is run. + +The ``egg_info`` command looks for extension points in an ``egg_info.writers`` +group, and calls them to write the files. Here's a simple example of a +distutils extension defining a setup argument ``foo_bar``, which is a list of +lines that will be written to ``foo_bar.txt`` in the EGG-INFO directory of any +project that uses the argument:: + + setup( + # ... + entry_points={ + "distutils.setup_keywords": [ + "foo_bar = setuptools.dist:assert_string_list", + ], + "egg_info.writers": [ + "foo_bar.txt = setuptools.command.egg_info:write_arg", + ], + }, + ) + +This simple example makes use of two utility functions defined by setuptools +for its own use: a routine to validate that a setup keyword is a sequence of +strings, and another one that looks up a setup argument and writes it to +a file. Here's what the writer utility looks like:: + + def write_arg(cmd, basename, filename): + argname = os.path.splitext(basename)[0] + value = getattr(cmd.distribution, argname, None) + if value is not None: + value = "\n".join(value) + "\n" + cmd.write_or_delete_file(argname, filename, value) + +As you can see, ``egg_info.writers`` entry points must be a function taking +three arguments: a ``egg_info`` command instance, the basename of the file to +write (e.g. ``foo_bar.txt``), and the actual full filename that should be +written to. + +In general, writer functions should honor the command object's ``dry_run`` +setting when writing files, and use the ``distutils.log`` object to do any +console output. The easiest way to conform to this requirement is to use +the ``cmd`` object's ``write_file()``, ``delete_file()``, and +``write_or_delete_file()`` methods exclusively for your file operations. See +those methods' docstrings for more details. + +Adding Support for Revision Control Systems +------------------------------------------------- + +If the files you want to include in the source distribution are tracked using +Git, Mercurial or SVN, you can use the following packages to achieve that: + +- Git and Mercurial: `setuptools_scm `_ +- SVN: `setuptools_svn `_ + +If you would like to create a plugin for ``setuptools`` to find files tracked +by another revision control system, you can do so by adding an entry point to +the ``setuptools.file_finders`` group. The entry point should be a function +accepting a single directory name, and should yield all the filenames within +that directory (and any subdirectories thereof) that are under revision +control. + +For example, if you were going to create a plugin for a revision control system +called "foobar", you would write a function something like this: + +.. code-block:: python + + def find_files_for_foobar(dirname): + # loop to yield paths that start with `dirname` + +And you would register it in a setup script using something like this:: + + entry_points={ + "setuptools.file_finders": [ + "foobar = my_foobar_module:find_files_for_foobar", + ] + } + +Then, anyone who wants to use your plugin can simply install it, and their +local setuptools installation will be able to find the necessary files. + +It is not necessary to distribute source control plugins with projects that +simply use the other source control system, or to specify the plugins in +``setup_requires``. When you create a source distribution with the ``sdist`` +command, setuptools automatically records what files were found in the +``SOURCES.txt`` file. That way, recipients of source distributions don't need +to have revision control at all. However, if someone is working on a package +by checking out with that system, they will need the same plugin(s) that the +original author is using. + +A few important points for writing revision control file finders: + +* Your finder function MUST return relative paths, created by appending to the + passed-in directory name. Absolute paths are NOT allowed, nor are relative + paths that reference a parent directory of the passed-in directory. + +* Your finder function MUST accept an empty string as the directory name, + meaning the current directory. You MUST NOT convert this to a dot; just + yield relative paths. So, yielding a subdirectory named ``some/dir`` under + the current directory should NOT be rendered as ``./some/dir`` or + ``/somewhere/some/dir``, but *always* as simply ``some/dir`` + +* Your finder function SHOULD NOT raise any errors, and SHOULD deal gracefully + with the absence of needed programs (i.e., ones belonging to the revision + control system itself. It *may*, however, use ``distutils.log.warn()`` to + inform the user of the missing program(s). \ No newline at end of file -- cgit v1.2.1 From f5c9ad1e228fb5751cb45171cd074c32890f9787 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 14 May 2020 12:45:48 -0400 Subject: docs: dedicate a file for miscel functionalities these should be properly grouped but for now I'm just leaving them here --- docs/userguide/miscellaneous.txt | 1297 -------------------------------------- 1 file changed, 1297 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/miscellaneous.txt b/docs/userguide/miscellaneous.txt index 5946662a..65e075cd 100644 --- a/docs/userguide/miscellaneous.txt +++ b/docs/userguide/miscellaneous.txt @@ -1,589 +1,3 @@ -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 two lists of package name -patterns to exclude and include. 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, filtering by inclusion -patterns, and finds Python packages (any directory). Packages are only -recognized if they include an ``__init__.py`` file. Finally, exclusion -patterns are applied to remove matching packages. - -Inclusion and 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:: - - 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 parameters, 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. - -``find_namespace_packages()`` ------------------------------ -In Python 3.3+, ``setuptools`` also provides the ``find_namespace_packages`` variant -of ``find_packages``, which has the same function signature as -``find_packages``, but works with `PEP 420`_ compliant implicit namespace -packages. Here is a minimal setup script using ``find_namespace_packages``:: - - from setuptools import setup, find_namespace_packages - setup( - name="HelloWorld", - version="0.1", - packages=find_namespace_packages(), - ) - - -Keep in mind that according to PEP 420, you may have to either re-organize your -codebase a bit or define a few exclusions, as the definition of an implicit -namespace package is quite lenient, so for a project organized like so:: - - - ├── namespace - │   └── mypackage - │   ├── __init__.py - │   └── mod1.py - ├── setup.py - └── tests - └── test_mod1.py - -A naive ``find_namespace_packages()`` would install both ``namespace.mypackage`` and a -top-level package called ``tests``! One way to avoid this problem is to use the -``include`` keyword to whitelist the packages to include, like so:: - - from setuptools import setup, find_namespace_packages - - setup( - name="namespace.mypackage", - version="0.1", - packages=find_namespace_packages(include=["namespace.*"]) - ) - -Another option is to use the "src" layout, where all package code is placed in -the ``src`` directory, like so:: - - - ├── setup.py - ├── src - │   └── namespace - │   └── mypackage - │   ├── __init__.py - │   └── mod1.py - └── tests - └── test_mod1.py - -With this layout, the package directory is specified as ``src``, as such:: - - setup(name="namespace.mypackage", - version="0.1", - package_dir={"": "src"}, - packages=find_namespace_packages(where="src")) - -.. _PEP 420: https://www.python.org/dev/peps/pep-0420/ - -Automatic Script Creation -========================= - -Packaging and installing scripts can be a bit awkward with the distutils. For -one thing, there's no easy way to have a script's filename match local -conventions on both Windows and POSIX platforms. For another, you often have -to create a separate file just for the "main" script, when your actual "main" -is a function in a module somewhere. And even in Python 2.4, using the ``-m`` -option only works for actual ``.py`` files that aren't installed in a package. - -``setuptools`` fixes all of these problems by automatically generating scripts -for you with the correct extension, and on Windows it will even create an -``.exe`` file so that users don't have to change their ``PATHEXT`` settings. -The way to use this feature is to define "entry points" in your setup script -that indicate what function the generated script should import and run. For -example, to create two console scripts called ``foo`` and ``bar``, and a GUI -script called ``baz``, you might do something like this:: - - setup( - # other arguments here... - entry_points={ - "console_scripts": [ - "foo = my_package.some_module:main_func", - "bar = other_module:some_func", - ], - "gui_scripts": [ - "baz = my_package_gui:start_func", - ] - } - ) - -When this project is installed on non-Windows platforms (using "setup.py -install", "setup.py develop", or with pip), a set of ``foo``, ``bar``, -and ``baz`` scripts will be installed that import ``main_func`` and -``some_func`` from the specified modules. The functions you specify are -called with no arguments, and their return value is passed to -``sys.exit()``, so you can return an errorlevel or message to print to -stderr. - -On Windows, a set of ``foo.exe``, ``bar.exe``, and ``baz.exe`` launchers are -created, alongside a set of ``foo.py``, ``bar.py``, and ``baz.pyw`` files. The -``.exe`` wrappers find and execute the right version of Python to run the -``.py`` or ``.pyw`` file. - -You may define as many "console script" and "gui script" entry points as you -like, and each one can optionally specify "extras" that it depends on, that -will be added to ``sys.path`` when the script is run. For more information on -"extras", see the section below on `Declaring Extras`_. For more information -on "entry points" in general, see the section below on `Dynamic Discovery of -Services and Plugins`_. - - - -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 pip 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 ``-``. - -Version specifiers for a given project are internally sorted into ascending -version order, and used to establish what ranges of versions are acceptable. -Adjacent redundant conditions are also consolidated (e.g. ``">1, >2"`` becomes -``">2"``, and ``"<2,<3"`` becomes ``"<2"``). ``"!="`` versions are excised from -the ranges they fall within. A project's version is then checked for -membership in the resulting ranges. (Note that providing conflicting conditions -for the same version (e.g. "<2,>=2" or "==2,!=2") is meaningless and may -therefore produce bizarre results.) - -Here are some example requirement specifiers:: - - 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 pip, ``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. - -2. 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). - -3. 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``.) - -Dependencies that aren't in PyPI --------------------------------- - -.. warning:: - Dependency links support has been dropped by pip starting with version - 19.0 (released 2019-01-22). - -If your project depends on packages that don't exist on PyPI, you may still be -able to depend on them, as long as they are available for download as: - -- an egg, in the standard distutils ``sdist`` format, -- a single ``.py`` file, or -- a VCS repository (Subversion, Mercurial, or Git). - -You just need to add some URLs to the ``dependency_links`` argument to -``setup()``. - -The URLs must be either: - -1. direct download URLs, -2. the URLs of web pages that contain direct download links, or -3. the repository's URL - -In general, it's better to link to web pages, because it is usually less -complex to update a web page than to release a new version of your project. -You can also use a SourceForge ``showfiles.php`` link in the case where a -package you depend on is distributed via SourceForge. - -If you depend on a package that's distributed as a single ``.py`` file, you -must include an ``"#egg=project-version"`` suffix to the URL, to give a project -name and version number. (Be sure to escape any dashes in the name or version -by replacing them with underscores.) EasyInstall will recognize this suffix -and automatically create a trivial ``setup.py`` to wrap the single ``.py`` file -as an egg. - -In the case of a VCS checkout, you should also append ``#egg=project-version`` -in order to identify for what package that checkout should be used. You can -append ``@REV`` to the URL's path (before the fragment) to specify a revision. -Additionally, you can also force the VCS being used by prepending the URL with -a certain prefix. Currently available are: - -- ``svn+URL`` for Subversion, -- ``git+URL`` for Git, and -- ``hg+URL`` for Mercurial - -A more complete example would be: - - ``vcs+proto://host/path@revision#egg=project-version`` - -Be careful with the version. It should match the one inside the project files. -If you want to disregard the version, you have to omit it both in the -``requires`` and in the URL's fragment. - -This will do a checkout (or a clone, in Git and Mercurial parlance) to a -temporary folder and run ``setup.py bdist_egg``. - -The ``dependency_links`` option takes the form of a list of URL strings. For -example, this will cause a search of the specified page for eggs or source -distributions, if the package's dependencies aren't already installed:: - - setup( - ... - dependency_links=[ - "http://peak.telecommunity.com/snapshots/" - ], - ) - - -.. _Declaring Extras: - - -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:: - - setup( - name="Project-A", - ... - extras_require={ - "PDF": ["ReportLab>=1.2", "RXP"], - "reST": ["docutils>=0.3"], - } - ) - -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 "pip install" -command line.) - -Extras can be used by a project's `entry points`_ to specify dynamic -dependencies. For example, if Project A includes a "rst2pdf" script, it might -declare it like this, so that the "PDF" requirements are only resolved if the -"rst2pdf" script is run:: - - setup( - name="Project-A", - ... - entry_points={ - "console_scripts": [ - "rst2pdf = project_a.tools.pdfgen [PDF]", - "rst2html = project_a.tools.htmlgen", - # more script entry points ... - ], - } - ) - -Projects can also use another project's extras when specifying dependencies. -For example, if project B needs "project A" with PDF support installed, it -might declare the dependency like this:: - - 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. - -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 could change its -setup to this:: - - 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. - -.. _Platform Specific Dependencies: - - -Declaring platform specific dependencies ----------------------------------------- - -Sometimes a project might require a dependency to run on a specific platform. -This could to a package that back ports a module so that it can be used in -older python versions. Or it could be a package that is required to run on a -specific operating system. This will allow a project to work on multiple -different platforms without installing dependencies that are not required for -a platform that is installing the project. - -For example, here is a project that uses the ``enum`` module and ``pywin32``:: - - setup( - name="Project", - ... - install_requires=[ - "enum34;python_version<'3.4'", - "pywin32 >= 1.0;platform_system=='Windows'" - ] - ) - -Since the ``enum`` module was added in Python 3.4, it should only be installed -if the python version is earlier. Since ``pywin32`` will only be used on -windows, it should only be installed when the operating system is Windows. -Specifying version requirements for the dependencies is supported as normal. - -The environmental markers that may be used for testing platform types are -detailed in `PEP 508`_. - -.. _PEP 508: https://www.python.org/dev/peps/pep-0508/ - -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 offers three ways to specify data files to be included in your -packages. First, you can simply use the ``include_package_data`` keyword, -e.g.:: - - from setuptools import setup, find_packages - setup( - ... - include_package_data=True - ) - -This tells setuptools to install any data files it finds in your packages. -The data files must be specified via the distutils' ``MANIFEST.in`` file. -(They can also be tracked by a revision control system, using an appropriate -plugin. See the section below on `Adding Support for Revision Control -Systems`_ for information on how to write such plugins.) - -If you want finer-grained control over what files are included (for example, -if you have documentation files in your package directories and want to exclude -them from installation), then you can also use the ``package_data`` keyword, -e.g.:: - - 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:: - - setup.py - src/ - mypkg/ - __init__.py - mypkg.txt - data/ - somefile.dat - otherdata.dat - -The setuptools setup file might look like this:: - - 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. - -If datafiles are contained in a subdirectory of a package that isn't a package -itself (no ``__init__.py``), then the subdirectory names (or ``*``) are required -in the ``package_data`` argument (as shown above with ``"data/*.dat"``). - -When building an ``sdist``, the datafiles are also drawn from the -``package_name.egg-info/SOURCES.txt`` file, so make sure that this is removed if -the ``setup.py`` ``package_data`` list is updated before calling ``setup.py``. - -(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 `some documentation for the feature`__ available on the -python.org website. If using the setuptools-specific ``include_package_data`` -argument, files specified by ``package_data`` will *not* be automatically -added to the manifest unless they are listed in the MANIFEST.in file.) - -__ https://docs.python.org/3/distutils/setupscript.html#installing-package-data - -Sometimes, the ``include_package_data`` or ``package_data`` options alone -aren't sufficient to precisely define what files you want included. For -example, you may want to include package README files in your revision control -system and source distributions, but exclude them from being installed. So, -setuptools offers an ``exclude_package_data`` option as well, that allows you -to do things like this:: - - 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 - - include_package_data=True, # include everything in source control - - # ...but exclude README.txt from all packages - exclude_package_data={"": ["README.txt"]}, - ) - -The ``exclude_package_data`` option is a dictionary mapping package names to -lists of wildcard patterns, just like the ``package_data`` option. And, just -as with that option, a key of ``""`` will apply the given pattern(s) to all -packages. However, any files that match these patterns will be *excluded* -from installation, even if they were listed in ``package_data`` or were -included as a result of using ``include_package_data``. - -In summary, the three options allow you to: - -``include_package_data`` - Accept all data files and directories matched by ``MANIFEST.in``. - -``package_data`` - Specify additional patterns to match files that may or may - not be matched by ``MANIFEST.in`` or found in source control. - -``exclude_package_data`` - Specify patterns for data files and directories that should *not* be - included when a package is installed, even if they would otherwise have - been included due to the use of the preceding options. - -NOTE: Due to the way the distutils build process works, a data file that you -include in your project and then stop including may be "orphaned" in your -project's build directories, requiring you to run ``setup.py clean --all`` to -fully remove them. This may also be important for your users and contributors -if they track intermediate revisions of your project using Subversion; be sure -to let them know when you make changes that remove files from inclusion so they -can run ``setup.py clean --all``. - -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 :ref:`ResourceManager 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 `Importlib Resources`_ for -a quick example of converting code that uses ``__file__`` to use -``pkg_resources`` instead. - -.. _Importlib Resources: https://docs.python.org/3/library/importlib.html#module-importlib.resources - - -Non-Package Data Files ----------------------- - -Historically, ``setuptools`` by way of ``easy_install`` would encapsulate data -files from the distribution into the egg (see `the old docs -`_). As eggs are deprecated and pip-based installs -fall back to the platform-specific location for installing data files, there is -no supported facility to reliably retrieve these resources. - -Instead, the PyPA recommends that any data files you wish to be accessible at -run time be included in the package. - - Automatic Resource Extraction ----------------------------- @@ -621,76 +35,6 @@ files, or Python plus C, you really don't need this. You've got to be using either C or an external program that needs "real" files in your project before there's any possibility of ``eager_resources`` being relevant to your project. - -Extensible Applications and Frameworks -====================================== - - -.. _Entry Points: - -Dynamic Discovery of Services and Plugins ------------------------------------------ - -``setuptools`` supports creating libraries that "plug in" to extensible -applications and frameworks, by letting you register "entry points" in your -project that can be imported by the application or framework. - -For example, suppose that a blogging tool wants to support plugins -that provide translation for various file types to the blog's output format. -The framework might define an "entry point group" called ``blogtool.parsers``, -and then allow plugins to register entry points for the file extensions they -support. - -This would allow people to create distributions that contain one or more -parsers for different file types, and then the blogging tool would be able to -find the parsers at runtime by looking up an entry point for the file -extension (or mime type, or however it wants to). - -Note that if the blogging tool includes parsers for certain file formats, it -can register these as entry points in its own setup script, which means it -doesn't have to special-case its built-in formats. They can just be treated -the same as any other plugin's entry points would be. - -If you're creating a project that plugs in to an existing application or -framework, you'll need to know what entry points or entry point groups are -defined by that application or framework. Then, you can register entry points -in your setup script. Here are a few examples of ways you might register an -``.rst`` file parser entry point in the ``blogtool.parsers`` entry point group, -for our hypothetical blogging tool:: - - setup( - # ... - entry_points={"blogtool.parsers": ".rst = some_module:SomeClass"} - ) - - setup( - # ... - entry_points={"blogtool.parsers": [".rst = some_module:a_func"]} - ) - - setup( - # ... - entry_points=""" - [blogtool.parsers] - .rst = some.nested.module:SomeClass.some_classmethod [reST] - """, - extras_require=dict(reST="Docutils>=0.3.5") - ) - -The ``entry_points`` argument to ``setup()`` accepts either a string with -``.ini``-style sections, or a dictionary mapping entry point group names to -either strings or lists of strings containing entry point specifiers. An -entry point specifier consists of a name and value, separated by an ``=`` -sign. The value consists of a dotted module name, optionally followed by a -``:`` and a dotted identifier naming an object within the module. It can -also include a bracketed list of "extras" that are required for the entry -point to be used. When the invoking application or framework requests loading -of an entry point, any requirements implied by the associated extras will be -passed to ``pkg_resources.require()``, so that an appropriate error message -can be displayed if the needed package(s) are missing. (Of course, the -invoking app or framework can ignore such errors if it wants to make an entry -point optional if a requirement isn't installed.) - Defining Additional Metadata ---------------------------- @@ -705,107 +49,6 @@ for many of the ``setup()`` arguments it adds. See the section below on `Creating distutils Extensions`_ for more details, especially the subsection on `Adding new EGG-INFO Files`_. - -"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``, 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. - -If you have enabled the ``use_2to3`` flag, then of course the ``.egg-link`` -will not link directly to your source code when run under Python 3, since -that source code would be made for Python 2 and not work under Python 3. -Instead the ``setup.py develop`` will build Python 3 code under the ``build`` -directory, and link there. This means that after doing code changes you will -have to run ``setup.py build`` before these changes are picked up by your -Python 3 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. - -Note that you can also apply setuptools commands to non-setuptools projects, -using commands like this:: - - python -c "import setuptools; with open('setup.py') as f: exec(compile(f.read(), 'setup.py', 'exec'))" develop - -That is, you can simply list the normal setup commands and options following -the quoted part. - - -Distributing a ``setuptools``-based project -=========================================== - -Detailed instructions to distribute a setuptools project can be found at -`Packaging project tutorials`_. - -.. _Packaging project tutorials: https://packaging.python.org/tutorials/packaging-projects/#generating-distribution-archives - -Before you begin, make sure you have the latest versions of setuptools and wheel:: - - pip install --upgrade setuptools wheel - -To build a setuptools project, run this command from the same directory where -setup.py is located:: - - setup.py sdist bdist_wheel - -This will generate distribution archives in the `dist` directory. - -Before you upload the generated archives make sure you're registered on -https://test.pypi.org/account/register/. You will also need to verify your email -to be able to upload any packages. -You should install twine to be able to upload packages:: - - pip install --upgrade twine - -Now, to upload these archives, run:: - - twine upload --repository-url https://test.pypi.org/legacy/ dist/* - -To install your newly uploaded package ``example_pkg``, you can use pip:: - - pip install --index-url https://test.pypi.org/simple/ example_pkg - -If you have issues at any point, please refer to `Packaging project tutorials`_ -for clarification. - - Setting the ``zip_safe`` flag ----------------------------- @@ -849,543 +92,3 @@ 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`` to try to guess whether your project can work as a zipfile. - -.. _Namespace Packages: - -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 then 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. The argument should list the namespace packages that the egg -participates in. For example, the ZopeInterface project might do this:: - - 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. When these projects are -installed and used, Python will see them both as part of a "virtual" ``zope`` -package, even though they will be installed in different locations. - -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 -*must* contain the line:: - - __import__("pkg_resources").declare_namespace(__name__) - -This code ensures that the namespace package machinery is operating and that -the current package is registered as a namespace package. - -You must NOT include any other code and data in a namespace package's -``__init__.py``. Even though it may appear to work during development, or when -projects are installed as ``.egg`` files, it will not work when the projects -are installed using "system" packaging tools -- in such cases the -``__init__.py`` files will not be installed, let alone executed. - -You must include the ``declare_namespace()`` line in the ``__init__.py`` of -*every* project that has contents for the namespace package in question, in -order to ensure that the namespace will be declared regardless of which -project's copy of ``__init__.py`` is loaded first. If the first loaded -``__init__.py`` doesn't declare it, it will never *be* declared, because no -other copies will ever be loaded! - -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: - -* A manually-specified pre-release tag, such as "build" or "dev", or a - manually-specified post-release tag, such as a build or revision number - (``--tag-build=STRING, -bSTRING``) - -* An 8-character representation of the build date (``--tag-date, -d``), as - a postrelease tag - -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, before you release your project, be sure to see the section above on -`Specifying Your Project's Version`_ for more information about how pre- and -post-release tags affect how version numbers are interpreted. This is -important in order to make sure that dependency processing tools will know -which versions of your project are newer than others.) - -Finally, 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:: - - 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 script or 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 with pluggable endpoints for looking up files to include. If you are -using a revision control system, and your source distributions only need to -include files that you're tracking in revision control, use a corresponding -plugin instead of writing a ``MANIFEST.in`` file. See the section below on -`Adding Support for Revision Control Systems`_ for information on plugins. - -If you need to include automatically generated files, or files that are kept in -an unsupported revision control system, you'll need to create a ``MANIFEST.in`` -file to specify any files that the default file location algorithm doesn't -catch. See the distutils documentation for more information on the format of -the ``MANIFEST.in`` file. - -But, be sure to ignore any part of the distutils documentation that deals with -``MANIFEST`` or how it's generated from ``MANIFEST.in``; setuptools shields you -from these issues and doesn't work the same way in any case. Unlike the -distutils, setuptools regenerates the source distribution manifest file -every time you build a source distribution, and it builds it inside the -project's ``.egg-info`` directory, out of the way of your main project -directory. You therefore need not worry about whether it is up-to-date or not. - -Indeed, because setuptools' approach to determining the contents of a source -distribution is so much simpler, its ``sdist`` command omits nearly all of -the options that the distutils' more complex ``sdist`` process requires. For -all practical purposes, you'll probably use only the ``--formats`` option, if -you use any option at all. - - -Making "Official" (Non-Snapshot) Releases -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When you make an official release, creating source or binary distributions, -you will need to override the tag settings from ``setup.cfg``, so that you -don't end up registering versions like ``foobar-0.7a1.dev-r34832``. This is -easy to do if you are developing on the trunk and using tags or branches for -your releases - just make the change to ``setup.cfg`` after branching or -tagging the release, so the trunk will still produce development snapshots. - -Alternately, if you are not branching for releases, you can override the -default version options on the command line, using something like:: - - setup.py egg_info -Db "" sdist bdist_egg - -The first part of this command (``egg_info -Db ""``) will override the -configured tag information, before creating source and binary eggs. Thus, these -commands will use the plain version from your ``setup.py``, without adding the -build designation string. - -Of course, if you will be doing this a lot, you may wish to create a personal -alias for this operation, e.g.:: - - setup.py alias -u release egg_info -Db "" - -You can then use it like this:: - - setup.py release sdist bdist_egg - -Or of course you can create more elaborate aliases that do all of the above. -See the sections below on the `egg_info`_ and `alias`_ commands for more ideas. - -Distributing Extensions compiled with Cython --------------------------------------------- - -``setuptools`` will detect at build time whether Cython is installed or not. -If Cython is not found ``setuptools`` will ignore pyx files. - -To ensure Cython is available, include Cython in the build-requires section -of your pyproject.toml:: - - [build-system] - requires=[..., "cython"] - -Built with pip 10 or later, that declaration is sufficient to include Cython -in the build. For broader compatibility, declare the dependency in your -setup-requires of setup.cfg:: - - [options] - setup_requires = - ... - cython - -As long as Cython is present in the build environment, ``setuptools`` includes -transparent support for building Cython extensions, as -long as extensions are defined using ``setuptools.Extension``. - -If you follow these rules, you can safely list ``.pyx`` files as the source -of your ``Extension`` objects in the setup script. If it is, then ``setuptools`` -will use it. - -Of course, for this to work, your source distributions must include the C -code generated by Cython, 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 a revision -control system will be able to build it even if they don't have Cython -installed, and that your source releases will be similarly usable with or -without Cython. - --------------------------------- -Extending and Reusing Setuptools --------------------------------- - -Creating ``distutils`` Extensions -================================= - -It can be hard to add new commands or setup arguments to the distutils. But -the ``setuptools`` package makes it a bit easier, by allowing you to distribute -a distutils extension as a separate project, and then have projects that need -the extension just refer to it in their ``setup_requires`` argument. - -With ``setuptools``, your distutils extension projects can hook in new -commands and ``setup()`` arguments just by defining "entry points". These -are mappings from command or argument names to a specification of where to -import a handler from. (See the section on `Dynamic Discovery of Services and -Plugins`_ above for some more background on entry points.) - - -Adding Commands ---------------- - -You can add new ``setup`` commands by defining entry points in the -``distutils.commands`` group. For example, if you wanted to add a ``foo`` -command, you might add something like this to your distutils extension -project's setup script:: - - setup( - # ... - entry_points={ - "distutils.commands": [ - "foo = mypackage.some_module:foo", - ], - }, - ) - -(Assuming, of course, that the ``foo`` class in ``mypackage.some_module`` is -a ``setuptools.Command`` subclass.) - -Once a project containing such entry points has been activated on ``sys.path``, -(e.g. by running "install" or "develop" with a site-packages installation -directory) the command(s) will be available to any ``setuptools``-based setup -scripts. It is not necessary to use the ``--command-packages`` option or -to monkeypatch the ``distutils.command`` package to install your commands; -``setuptools`` automatically adds a wrapper to the distutils to search for -entry points in the active distributions on ``sys.path``. In fact, this is -how setuptools' own commands are installed: the setuptools project's setup -script defines entry points for them! - -Adding ``setup()`` Arguments ----------------------------- - -.. warning:: Adding arguments to setup is discouraged as such arguments - are only supported through imperative execution and not supported through - declarative config. - -Sometimes, your commands may need additional arguments to the ``setup()`` -call. You can enable this by defining entry points in the -``distutils.setup_keywords`` group. For example, if you wanted a ``setup()`` -argument called ``bar_baz``, you might add something like this to your -distutils extension project's setup script:: - - setup( - # ... - entry_points={ - "distutils.commands": [ - "foo = mypackage.some_module:foo", - ], - "distutils.setup_keywords": [ - "bar_baz = mypackage.some_module:validate_bar_baz", - ], - }, - ) - -The idea here is that the entry point defines a function that will be called -to validate the ``setup()`` argument, if it's supplied. The ``Distribution`` -object will have the initial value of the attribute set to ``None``, and the -validation function will only be called if the ``setup()`` call sets it to -a non-None value. Here's an example validation function:: - - def assert_bool(dist, attr, value): - """Verify that value is True, False, 0, or 1""" - if bool(value) != value: - raise DistutilsSetupError( - "%r must be a boolean value (got %r)" % (attr,value) - ) - -Your function should accept three arguments: the ``Distribution`` object, -the attribute name, and the attribute value. It should raise a -``DistutilsSetupError`` (from the ``distutils.errors`` module) if the argument -is invalid. Remember, your function will only be called with non-None values, -and the default value of arguments defined this way is always None. So, your -commands should always be prepared for the possibility that the attribute will -be ``None`` when they access it later. - -If more than one active distribution defines an entry point for the same -``setup()`` argument, *all* of them will be called. This allows multiple -distutils extensions to define a common argument, as long as they agree on -what values of that argument are valid. - -Also note that as with commands, it is not necessary to subclass or monkeypatch -the distutils ``Distribution`` class in order to add your arguments; it is -sufficient to define the entry points in your extension, as long as any setup -script using your extension lists your project in its ``setup_requires`` -argument. - - -Customizing Distribution Options --------------------------------- - -Plugins may wish to extend or alter the options on a Distribution object to -suit the purposes of that project. For example, a tool that infers the -``Distribution.version`` from SCM-metadata may need to hook into the -option finalization. To enable this feature, Setuptools offers an entry -point "setuptools.finalize_distribution_options". That entry point must -be a callable taking one argument (the Distribution instance). - -If the callable has an ``.order`` property, that value will be used to -determine the order in which the hook is called. Lower numbers are called -first and the default is zero (0). - -Plugins may read, alter, and set properties on the distribution, but each -plugin is encouraged to load the configuration/settings for their behavior -independently. - - -Adding new EGG-INFO Files -------------------------- - -Some extensible applications or frameworks may want to allow third parties to -develop plugins with application or framework-specific metadata included in -the plugins' EGG-INFO directory, for easy access via the ``pkg_resources`` -metadata API. The easiest way to allow this is to create a distutils extension -to be used from the plugin projects' setup scripts (via ``setup_requires``) -that defines a new setup keyword, and then uses that data to write an EGG-INFO -file when the ``egg_info`` command is run. - -The ``egg_info`` command looks for extension points in an ``egg_info.writers`` -group, and calls them to write the files. Here's a simple example of a -distutils extension defining a setup argument ``foo_bar``, which is a list of -lines that will be written to ``foo_bar.txt`` in the EGG-INFO directory of any -project that uses the argument:: - - setup( - # ... - entry_points={ - "distutils.setup_keywords": [ - "foo_bar = setuptools.dist:assert_string_list", - ], - "egg_info.writers": [ - "foo_bar.txt = setuptools.command.egg_info:write_arg", - ], - }, - ) - -This simple example makes use of two utility functions defined by setuptools -for its own use: a routine to validate that a setup keyword is a sequence of -strings, and another one that looks up a setup argument and writes it to -a file. Here's what the writer utility looks like:: - - def write_arg(cmd, basename, filename): - argname = os.path.splitext(basename)[0] - value = getattr(cmd.distribution, argname, None) - if value is not None: - value = "\n".join(value) + "\n" - cmd.write_or_delete_file(argname, filename, value) - -As you can see, ``egg_info.writers`` entry points must be a function taking -three arguments: a ``egg_info`` command instance, the basename of the file to -write (e.g. ``foo_bar.txt``), and the actual full filename that should be -written to. - -In general, writer functions should honor the command object's ``dry_run`` -setting when writing files, and use the ``distutils.log`` object to do any -console output. The easiest way to conform to this requirement is to use -the ``cmd`` object's ``write_file()``, ``delete_file()``, and -``write_or_delete_file()`` methods exclusively for your file operations. See -those methods' docstrings for more details. - -Adding Support for Revision Control Systems -------------------------------------------------- - -If the files you want to include in the source distribution are tracked using -Git, Mercurial or SVN, you can use the following packages to achieve that: - -- Git and Mercurial: `setuptools_scm `_ -- SVN: `setuptools_svn `_ - -If you would like to create a plugin for ``setuptools`` to find files tracked -by another revision control system, you can do so by adding an entry point to -the ``setuptools.file_finders`` group. The entry point should be a function -accepting a single directory name, and should yield all the filenames within -that directory (and any subdirectories thereof) that are under revision -control. - -For example, if you were going to create a plugin for a revision control system -called "foobar", you would write a function something like this: - -.. code-block:: python - - def find_files_for_foobar(dirname): - # loop to yield paths that start with `dirname` - -And you would register it in a setup script using something like this:: - - entry_points={ - "setuptools.file_finders": [ - "foobar = my_foobar_module:find_files_for_foobar", - ] - } - -Then, anyone who wants to use your plugin can simply install it, and their -local setuptools installation will be able to find the necessary files. - -It is not necessary to distribute source control plugins with projects that -simply use the other source control system, or to specify the plugins in -``setup_requires``. When you create a source distribution with the ``sdist`` -command, setuptools automatically records what files were found in the -``SOURCES.txt`` file. That way, recipients of source distributions don't need -to have revision control at all. However, if someone is working on a package -by checking out with that system, they will need the same plugin(s) that the -original author is using. - -A few important points for writing revision control file finders: - -* Your finder function MUST return relative paths, created by appending to the - passed-in directory name. Absolute paths are NOT allowed, nor are relative - paths that reference a parent directory of the passed-in directory. - -* Your finder function MUST accept an empty string as the directory name, - meaning the current directory. You MUST NOT convert this to a dot; just - yield relative paths. So, yielding a subdirectory named ``some/dir`` under - the current directory should NOT be rendered as ``./some/dir`` or - ``/somewhere/some/dir``, but *always* as simply ``some/dir`` - -* Your finder function SHOULD NOT raise any errors, and SHOULD deal gracefully - with the absence of needed programs (i.e., ones belonging to the revision - control system itself. It *may*, however, use ``distutils.log.warn()`` to - inform the user of the missing program(s). - -Specifying Your Project's Version ---------------------------------- - -Setuptools can work well with most versioning schemes; there are, however, a -few special things to watch out for, in order to ensure that setuptools and -other tools can always tell what version of your package is newer than another -version. Knowing these things will also help you correctly specify what -versions of other projects your project depends on. - -A version consists of an alternating series of release numbers and pre-release -or post-release tags. A release number is a series of digits punctuated by -dots, such as ``2.4`` or ``0.5``. Each series of digits is treated -numerically, so releases ``2.1`` and ``2.1.0`` are different ways to spell the -same release number, denoting the first subrelease of release 2. But ``2.10`` -is the *tenth* subrelease of release 2, and so is a different and newer release -from ``2.1`` or ``2.1.0``. Leading zeros within a series of digits are also -ignored, so ``2.01`` is the same as ``2.1``, and different from ``2.0.1``. - -Following a release number, you can have either a pre-release or post-release -tag. Pre-release tags make a version be considered *older* than the version -they are appended to. So, revision ``2.4`` is *newer* than revision ``2.4c1``, -which in turn is newer than ``2.4b1`` or ``2.4a1``. Postrelease tags make -a version be considered *newer* than the version they are appended to. So, -revisions like ``2.4-1`` and ``2.4pl3`` are newer than ``2.4``, but are *older* -than ``2.4.1`` (which has a higher release number). - -A pre-release tag is a series of letters that are alphabetically before -"final". Some examples of prerelease tags would include ``alpha``, ``beta``, -``a``, ``c``, ``dev``, and so on. You do not have to place a dot or dash -before the prerelease tag if it's immediately after a number, but it's okay to -do so if you prefer. Thus, ``2.4c1`` and ``2.4.c1`` and ``2.4-c1`` all -represent release candidate 1 of version ``2.4``, and are treated as identical -by setuptools. - -In addition, there are three special prerelease tags that are treated as if -they were the letter ``c``: ``pre``, ``preview``, and ``rc``. So, version -``2.4rc1``, ``2.4pre1`` and ``2.4preview1`` are all the exact same version as -``2.4c1``, and are treated as identical by setuptools. - -A post-release tag is either a series of letters that are alphabetically -greater than or equal to "final", or a dash (``-``). Post-release tags are -generally used to separate patch numbers, port numbers, build numbers, revision -numbers, or date stamps from the release number. For example, the version -``2.4-r1263`` might denote Subversion revision 1263 of a post-release patch of -version ``2.4``. Or you might use ``2.4-20051127`` to denote a date-stamped -post-release. - -Notice that after each pre or post-release tag, you are free to place another -release number, followed again by more pre- or post-release tags. For example, -``0.6a9.dev-r41475`` could denote Subversion revision 41475 of the in- -development version of the ninth alpha of release 0.6. Notice that ``dev`` is -a pre-release tag, so this version is a *lower* version number than ``0.6a9``, -which would be the actual ninth alpha of release 0.6. But the ``-r41475`` is -a post-release tag, so this version is *newer* than ``0.6a9.dev``. - -For the most part, setuptools' interpretation of version numbers is intuitive, -but here are a few tips that will keep you out of trouble in the corner cases: - -* Don't stick adjoining pre-release tags together without a dot or number - between them. Version ``1.9adev`` is the ``adev`` prerelease of ``1.9``, - *not* a development pre-release of ``1.9a``. Use ``.dev`` instead, as in - ``1.9a.dev``, or separate the prerelease tags with a number, as in - ``1.9a0dev``. ``1.9a.dev``, ``1.9a0dev``, and even ``1.9.a.dev`` are - identical versions from setuptools' point of view, so you can use whatever - scheme you prefer. - -* If you want to be certain that your chosen numbering scheme works the way - you think it will, you can use the ``pkg_resources.parse_version()`` function - to compare different version numbers:: - - >>> from pkg_resources import parse_version - >>> parse_version("1.9.a.dev") == parse_version("1.9a0dev") - True - >>> parse_version("2.1-rc2") < parse_version("2.1") - True - >>> parse_version("0.6a9dev-r41475") < parse_version("0.6a9") - True - -Once you've decided on a version numbering scheme for your project, you can -have setuptools automatically tag your in-development releases with various -pre- or post-release tags. See the following sections for more details: - -* `Tagging and "Daily Build" or "Snapshot" Releases`_ -* The `egg_info`_ command \ No newline at end of file -- cgit v1.2.1 From 04dbe6f9434bd73ba839f2fd386c63133a8381d1 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Mon, 18 May 2020 10:55:58 -0400 Subject: docs: WIP update quickstart guide to make it pep517-compatible and declarative --- docs/userguide/quickstart.txt | 109 ++++++++++++++++++++---------------------- 1 file changed, 53 insertions(+), 56 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.txt b/docs/userguide/quickstart.txt index e75d74e1..fd203b16 100644 --- a/docs/userguide/quickstart.txt +++ b/docs/userguide/quickstart.txt @@ -13,78 +13,75 @@ To install the latest version of setuptools, use:: Refer to `Installing Packages`_ guide for more information. +Python packaging at a glance +============================ + +The landscape of Python packaging is shifting and ``Setuptools`` has evolved to +only provide backend support, no longer being the de-facto packaging tool in +the market. All python package must provide a ``pyproject.toml`` and specify +the backend (build system) it wants to use. The distribution can then +be generated with whatever tools that provides a ``build sdist``-alike +functionality. While this may appear cumbersome, given the added pieces, +it in fact tremendously enhances the portability of your package. The +change is driven under `PEP 517 `` + Basic Use ========= -For basic use of setuptools, just import things from setuptools. Here's a -minimal setup script using setuptools:: +For basic use of setuptools, you will need a ``pyproject.toml`` with the +exact following info, which declares you want to use ``setuptools`` to +package your project: - from setuptools import setup, find_packages - setup( - name="HelloWorld", - version="0.1", - packages=find_packages(), - ) +.. code-block:: toml + + [build-system] + requires = ["setuptools", "wheel"] + build-backend = "setuptools.build_meta" + +Then, you will need a ``setup.cfg`` to specify your package information, +such as metadata, contents, dependencies, etc. Here we demonstrate the minimum + +.. code-block:: ini + + [metadata] + name = "mypackage" + version = 0.0.1 -As you can see, it doesn't take much to use setuptools in a project. -Run that script in your project folder, alongside the Python packages -you have developed. + [options] + packages = "mypackage" + install_requires = + requests + importlib; python_version == "2.6" -Invoke that script to produce distributions 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. For example, to produce a source distribution, simply invoke:: +This is what your project would look like:: - setup.py sdist + ~/mypackage/ + pyproject.toml + setup.cfg + mypackage/__init__.py + +As you can see, it doesn't take much to use setuptools in a project. Invoke +the installer at the root of your package:: + + pep517 build + +You now have your distribution ready, which you can upload to PyPI. 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:: - - 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 to display on PyPI - author="Me", - author_email="me@example.com", - description="This is an Example Package", - keywords="hello world example examples", - url="http://example.com/HelloWorld/", # project home page, if any - project_urls={ - "Bug Tracker": "https://bugs.example.com/HelloWorld/", - "Documentation": "https://docs.example.com/HelloWorld/", - "Source Code": "https://code.example.com/HelloWorld/", - }, - classifiers=[ - "License :: OSI Approved :: Python Software Foundation License" - ] - - # could also include long_description, download_url, etc. - ) +dependencies, and perhaps some data files and scripts. In the next few section, +we will walk through those additional but essential information you need +to specify to properly package your project. Automatic package discovery =========================== For simple projects, it's usually easy enough to manually add packages to -the ``packages`` argument of ``setup()``. However, for very large projects -, it can be a big burden to keep the package list updated. setuptools therefore -provides tools to ease the burden. +the ``packages`` keyword in ``setup.cfg``. However, for very large projects +, it can be a big burden to keep the package list updated. ``setuptools`` +therefore provides tools to ease the burden. ``find_packages()`` takes a source directory and two lists of package name patterns to exclude and include. It then walks the target directory, filtering -- cgit v1.2.1 From cdf8524ec7b419a49f7c2c504798b29b79c3bba8 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Wed, 20 May 2020 15:37:30 -0400 Subject: docs: made quickstart pkg section declarative WIP --- docs/userguide/quickstart.txt | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.txt b/docs/userguide/quickstart.txt index fd203b16..d0fe4a28 100644 --- a/docs/userguide/quickstart.txt +++ b/docs/userguide/quickstart.txt @@ -81,21 +81,26 @@ Automatic package discovery For simple projects, it's usually easy enough to manually add packages to the ``packages`` keyword in ``setup.cfg``. However, for very large projects , it can be a big burden to keep the package list updated. ``setuptools`` -therefore provides tools to ease the burden. +therefore provides two convenient tools to ease the burden: ``find: `` and +``find_namespace: ``. To use it in your project: -``find_packages()`` takes a source directory and two lists of package name -patterns to exclude and include. It then walks the target directory, filtering -by inclusion patterns, and return a list of Python packages (any directory). -Finally, exclusion patterns are applied to remove matching packages. +.. code-block:: ini -For example:: - #... - from setuptools import find_packages() + [options] + packages = find: - setup( - #..., - packages = find_packages() - ) + [options.packages.find] #optional + where="." + include=['pkg1', 'pkg2'] + exclude=['pkg3', 'pkg4']] + + +When you pass the above information, alongside other necessary ones, +``setuptools`` walks through the directory specified in ``where`` (default to +current directory) and filters the packages +it can find following the ``include`` (default to none), then remove +those that match the ``exclude`` and return a list of Python packages. Note +that each entry in the ``[options.packages.find]`` is optional. For more details and advanced use, go to :ref:`package_discovery` -- cgit v1.2.1 From 780b91b3834e49eeb07d35afd1f419fee777f904 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Mon, 25 May 2020 15:37:30 -0400 Subject: docs: changed some mistaken explanation in quickst --- docs/userguide/quickstart.txt | 97 ++++++++++++++++++++----------------------- 1 file changed, 44 insertions(+), 53 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.txt b/docs/userguide/quickstart.txt index d0fe4a28..3798c402 100644 --- a/docs/userguide/quickstart.txt +++ b/docs/userguide/quickstart.txt @@ -88,19 +88,22 @@ therefore provides two convenient tools to ease the burden: ``find: `` and [options] packages = find: + package_dir= [options.packages.find] #optional - where="." - include=['pkg1', 'pkg2'] - exclude=['pkg3', 'pkg4']] + where= + include=pkg1, pkg2 + exclude=pk3, pk4 When you pass the above information, alongside other necessary ones, ``setuptools`` walks through the directory specified in ``where`` (default to -current directory) and filters the packages +current directory when left empty) and filters the packages it can find following the ``include`` (default to none), then remove those that match the ``exclude`` and return a list of Python packages. Note -that each entry in the ``[options.packages.find]`` is optional. +that each entry in the ``[options.packages.find]`` is optional. And when +``where`` keyword is used, ``package_dir`` also need to be specified (so that +the packages discovered by ``find:`` can actually be loaded) For more details and advanced use, go to :ref:`package_discovery` @@ -110,40 +113,45 @@ Entry points and automatic script creation Setuptools support automatic creation of scripts upon installation, that runs code within your package if you specify them with the ``entry_point`` keyword. This is what allows you to run commands like ``pip install`` instead of having -to type ``python -m pip install``. To accomplish this, consider the following -example:: - - setup( - #.... - entry_points={ - "console_scripts": [ - "foo = my_package.some_module:main_func", - ], - } - ) - -When this project is installed, a ``foo`` script will be installed and will -invoke the ``main_func`` when called by the user. For detailed usage, including -managing the additional or optional dependencies, go to :ref:`entry_point`. +to type ``python -m pip install``. To accomplish this, add the entry_points +keyword in your ``setup.cfg``: + +.. code-block:: ini + + [options] + entry_points = + [console_script] + main = mypkg:some_func + +When this project is installed, a ``main`` script will be installed and will +invoke the ``some_func`` in the ``__init__.py`` file when called by the user. +For detailed usage, including managing the additional or optional dependencies, +go to :ref:`entry_point`. Dependency management ===================== ``setuptools`` supports automatically installing dependencies when a package is installed. 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:: - - setup( - #... - install_requires = "docutils >= 0.3" - ) +``install_requires`` argument to ``setup.cfg``. It takes a string or list of +strings containing requirement specifiers (A version specifier is one of the +operators <, >, <=, >=, == or !=, followed by a version identifier): -When your project is installed, either by using pip, ``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. +.. code-block:: ini -For more advanced use, see :ref:`dependency_management` + [options] + install_requires = + docutils >= 0.3 + requests <= 0.4 + +When your project is installed, all of the dependencies not already installed +will be located (via PyPI), downloaded, built (if necessary), and installed. +This, of course, is a simplified scenarios. ``setuptools`` also provide +additional keywords such as ``setup_requires`` that allows you to install +dependencies before running the script, and ``extras_requires`` that take +care of those needed by automatically generated scripts. It also provides +mechanisms to handle dependencies that are not in PyPI. For more advanced use, +see :ref:`dependency_management` Including Data Files ==================== @@ -151,35 +159,18 @@ Including Data Files The distutils have traditionally allowed installation of "data files", which are placed in a platform-specific location. Setuptools offers three ways to specify data files to be included in your packages. For the simpliest use, you -can simply use the ``include_package_data`` keyword e.g.:: +can simply use the ``include_package_data`` keyword: + +.. code-block:: ini - setup( - ... - include_package_data=True - ) + [options] + include_package_data = True This tells setuptools to install any data files it finds in your packages. The data files must be specified via the distutils' ``MANIFEST.in`` file. For more details, see :ref:`datafiles` -Development mode -================ - -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. - -To do this, use the ``setup.py develop`` command. It works very similarly to -``setup.py install``, 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. - -for more information, go to :ref:`development_mode` Distributing a ``setuptools``-based project =========================================== -- cgit v1.2.1 From 8dbae6eea738b17e1a22ea2949993f0bf238a57f Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Mon, 25 May 2020 15:50:00 -0400 Subject: docs: update quickstart It is now declarative and covers the following aspects of packaging: - installation - basic use - package discovery - entry points - dependencies - data files Each section comprises a brief demonstration of the functionality and provide a link to more advanced explanation --- docs/userguide/quickstart.txt | 59 +++++++++---------------------------------- 1 file changed, 12 insertions(+), 47 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.txt b/docs/userguide/quickstart.txt index 3798c402..95abec0f 100644 --- a/docs/userguide/quickstart.txt +++ b/docs/userguide/quickstart.txt @@ -24,7 +24,8 @@ be generated with whatever tools that provides a ``build sdist``-alike functionality. While this may appear cumbersome, given the added pieces, it in fact tremendously enhances the portability of your package. The change is driven under `PEP 517 `` +build-requirements>``. To learn more about Python packaging in general, +navigate to the `bottom `_ of this page. Basic Use ========= @@ -61,12 +62,14 @@ This is what your project would look like:: setup.cfg mypackage/__init__.py -As you can see, it doesn't take much to use setuptools in a project. Invoke -the installer at the root of your package:: +Then, you need an installer, such as ``pep517 Date: Mon, 25 May 2020 16:08:57 -0400 Subject: docs: update quickstart added a few sections (WIP) to make it more complete --- docs/userguide/quickstart.txt | 44 +++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 12 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.txt b/docs/userguide/quickstart.txt index 95abec0f..1b58dfb3 100644 --- a/docs/userguide/quickstart.txt +++ b/docs/userguide/quickstart.txt @@ -2,20 +2,18 @@ ``setuptools`` Quickstart ========================== +.. contents:: + Installation ============ -.. _Installing Packages: https://packaging.python.org/tutorials/installing-packages/ - To install the latest version of setuptools, use:: pip install --upgrade setuptools -Refer to `Installing Packages`_ guide for more information. Python packaging at a glance ============================ - The landscape of Python packaging is shifting and ``Setuptools`` has evolved to only provide backend support, no longer being the de-facto packaging tool in the market. All python package must provide a ``pyproject.toml`` and specify @@ -27,9 +25,9 @@ change is driven under `PEP 517 ``. To learn more about Python packaging in general, navigate to the `bottom `_ of this page. + Basic Use ========= - For basic use of setuptools, you will need a ``pyproject.toml`` with the exact following info, which declares you want to use ``setuptools`` to package your project: @@ -62,14 +60,14 @@ This is what your project would look like:: setup.cfg mypackage/__init__.py -Then, you need an installer, such as ``pep517 `_ which you can obtain via ``pip install pep517``. After downloading it, invoke the installer:: pep517 build You now have your distribution ready (e.g. a ``tar.gz`` file and a ``.whl`` -file in the ``dist``), which you can upload to PyPI! +file in the ``dist`` directory), which you can upload to PyPI! 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 @@ -78,9 +76,9 @@ dependencies, and perhaps some data files and scripts. In the next few section, we will walk through those additional but essential information you need to specify to properly package your project. + Automatic package discovery =========================== - For simple projects, it's usually easy enough to manually add packages to the ``packages`` keyword in ``setup.cfg``. However, for very large projects , it can be a big burden to keep the package list updated. ``setuptools`` @@ -105,9 +103,9 @@ that each entry in the ``[options.packages.find]`` is optional. The above setup also allows you to adopt a ``src/`` layout. For more details and advanced use, go to :ref:`package_discovery` + Entry points and automatic script creation =========================================== - Setuptools support automatic creation of scripts upon installation, that runs code within your package if you specify them with the ``entry_point`` keyword. This is what allows you to run commands like ``pip install`` instead of having @@ -126,9 +124,9 @@ invoke the ``some_func`` in the ``__init__.py`` file when called by the user. For detailed usage, including managing the additional or optional dependencies, go to :ref:`entry_point`. + Dependency management ===================== - ``setuptools`` supports automatically installing dependencies when a package is installed. The simplest way to include requirement specifiers is to use the ``install_requires`` argument to ``setup.cfg``. It takes a string or list of @@ -151,9 +149,9 @@ care of those needed by automatically generated scripts. It also provides mechanisms to handle dependencies that are not in PyPI. For more advanced use, see :ref:`dependency_management` + Including Data Files ==================== - The distutils have traditionally allowed installation of "data files", which are placed in a platform-specific location. Setuptools offers three ways to specify data files to be included in your packages. For the simpliest use, you @@ -166,5 +164,27 @@ can simply use the ``include_package_data`` keyword: This tells setuptools to install any data files it finds in your packages. The data files must be specified via the distutils' ``MANIFEST.in`` file. - For more details, see :ref:`datafiles` + + +Uploading your package to PyPI +============================== +After generating the distribution files, next step would be to upload your +distribution so others can use it. This functionality is provided by +``twine `` and we will only demonstrate the +basic use here. + + +Transitioning from ``setup.py`` to ``setup.cfg`` +================================================== +To avoid executing arbitary scripts and boilerplate code, we are transitioning +into a full-fledged ``setup.cfg`` to declare your package information instead +of running ``setup()``. This inevitably brings challenges due to a different +syntax. Here we provide a quick guide to understanding how ``setup.cfg`` is +parsed by ``setuptool`` to ease the pain of transition. + + +Resources on Python packaging +============================= +Packaging in Python is hard. Here we provide a list of links for those that +want to learn more. -- cgit v1.2.1 From 992ecc09a2aa08310ae9bba4865e54e157b581cb Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Mon, 25 May 2020 17:46:28 -0400 Subject: docs: proper invocation of pep517 before: pep517 build (incorrect) now: python -m pep517.build (correct) --- docs/userguide/quickstart.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.txt b/docs/userguide/quickstart.txt index 1b58dfb3..224be368 100644 --- a/docs/userguide/quickstart.txt +++ b/docs/userguide/quickstart.txt @@ -64,7 +64,7 @@ Then, you need an installer, such as `pep517 ` which you can obtain via ``pip install pep517``. After downloading it, invoke the installer:: - pep517 build + python -m pep517.build You now have your distribution ready (e.g. a ``tar.gz`` file and a ``.whl`` file in the ``dist`` directory), which you can upload to PyPI! -- cgit v1.2.1 From b13e4a2a96c2d88890157fdd0b116619436761c4 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Mon, 25 May 2020 21:32:01 -0400 Subject: docs: add dev mode section in quickstart --- docs/userguide/quickstart.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.txt b/docs/userguide/quickstart.txt index 224be368..52829751 100644 --- a/docs/userguide/quickstart.txt +++ b/docs/userguide/quickstart.txt @@ -167,6 +167,26 @@ The data files must be specified via the distutils' ``MANIFEST.in`` file. For more details, see :ref:`datafiles` +Development mode +================ +``setuptools`` allows you to install a package without copying any files +to your interpretor directory (e.g. the ``site-packages`` directory). This +allows you to modify your source code and have the changes take effect without +you having to rebuild and reinstall. This is currently incompatible with +PEP 517 and therefore it requires a ``setup.py`` script with the following +content:: + + import setuptools + setuptools.setup() + +Then:: + + pip install --editable . + +This creates a link file in your interpretor site package directory which +associate with your source code. For more information, see: (WIP) + + Uploading your package to PyPI ============================== After generating the distribution files, next step would be to upload your -- cgit v1.2.1 From d51059ac1cc2fcc54a572eecadfae7e2bb07ad70 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Tue, 26 May 2020 00:43:54 -0400 Subject: docs: WIP detailed guide on pkg discovery --- docs/userguide/package_discovery.txt | 101 ++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 38 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/package_discovery.txt b/docs/userguide/package_discovery.txt index 8ba12cdf..45d88b60 100644 --- a/docs/userguide/package_discovery.txt +++ b/docs/userguide/package_discovery.txt @@ -1,65 +1,90 @@ +.. _`package_discovery`: + =================== Package Discovery =================== ``Setuptools`` provide powerful tools to handle package discovery, including -support for namespace package. The following explain how you include package -in your ``setup`` script:: +support for namespace package. Normally, you would specify the package to be +included manually in the following manner: + +.. code-block:: ini + + [options] + packages = + mypkg1 + mypkg2 + +.. code-block:: python setup( packages = ['mypkg1', 'mypkg2'] ) -To speed things up, we introduce two functions provided by setuptools:: +This can get tiresome reallly quickly. To speed things up, we introduce two +functions provided by setuptools: - from setuptools import find_packages +.. code-block:: ini -or:: + [options] + packages = find: + #or + packages = find_namespace: +.. code-block:: python + + from setuptools import find_packages + #or from setuptools import find_namespace_packages -Using ``find_packages()`` -------------------------- +Using ``find:`` (``find_packages``) +=================================== +Let's start with the first tool. ``find:`` (``find_packages``) takes a source +directory and two lists of package name patterns to exclude and include, and +then return a list of ``str`` representing the packages it could find. To use +it, consider the following directory + + mypkg/ + src/ + pkg1/__init__.py + pkg2/__init__.py + tests/__init__.py + setup.cfg #or setup.py -Let's start with the first tool. +To have your setup.cfg or setup.py to automatically include packages found +in ``src`` that starts with the name ``pkg`` and not ``tests``: -``find_packages()`` takes a source directory and two lists of package name -patterns to exclude and include. 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.) +.. code-block:: ini -Anyway, ``find_packages()`` walks the target directory, filtering by inclusion -patterns, and finds Python packages (any directory). Packages are only -recognized if they include an ``__init__.py`` file. Finally, exclusion -patterns are applied to remove matching packages. + [options] + packages = find: + package_dir = + =src -Inclusion and 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:: + [options.packages.find] + where = src + include = pkg* + exclude = tests - find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]) +.. code-block:: python -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. + setup( + #... + packages = find_packages( + where = 'src', + include = ['pkg*',], + exclude = ['tests',] + ), + package_dir = {"":"src"} + #... + ) -Regardless of the parameters, 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. +Of course the keywords presented here appear arbitary and the example given +doesn't apply to every other scenarios. For best understanding, we recommend +going to :ref:`keywords_ref`. +#####WIP below######### ``find_namespace_packages()`` ----------------------------- In Python 3.3+, ``setuptools`` also provides the ``find_namespace_packages`` variant -- cgit v1.2.1 From 9b87e896de30cda6003bb2f18c41c5f6c4db9d12 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Tue, 26 May 2020 13:27:34 -0400 Subject: docs: detail pkg discover guide and namespace pkg userguide/pkg_discovery.txt now covers find_package, find_namespace package and legacy use of namespace package creation in both setup.py and setup.cfg style --- docs/userguide/package_discovery.txt | 210 +++++++++++++++++------------------ 1 file changed, 105 insertions(+), 105 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/package_discovery.txt b/docs/userguide/package_discovery.txt index 45d88b60..77d61770 100644 --- a/docs/userguide/package_discovery.txt +++ b/docs/userguide/package_discovery.txt @@ -1,8 +1,19 @@ .. _`package_discovery`: -=================== -Package Discovery -=================== +======================================== +Package Discovery and Namespace Package +======================================== + +.. note:: + a full specification for the keyword supplied to ``setup.cfg`` or + ``setup.py`` can be found at :ref:`keywords reference ` + +.. note:: + the examples provided here are only to demonstrate the functionality + introduced. More metadata and options arguments need to be supplied + if you want to replicate them on your system. If you are completely + new to setuptools, the :ref:`quickstart section ` is a good + place to start. ``Setuptools`` provide powerful tools to handle package discovery, including support for namespace package. Normally, you would specify the package to be @@ -38,22 +49,25 @@ functions provided by setuptools: from setuptools import find_namespace_packages -Using ``find:`` (``find_packages``) -=================================== +Using ``find:`` or ``find_packages`` +==================================== Let's start with the first tool. ``find:`` (``find_packages``) takes a source directory and two lists of package name patterns to exclude and include, and then return a list of ``str`` representing the packages it could find. To use it, consider the following directory +.. code-block:: bash + mypkg/ src/ pkg1/__init__.py pkg2/__init__.py - tests/__init__.py + additional/__init__.py + setup.cfg #or setup.py To have your setup.cfg or setup.py to automatically include packages found -in ``src`` that starts with the name ``pkg`` and not ``tests``: +in ``src`` that starts with the name ``pkg`` and not ``additional``: .. code-block:: ini @@ -65,7 +79,7 @@ in ``src`` that starts with the name ``pkg`` and not ``tests``: [options.packages.find] where = src include = pkg* - exclude = tests + exclude = additional .. code-block:: python @@ -80,127 +94,113 @@ in ``src`` that starts with the name ``pkg`` and not ``tests``: #... ) -Of course the keywords presented here appear arbitary and the example given -doesn't apply to every other scenarios. For best understanding, we recommend -going to :ref:`keywords_ref`. -#####WIP below######### -``find_namespace_packages()`` ------------------------------ -In Python 3.3+, ``setuptools`` also provides the ``find_namespace_packages`` variant -of ``find_packages``, which has the same function signature as -``find_packages``, but works with `PEP 420`_ compliant implicit namespace -packages. Here is a minimal setup script using ``find_namespace_packages``:: +Using ``find_namespace:`` or ``find_namespace_packages`` +======================================================== +``setuptools`` provides the ``find_namespace:`` (``find_namespace_packages``) +which behaves similarly to ``find:`` but works with namespace package. Before +diving in, it is important to have a good understanding of what namespace +packages are. Here is a quick recap: - from setuptools import setup, find_namespace_packages - setup( - name="HelloWorld", - version="0.1", - packages=find_namespace_packages(), - ) +Suppose you have two packages named as follows: +.. code-block:: bash -Keep in mind that according to PEP 420, you may have to either re-organize your -codebase a bit or define a few exclusions, as the definition of an implicit -namespace package is quite lenient, so for a project organized like so:: + /Users/Desktop/timmins/foo/__init__.py + /Library/timmins/bar/__init__.py +If both ``Desktop`` and ``Library`` are on your ``PYTHONPATH``, then a +namespace package called ``timmins`` will be created automatically for you when +you invoke the import mechanism, allowing you to accomplish the following - ├── namespace - │   └── mypackage - │   ├── __init__.py - │   └── mod1.py - ├── setup.py - └── tests - └── test_mod1.py +.. code-block:: python -A naive ``find_namespace_packages()`` would install both ``namespace.mypackage`` and a -top-level package called ``tests``! One way to avoid this problem is to use the -``include`` keyword to whitelist the packages to include, like so:: + >>> import timmins.foo + >>> import timmins.bar - from setuptools import setup, find_namespace_packages +as if there is only one ``timmins`` on your system. The two packages can then +be distributed separately and installed individually without affecting the +other one. Suppose you are packaging the ``foo`` part: - setup( - name="namespace.mypackage", - version="0.1", - packages=find_namespace_packages(include=["namespace.*"]) - ) +.. code-block:: bash + + foo/ + src/ + timmins/foo/__init__.py + setup.cfg # or setup.py + +and you want the ``foo`` to be automatically included, ``find:`` won't work +because timmins doesn't contain ``__init__.py`` directly, instead, you have +to use ``find_namespace:``: + +.. code-block:: ini + + [options] + package_dir = + =src + packages = find_namespace: -Another option is to use the "src" layout, where all package code is placed in -the ``src`` directory, like so:: + [options.packages.find_namespace] + where = src +When you install the zipped distribution, ``timmins.foo`` would become +available to your interpreter. - ├── setup.py - ├── src - │   └── namespace - │   └── mypackage - │   ├── __init__.py - │   └── mod1.py - └── tests - └── test_mod1.py +You can think of ``find_namespace:`` as identical to ``find:`` except it +would count a directory as a package even if it doesn't contain ``__init__.py`` +file directly. As a result, this creates an interesting side effect. If you +organize your package like this: -With this layout, the package directory is specified as ``src``, as such:: +.. code-block:: bash - setup(name="namespace.mypackage", - version="0.1", - package_dir={"": "src"}, - packages=find_namespace_packages(where="src")) + foo/ + timmins/ + foo/__init__.py + setup.cfg # or setup.py + tests/ + test_foo/__init__.py -.. _PEP 420: https://www.python.org/dev/peps/pep-0420/ +a naive ``find_namespace:`` would include tests as part of your package to +be installed. A simple way to fix it is to adopt the aforementioned +``src`` layout. -Namespace Packages ------------------- +Legacy Namespace Packages +========================== +The fact you can create namespace package so effortlessly above is credited +to `PEP 420 `_. In the past, it +is more cumbersome to accomplish the same result. -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. +Starting with the same layout, there are two pieces you need to add to it. +First, an ``__init__.py`` file directly under your namespace package +directory that contains the following: -The ``pkg_resources`` runtime will then automatically ensure that the contents -of namespace packages that are spread over multiple eggs or directories are -combined into a single "virtual" package. +.. code-block:: python -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. The argument should list the namespace packages that the egg -participates in. For example, the ZopeInterface project might do this:: + __import__("pkg_resources").declare_namespace(__name__) + +And the ``namespace_packages`` keyword in your ``setup.cfg`` or ``setup.py``: + +.. code-block:: ini + + [options] + namespace_packages = timmins + +.. code-block:: python setup( # ... - namespace_packages=["zope"] + namespace_packages = ['timmins'] ) -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. When these projects are -installed and used, Python will see them both as part of a "virtual" ``zope`` -package, even though they will be installed in different locations. - -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. +And your directory should look like this:: -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 -*must* contain the line:: - - __import__("pkg_resources").declare_namespace(__name__) + /foo/ + src/ + timmins/ + __init__.py + foo/__init__.py + setup.cfg #or setup.py -This code ensures that the namespace package machinery is operating and that -the current package is registered as a namespace package. - -You must NOT include any other code and data in a namespace package's -``__init__.py``. Even though it may appear to work during development, or when -projects are installed as ``.egg`` files, it will not work when the projects -are installed using "system" packaging tools -- in such cases the -``__init__.py`` files will not be installed, let alone executed. - -You must include the ``declare_namespace()`` line in the ``__init__.py`` of -*every* project that has contents for the namespace package in question, in -order to ensure that the namespace will be declared regardless of which -project's copy of ``__init__.py`` is loaded first. If the first loaded -``__init__.py`` doesn't declare it, it will never *be* declared, because no -other copies will ever be loaded! +Repeat the same for other packages and you can achieve the same result as +the previous section. -- cgit v1.2.1 From e53fe0d2eafa85c3ad85c837953f67f4aba28ed3 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Tue, 26 May 2020 23:47:49 -0400 Subject: docs: cover pkgutil style namespace pkg --- docs/userguide/package_discovery.txt | 41 +++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 8 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/package_discovery.txt b/docs/userguide/package_discovery.txt index 77d61770..350a02ad 100644 --- a/docs/userguide/package_discovery.txt +++ b/docs/userguide/package_discovery.txt @@ -22,6 +22,7 @@ included manually in the following manner: .. code-block:: ini [options] + #... packages = mypkg1 mypkg2 @@ -29,6 +30,7 @@ included manually in the following manner: .. code-block:: python setup( + #... packages = ['mypkg1', 'mypkg2'] ) @@ -166,14 +168,24 @@ be installed. A simple way to fix it is to adopt the aforementioned Legacy Namespace Packages -========================== +========================= The fact you can create namespace package so effortlessly above is credited -to `PEP 420 `_. In the past, it -is more cumbersome to accomplish the same result. - -Starting with the same layout, there are two pieces you need to add to it. -First, an ``__init__.py`` file directly under your namespace package -directory that contains the following: +to `PEP 420 `_. It use to be more +cumbersome to accomplish the same result. Historically, there were two methods +to create namespace packages. One is the ``pkg_resources`` style supported by +``setuptools`` and the other one being ``pkgutils`` style offered by +``pkgutils`` module in Python. Both are now considered deprecated despite the +fact they still linger in many existing packages. These two differ in many +subtle yet significant aspects and you can find out more on `Python packaging +user guide `_ + + +``pkg_resource`` style namespace package +---------------------------------------- +This is the method ``setuptools`` directly supports. Starting with the same +layout, there are two pieces you need to add to it. First, an ``__init__.py`` +file directly under your namespace package directory that contains the +following: .. code-block:: python @@ -193,7 +205,9 @@ And the ``namespace_packages`` keyword in your ``setup.cfg`` or ``setup.py``: namespace_packages = ['timmins'] ) -And your directory should look like this:: +And your directory should look like this + +.. code-block:: bash /foo/ src/ @@ -204,3 +218,14 @@ And your directory should look like this:: Repeat the same for other packages and you can achieve the same result as the previous section. + +``pkgutil`` style namespace package +----------------------------------- +This method is almost identical to the ``pkg_resource`` except that the +``__init__.py`` file contains the following: + +.. code-block:: python + + __path__ = __import__('pkgutil').extend_path(__path__, __name__) + +The project layout remains the same and ``setup.cfg`` remains the same. -- cgit v1.2.1 From 70c8c0f39cf737d5eff70e36af5c66973ae1340a Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 27 May 2020 08:54:37 -0400 Subject: Mention that `namespace_packages` is omitted. --- docs/userguide/package_discovery.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/package_discovery.txt b/docs/userguide/package_discovery.txt index 350a02ad..0e0d27c5 100644 --- a/docs/userguide/package_discovery.txt +++ b/docs/userguide/package_discovery.txt @@ -222,7 +222,8 @@ the previous section. ``pkgutil`` style namespace package ----------------------------------- This method is almost identical to the ``pkg_resource`` except that the -``__init__.py`` file contains the following: +``namespace_packages`` declaration is omitted and the ``__init__.py`` +file contains the following: .. code-block:: python -- cgit v1.2.1 From 1639d010a7469ca6cabf49d038dfcfb4a4472a3d Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Tue, 26 May 2020 17:49:10 -0400 Subject: docs: detail userguide for entry point WIP --- docs/userguide/entry_point.txt | 118 +++++++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 47 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/entry_point.txt b/docs/userguide/entry_point.txt index 18211a72..a23d223b 100644 --- a/docs/userguide/entry_point.txt +++ b/docs/userguide/entry_point.txt @@ -2,61 +2,82 @@ Entry Points and Automatic Script Creation ========================================== -Packaging and installing scripts can be a bit awkward with the distutils. For -one thing, there's no easy way to have a script's filename match local -conventions on both Windows and POSIX platforms. For another, you often have -to create a separate file just for the "main" script, when your actual "main" -is a function in a module somewhere. And even in Python 2.4, using the ``-m`` -option only works for actual ``.py`` files that aren't installed in a package. - -``setuptools`` fixes all of these problems by automatically generating scripts -for you with the correct extension, and on Windows it will even create an -``.exe`` file so that users don't have to change their ``PATHEXT`` settings. -The way to use this feature is to define "entry points" in your setup script -that indicate what function the generated script should import and run. For -example, to create two console scripts called ``foo`` and ``bar``, and a GUI -script called ``baz``, you might do something like this:: +When installing a package, you may realize you can invoke some commands without +explicitly calling the python interpreter. For example, instead of calling +``python -m pip install`` you can just do ``pip install``. The magic behind +this is entry point, a keyword passed to your ``setup.cfg`` or ``setup.py`` +to create script wrapped around function in your libraries. + + +Using entry point in your package +================================= +Let's start with an example. Suppose you have written your package like this: + +.. code-block:: bash + + timmins/ + timmins/__init__.py + setup.cfg + #other necessary files + +and in your ``__init__.py`` it defines a function: + +.. code-block:: python + + def helloworld(): + print("Hello world") + +After installing the package, you can invoke this function in the following +manner, without applying any magic: + +.. code-block:: bash + + python -m mypkg.helloworld + +But entry point simplifies this process and would create a wrapper script around +your function, making it behave more natively. To do that, add the following +lines to your ``setup.cfg`` or ``setup.py``: + +.. code-block:: ini + + [options] + #... + entry_points = + [console_scripts] + helloworld = mypkg:helloworld + +.. code-block:: python setup( - # other arguments here... - entry_points={ - "console_scripts": [ - "foo = my_package.some_module:main_func", - "bar = other_module:some_func", - ], - "gui_scripts": [ - "baz = my_package_gui:start_func", - ] - } + #... + entry_points = """ + [console_scripts] + helloworld = mypkg:helloworld + """ ) -When this project is installed on non-Windows platforms (using "setup.py -install", "setup.py develop", or with pip), a set of ``foo``, ``bar``, -and ``baz`` scripts will be installed that import ``main_func`` and -``some_func`` from the specified modules. The functions you specify are -called with no arguments, and their return value is passed to -``sys.exit()``, so you can return an errorlevel or message to print to -stderr. +The syntax for your entry points is specified as follows -On Windows, a set of ``foo.exe``, ``bar.exe``, and ``baz.exe`` launchers are -created, alongside a set of ``foo.py``, ``bar.py``, and ``baz.pyw`` files. The -``.exe`` wrappers find and execute the right version of Python to run the -``.py`` or ``.pyw`` file. +.. code-block:: -You may define as many "console script" and "gui script" entry points as you -like, and each one can optionally specify "extras" that it depends on, that -will be added to ``sys.path`` when the script is run. For more information on -"extras", see the section below on `Declaring Extras`_. For more information -on "entry points" in general, see the section below on `Dynamic Discovery of -Services and Plugins`_. + [] + = [..]: +where ``name`` is the name for the script you want to create and the left hand +side of ``:`` is the module that contains your function and the right hand +side is the function you wish to wrap. ``type`` specifies the type of script +you want to create. ``setuptools`` currently supports either ``[console_script]`` +and ``[gui_script]`` (DOUBLE CHECK ON THIS). -Dynamic Discovery of Services and Plugins ------------------------------------------ +After installation, you will be able to invoke that function simply calling +``helloworld`` on your command line. It will also do command line options parsing +for you! -``setuptools`` supports creating libraries that "plug in" to extensible -applications and frameworks, by letting you register "entry points" in your -project that can be imported by the application or framework. +Dynamic discovery of services and plugins +========================================= +The ability of entry points isn't limited to "advertising" your functions. In +fact, its implementation allows us to achieve more powerful features, such as +supporting libraries that "plus in" to extensible applications and frameworks For example, suppose that a blogging tool wants to support plugins that provide translation for various file types to the blog's output format. @@ -112,4 +133,7 @@ of an entry point, any requirements implied by the associated extras will be passed to ``pkg_resources.require()``, so that an appropriate error message can be displayed if the needed package(s) are missing. (Of course, the invoking app or framework can ignore such errors if it wants to make an entry -point optional if a requirement isn't installed.) \ No newline at end of file +point optional if a requirement isn't installed.) + +Dependencies management for entry points +======================================== -- cgit v1.2.1 From 45e784678b46636b7152ad7557d0757c3dfefaec Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Wed, 27 May 2020 11:08:45 -0400 Subject: docs: update entry point userguide --- docs/userguide/entry_point.txt | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/entry_point.txt b/docs/userguide/entry_point.txt index a23d223b..5772698e 100644 --- a/docs/userguide/entry_point.txt +++ b/docs/userguide/entry_point.txt @@ -34,9 +34,10 @@ manner, without applying any magic: python -m mypkg.helloworld -But entry point simplifies this process and would create a wrapper script around -your function, making it behave more natively. To do that, add the following -lines to your ``setup.cfg`` or ``setup.py``: +But entry point simplifies the call and would create a wrapper script around +your function, making it behave more natively (you type in ``helloworld`` and +the ``helloworld`` function residing inside ``__init__.py`` is executed!). To +accomplish that, add the following lines to your ``setup.cfg`` or ``setup.py``: .. code-block:: ini @@ -56,22 +57,27 @@ lines to your ``setup.cfg`` or ``setup.py``: """ ) -The syntax for your entry points is specified as follows +The syntax for entry points is specified as follows: .. code-block:: [] - = [..]: + = [..][:.] -where ``name`` is the name for the script you want to create and the left hand +where ``name`` is the name for the script you want to create, the left hand side of ``:`` is the module that contains your function and the right hand -side is the function you wish to wrap. ``type`` specifies the type of script -you want to create. ``setuptools`` currently supports either ``[console_script]`` -and ``[gui_script]`` (DOUBLE CHECK ON THIS). - -After installation, you will be able to invoke that function simply calling -``helloworld`` on your command line. It will also do command line options parsing -for you! +side is the object you want to invoke (e.g. a function). ``type`` specifies the +type of script you want to create. ``setuptools`` currently supports either +``[console_script]`` and ``[gui_script]``. + +.. note:: + the syntax is not limited to ``INI`` string as demonstrated above. You can + also pass in the values in the form of a dictionary or list. Check out + :ref:`keyword reference ` for more details + +After installation, you will be able to invoke that function by simply calling +``helloworld`` on your command line. It will even do command line argument +parsing for you! Dynamic discovery of services and plugins ========================================= -- cgit v1.2.1 From 3eb1cecdd24c53bd07911177c52b3de253159709 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 28 May 2020 13:28:02 -0400 Subject: docs: guide on entry point completed Coverage 1. console_script 2. plugin support 3. optional dependencies --- docs/userguide/entry_point.txt | 181 +++++++++++++++++++++++++++-------------- 1 file changed, 118 insertions(+), 63 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/entry_point.txt b/docs/userguide/entry_point.txt index 5772698e..fe31f446 100644 --- a/docs/userguide/entry_point.txt +++ b/docs/userguide/entry_point.txt @@ -1,12 +1,14 @@ +.. _`entry_points`: + ========================================== Entry Points and Automatic Script Creation ========================================== -When installing a package, you may realize you can invoke some commands without -explicitly calling the python interpreter. For example, instead of calling -``python -m pip install`` you can just do ``pip install``. The magic behind -this is entry point, a keyword passed to your ``setup.cfg`` or ``setup.py`` -to create script wrapped around function in your libraries. +After installing some packages, you may realize you can invoke some commands +without explicitly calling the python interpreter. For example, instead of +calling ``python -m pip install`` you can just do ``pip install``. The magic +behind this is entry point, a keyword passed to your ``setup.cfg`` or +``setup.py`` to create script wrapped around function in your libraries. Using entry point in your package @@ -17,7 +19,7 @@ Let's start with an example. Suppose you have written your package like this: timmins/ timmins/__init__.py - setup.cfg + setup.cfg # or setup.py #other necessary files and in your ``__init__.py`` it defines a function: @@ -79,67 +81,120 @@ After installation, you will be able to invoke that function by simply calling ``helloworld`` on your command line. It will even do command line argument parsing for you! -Dynamic discovery of services and plugins -========================================= -The ability of entry points isn't limited to "advertising" your functions. In -fact, its implementation allows us to achieve more powerful features, such as -supporting libraries that "plus in" to extensible applications and frameworks - -For example, suppose that a blogging tool wants to support plugins -that provide translation for various file types to the blog's output format. -The framework might define an "entry point group" called ``blogtool.parsers``, -and then allow plugins to register entry points for the file extensions they -support. - -This would allow people to create distributions that contain one or more -parsers for different file types, and then the blogging tool would be able to -find the parsers at runtime by looking up an entry point for the file -extension (or mime type, or however it wants to). - -Note that if the blogging tool includes parsers for certain file formats, it -can register these as entry points in its own setup script, which means it -doesn't have to special-case its built-in formats. They can just be treated -the same as any other plugin's entry points would be. - -If you're creating a project that plugs in to an existing application or -framework, you'll need to know what entry points or entry point groups are -defined by that application or framework. Then, you can register entry points -in your setup script. Here are a few examples of ways you might register an -``.rst`` file parser entry point in the ``blogtool.parsers`` entry point group, -for our hypothetical blogging tool:: - setup( - # ... - entry_points={"blogtool.parsers": ".rst = some_module:SomeClass"} - ) +Dynamic discovery of services (aka plugin support) +================================================== +The ability of entry points isn't limited to "advertising" your functions. Its +implementation allows us to accomplish more powerful features, such as creating +plugins. In fact, the aforementioned script wrapping ability is a form of +plugin that was built into ``setuptools``. With that being said, you now have +more options than ``[console_script]`` or ``[gui_script]`` when creating your +package. - setup( - # ... - entry_points={"blogtool.parsers": [".rst = some_module:a_func"]} - ) +To understand how you can extend this functionality, let's go through how +``setuptool`` does its ``[console_script]`` magic. Again, we use the same +example as above: - setup( - # ... - entry_points=""" - [blogtool.parsers] - .rst = some.nested.module:SomeClass.some_classmethod [reST] - """, - extras_require=dict(reST="Docutils>=0.3.5") - ) +.. code-block:: ini + + [options] + # ... + entry_points = + [console_scripts] + helloworld = mypkg:helloworld + +Package installation contains multiple steps, so at some point, this package +becomes available to your interpreter, and if you run the following code: + +.. code-block:: ini + + >>> import pkg_resources #a module part of setuptools + >>> [item for item in + pkg_srouces.working_set.iter_entry_points('console_scripts')] + +It will return a list of special objects (called "EntryPoints"), and there +will be one of them that corresponds to the ``helloworld = mypkg:helloworld`` +which we defined above. In fact, this object doesn't just contain the string, +but also an encompassing representation of the package that created it. +In the case of ``console_scripts``, setuptools will automatically invoke +an internal function that utilizes this object and create the wrapper scripts +and place them in your ``bin`` directory for your interpreter. How +``pkg_resource`` look up all the entry points is further detailed in our +:ref:`developer_guide` (WIP). With that being said, if you specify a different +entry point: + +.. code-block:: ini + + [options] + # ... + entry_points = + [iam.just.playing.around] + helloworld = mypkg:helloworld + +Then, running the same python expression like above: + +.. code-block:: python + + >>> import pkg_resources + >>> [item for item in + pkg_srouces.working_set.iter_entry_points('iam.just.playing.around') + ] + +will create another ``EntryPoints`` object that contains the +``helloworld = mypkg:helloworld`` and you can create custom +functions to exploit its information however you want. For example, one of +the installed programs on your system may contain a startup script that +scans the system for all the packages that specify this +``iam.just.playing.around`` entry points, such that when you install this new +package, it becomes immediately available without having to reconfigure +the already installed program. This in fact is the very idea of a plugin! -The ``entry_points`` argument to ``setup()`` accepts either a string with -``.ini``-style sections, or a dictionary mapping entry point group names to -either strings or lists of strings containing entry point specifiers. An -entry point specifier consists of a name and value, separated by an ``=`` -sign. The value consists of a dotted module name, optionally followed by a -``:`` and a dotted identifier naming an object within the module. It can -also include a bracketed list of "extras" that are required for the entry -point to be used. When the invoking application or framework requests loading -of an entry point, any requirements implied by the associated extras will be -passed to ``pkg_resources.require()``, so that an appropriate error message -can be displayed if the needed package(s) are missing. (Of course, the -invoking app or framework can ignore such errors if it wants to make an entry -point optional if a requirement isn't installed.) Dependencies management for entry points ======================================== +Some entry points may require additional dependencies for them to work and +others may trigger the installation of additional dependencies only when they +are run. While this is elaborated in more excrutiating details on +:ref:`guide on dependencies management `, we will +provide a brief overview on the entry point aspect. + +Dependencies of this manner are declared using the ``extra_requires`` keywords, +which takes a mapping of the arbitary name of the functionality and a list of +its depencencies, optionally suffixed with its :ref:`version specifier +`. For example, our package provides "pdf" output capability +which requires at least 0.3 version of "ReportLab" and whatever version of "RXP" + +.. code-block:: ini + + [options.extras_require] + PDF = ReportLab>=1.2; RXP + +.. code-block:: python + + setup( + extras_require = { + "PDF": ["ReportLab>=1.2", "RXP"], + } + ) + + +And we only want them to be installed if the console script entry point +``rst2pdf`` is run: + +.. code-block:: ini + + [options] + entry_points = + ['console_script'] + rst2pdf = project_a.tools.pdfgen [PDF] + rst2html = project_a.tools.htmlgen + +.. code-block:: python + + setup( + entry_points = """ + ['console_script'] + rst2pdf = project_a.tools.pdfgen [PDF] + rst2html = project_a.tools.htmlgen + """ + ) -- cgit v1.2.1 From 1459bb4dcdc0f08463c71906952b35275be531de Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 28 May 2020 14:32:49 -0400 Subject: docs: fixed mistaken explanation --- docs/userguide/entry_point.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/entry_point.txt b/docs/userguide/entry_point.txt index fe31f446..8190d8e3 100644 --- a/docs/userguide/entry_point.txt +++ b/docs/userguide/entry_point.txt @@ -69,8 +69,8 @@ The syntax for entry points is specified as follows: where ``name`` is the name for the script you want to create, the left hand side of ``:`` is the module that contains your function and the right hand side is the object you want to invoke (e.g. a function). ``type`` specifies the -type of script you want to create. ``setuptools`` currently supports either -``[console_script]`` and ``[gui_script]``. +type of entry point (pertinent to the program that exploits it). ``setuptools`` +natively supports ``[console_script]`` and ``[gui_script]``. .. note:: the syntax is not limited to ``INI`` string as demonstrated above. You can -- cgit v1.2.1 From fdf51a0bee8de4cf0c10ccd2f94541242580fa0c Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 28 May 2020 16:59:48 -0400 Subject: docs: editing user guide on dependency management --- docs/userguide/dependency_management.txt | 227 +++++++++++++++++++------------ 1 file changed, 137 insertions(+), 90 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.txt b/docs/userguide/dependency_management.txt index 18ba952f..d9990ded 100644 --- a/docs/userguide/dependency_management.txt +++ b/docs/userguide/dependency_management.txt @@ -2,71 +2,118 @@ Dependencies Management in Setuptools ===================================== -Declaring Dependencies -====================== +``Setuptools``'s dependency management is meticulous, or agonizing, depending +on your level of familiarity. There are three types of dependency styles. +1) those required to run the packaging program (build system requirement), +2) those your package depends on (required dependency) and 3) optional +dependency. -``setuptools`` supports automatically installing dependencies when a package is -installed, and including information about dependencies in Python Eggs (so that -package management tools like pip can use the information). +.. Note:: + For all the packages you intend to add to dependency, you can optionally + specify the version following :ref:`reference on version specifyer ` -``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 ``-``. -Version specifiers for a given project are internally sorted into ascending -version order, and used to establish what ranges of versions are acceptable. -Adjacent redundant conditions are also consolidated (e.g. ``">1, >2"`` becomes -``">2"``, and ``"<2,<3"`` becomes ``"<2"``). ``"!="`` versions are excised from -the ranges they fall within. A project's version is then checked for -membership in the resulting ranges. (Note that providing conflicting conditions -for the same version (e.g. "<2,>=2" or "==2,!=2") is meaningless and may -therefore produce bizarre results.) +Build system requirement +======================== -Here are some example requirement specifiers:: +Package requirement +------------------- +After organizing all the scripts and files and getting ready for packaging, +there needs to be a way to tell Python what programs it need to actually +do the packgaging (in our case, ``setuptools`` of course). Usually, +you also need the ``wheel`` package as well since it is recommended that you +upload a ``.whl`` file to PyPI alongside your ``.tar.gz`` file. Unlike the +other two types of dependency keyword, this one is specified in your +``pyproject.toml`` file (if you have forgot what this is, go to +:ref:`quickstart` or (WIP)): - docutils >= 0.3 +.. code-block:: ini - # 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 + [build-system] + requires = ["setuptools", "wheel"] + #... - PEAK[FastCGI, reST]>=0.5a4 +.. note:: + This used to be accomplished with the ``setup_requires`` keyword but is + now considered deprecated in favor of the PEP 517 style described above. + To peek into how this legacy keyword is used, consult our :ref:`guide on + deprecated practice (WIP)` - 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. +Python requirement +------------------ +In some cases, you might need to specify the minimum required python version. +This is handled with the ``python_requires`` keyword supplied to ``setup.cfg`` +or ``setup.py``. -This has three effects: +Example WIP -1. When your project is installed, either by using pip, ``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. -2. 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). +Declaring required dependency +============================= +This is where a package declares its core dependencies, without which it won't +be able to run. ``setuptools`` support automatically download and install +these dependencies when the package is installed. Although there is more +finess to it, let's start with a simple example. -3. Python Egg distributions will include a metadata file listing the - dependencies. +.. code-block:: ini + + [options] + #... + install_requires = + docutils + BazSpam ==1.1 + +.. code-block:: python + + setup( + #..., + install_requires = [ + 'docutils', + 'BazSpam ==1.1' + ] + ) + + +When your project is installed (e.g. using pip), all of the dependencies not +already installed will be located (via PyPI), downloaded, built (if necessary), +and installed and 2) 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). + + +Platform specific dependencies +------------------------------ +Sometimes a project might require a dependency to run on a specific platform. +This could to a package that back ports a module so that it can be used in +older python versions. Or it could be a package that is required to run on a +specific operating system. This will allow a project to work on multiple +different platforms without installing dependencies that are not required for +a platform that is installing the project. + +For example, here is a project that uses the ``enum`` module and ``pywin32``:: + + setup( + name="Project", + ... + install_requires=[ + "enum34;python_version<'3.4'", + "pywin32 >= 1.0;platform_system=='Windows'" + ] + ) + +Since the ``enum`` module was added in Python 3.4, it should only be installed +if the python version is earlier. Since ``pywin32`` will only be used on +windows, it should only be installed when the operating system is Windows. +Specifying version requirements for the dependencies is supported as normal. + +The environmental markers that may be used for testing platform types are +detailed in `PEP 508 `_. -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``.) Dependencies that aren't in PyPI -------------------------------- - .. warning:: Dependency links support has been dropped by pip starting with version 19.0 (released 2019-01-22). @@ -122,22 +169,27 @@ temporary folder and run ``setup.py bdist_egg``. The ``dependency_links`` option takes the form of a list of URL strings. For example, this will cause a search of the specified page for eggs or source -distributions, if the package's dependencies aren't already installed:: +distributions, if the package's dependencies aren't already installed: + +.. code-block:: ini + + [options] + #... + dependency_links = http://peak.telecommunity.com/snapshots/ + +.. code-block:: python setup( - ... + #... dependency_links=[ "http://peak.telecommunity.com/snapshots/" ], ) -.. _Declaring Extras: - - -Declaring "Extras" (optional features with their own dependencies) ------------------------------------------------------------------- +Optional 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 @@ -170,14 +222,28 @@ dependencies. For example, if Project A includes a "rst2pdf" script, it might declare it like this, so that the "PDF" requirements are only resolved if the "rst2pdf" script is run:: +.. code-block:: ini + + [metadata] + name = Project A + #... + + [options] + #... + entry_points= + [console_scripts] + rst2pdf = project_a.tools.pdfgen [PDF] + rst2html = project_a.tools.htmlgen + +.. code-block:: python + setup( - name="Project-A", - ... + name = "Project-A" + #..., entry_points={ "console_scripts": [ "rst2pdf = project_a.tools.pdfgen [PDF]", "rst2html = project_a.tools.htmlgen", - # more script entry points ... ], } ) @@ -186,6 +252,19 @@ Projects can also use another project's extras when specifying dependencies. For example, if project B needs "project A" with PDF support installed, it might declare the dependency like this:: +.. code-block:: ini + + [metadata] + name = Project-B + #... + + [options] + #... + install_requires = + Project-A[PDF] + +.. code-block:: python + setup( name="Project-B", install_requires=["Project-A[PDF]"], @@ -221,35 +300,3 @@ so that Package B doesn't have to remove the ``[PDF]`` from its requirement specifier. .. _Platform Specific Dependencies: - - -Declaring platform specific dependencies ----------------------------------------- - -Sometimes a project might require a dependency to run on a specific platform. -This could to a package that back ports a module so that it can be used in -older python versions. Or it could be a package that is required to run on a -specific operating system. This will allow a project to work on multiple -different platforms without installing dependencies that are not required for -a platform that is installing the project. - -For example, here is a project that uses the ``enum`` module and ``pywin32``:: - - setup( - name="Project", - ... - install_requires=[ - "enum34;python_version<'3.4'", - "pywin32 >= 1.0;platform_system=='Windows'" - ] - ) - -Since the ``enum`` module was added in Python 3.4, it should only be installed -if the python version is earlier. Since ``pywin32`` will only be used on -windows, it should only be installed when the operating system is Windows. -Specifying version requirements for the dependencies is supported as normal. - -The environmental markers that may be used for testing platform types are -detailed in `PEP 508`_. - -.. _PEP 508: https://www.python.org/dev/peps/pep-0508/ -- cgit v1.2.1 From 00888dd0d88a3463afd6e68ad85da515c194d63f Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 28 May 2020 17:49:45 -0400 Subject: docs: more finetuning on dependency guide --- docs/userguide/dependency_management.txt | 128 ++++++++++++++++--------------- 1 file changed, 68 insertions(+), 60 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.txt b/docs/userguide/dependency_management.txt index d9990ded..abde5503 100644 --- a/docs/userguide/dependency_management.txt +++ b/docs/userguide/dependency_management.txt @@ -12,6 +12,7 @@ dependency. For all the packages you intend to add to dependency, you can optionally specify the version following :ref:`reference on version specifyer ` +.. contents:: Build system requirement ======================== @@ -85,29 +86,48 @@ versions have been installed). Platform specific dependencies ------------------------------ -Sometimes a project might require a dependency to run on a specific platform. -This could to a package that back ports a module so that it can be used in -older python versions. Or it could be a package that is required to run on a -specific operating system. This will allow a project to work on multiple -different platforms without installing dependencies that are not required for -a platform that is installing the project. +Setuptools offer the capability to evaluate certain conditions before blindly +installing everything listed in ``install_requires``. This is great for platform +specific dependencies. For example, the ``enum`` package was added in Python +3.4, therefore, package that depends on it can elect to install it only when +the Python version is older than 3.4. To accomplish this -For example, here is a project that uses the ``enum`` module and ``pywin32``:: +.. code-block:: ini + + [options] + #... + install_requires = + enum34;python_version<'3.4' + +.. code-block:: python setup( - name="Project", - ... + #... + install_requires=[ + "enum34;python_version<'3.4'",] + ) + +Similarly, if you also wish to declare ``pywin32`` with a minimal version of 1.0 +and only install it if the user is using a Windows operating system: + +.. code-block:: ini + + [options] + #... + install_requires = + enum34;python_version<'3.4' + pywin32 >= 1.0;platform_system=='Windows' + +.. code-block:: python + + setup( + #... install_requires=[ "enum34;python_version<'3.4'", "pywin32 >= 1.0;platform_system=='Windows'" - ] + ] ) -Since the ``enum`` module was added in Python 3.4, it should only be installed -if the python version is earlier. Since ``pywin32`` will only be used on -windows, it should only be installed when the operating system is Windows. -Specifying version requirements for the dependencies is supported as normal. - The environmental markers that may be used for testing platform types are detailed in `PEP 508 `_. @@ -187,40 +207,40 @@ distributions, if the package's dependencies aren't already installed: ) - Optional 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``. +Setuptools allows you to declare dependencies that only get installed under +specific circumstances. For example, let's say that Project-A offers optional +PDF support and requires some additional package for it to work. Such a +dependency will be specified with ``extras_require`` keyword and they are only +installed if another package depends on it (either directly or indirectly). + +Let's first see how to specify such package: + +.. code-block:: ini + + [metadata] + name = Package-A + + [options.extras_require] + PDF = ReportLab>=1.2; RXP + -For example, let's say that Project A offers optional PDF and reST support:: +.. code-block:: python setup( name="Project-A", - ... + #... extras_require={ "PDF": ["ReportLab>=1.2", "RXP"], - "reST": ["docutils>=0.3"], } ) -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 "pip install" -command line.) +The name ``PDF`` is an arbitary identifier of such a list of dependencies, to +which other components can refer and have them installed. There are two common +use cases. -Extras can be used by a project's `entry points`_ to specify dynamic -dependencies. For example, if Project A includes a "rst2pdf" script, it might -declare it like this, so that the "PDF" requirements are only resolved if the -"rst2pdf" script is run:: +First is the console_scripts entry point: .. code-block:: ini @@ -248,9 +268,12 @@ declare it like this, so that the "PDF" requirements are only resolved if the } ) -Projects can also use another project's extras when specifying dependencies. -For example, if project B needs "project A" with PDF support installed, it -might declare the dependency like this:: +When the script ``rst2pdf`` is run, it will trigger the installation of +the two dependencies ``PDF`` maps to. + +The second use case is that other package can use this "extra" for their +own dependencies. For example, if "Project-B" needs "project A" with PDF support +installed, it might declare the dependency like this:: .. code-block:: ini @@ -280,23 +303,8 @@ 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. -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 could change its -setup to this:: - - 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. - -.. _Platform Specific Dependencies: +.. note:: + Best practice: 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). -- cgit v1.2.1 From 89e852c476c4fad9849ac21562be5be836c5a9f6 Mon Sep 17 00:00:00 2001 From: alvyjudy Date: Thu, 28 May 2020 17:58:16 -0400 Subject: docs: restored notes on "require()" function --- docs/userguide/dependency_management.txt | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.txt b/docs/userguide/dependency_management.txt index abde5503..ca2ac75a 100644 --- a/docs/userguide/dependency_management.txt +++ b/docs/userguide/dependency_management.txt @@ -83,6 +83,12 @@ 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). +.. note:: + 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. + Platform specific dependencies ------------------------------ -- cgit v1.2.1 From dfe2ef5d780f476db778aacfb37a44a017022180 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 15 Jun 2020 18:53:58 -0400 Subject: Correct some of the behaviors indicated in new entry points docs. Switch to imperative voice. Limit to declarative config (setup.cfg) examples. --- docs/userguide/entry_point.txt | 234 +++++++++++++++++------------------------ 1 file changed, 94 insertions(+), 140 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/entry_point.txt b/docs/userguide/entry_point.txt index 8190d8e3..7f5165a8 100644 --- a/docs/userguide/entry_point.txt +++ b/docs/userguide/entry_point.txt @@ -1,200 +1,154 @@ .. _`entry_points`: -========================================== -Entry Points and Automatic Script Creation -========================================== +============ +Entry Points +============ -After installing some packages, you may realize you can invoke some commands -without explicitly calling the python interpreter. For example, instead of -calling ``python -m pip install`` you can just do ``pip install``. The magic -behind this is entry point, a keyword passed to your ``setup.cfg`` or -``setup.py`` to create script wrapped around function in your libraries. +Packages may provide commands to be run at the console (console scripts), +such as the ``pip`` command. These commands are defined for a package +as a specific kind of entry point in the ``setup.cfg`` or +``setup.py``. -Using entry point in your package -================================= -Let's start with an example. Suppose you have written your package like this: +Console Scripts +=============== + +First consider an example without entry points. Imagine a package +defined thus:: .. code-block:: bash timmins/ timmins/__init__.py + timmins/__main__.py setup.cfg # or setup.py #other necessary files -and in your ``__init__.py`` it defines a function: +with ``__init__.py`` as: .. code-block:: python def helloworld(): print("Hello world") -After installing the package, you can invoke this function in the following -manner, without applying any magic: +and ``__main__.py`` providing a hook: + + from . import hello_world + if __name__ == '__main__': + hello_world() + +After installing the package, the function may be invoked through the +`runpy `_ module:: .. code-block:: bash - python -m mypkg.helloworld + python -m timmins -But entry point simplifies the call and would create a wrapper script around -your function, making it behave more natively (you type in ``helloworld`` and -the ``helloworld`` function residing inside ``__init__.py`` is executed!). To -accomplish that, add the following lines to your ``setup.cfg`` or ``setup.py``: +Adding a console script entry point allows the package to define a +user-friendly name for installers of the package to execute. Installers +like pip will create wrapper scripts to execute a function. In the +above example, to create a command ``hello-world`` that invokes +``timmins.hello_world``, add a console script entry point to +``setup.cfg``:: .. code-block:: ini - [options] - #... - entry_points = - [console_scripts] - helloworld = mypkg:helloworld - -.. code-block:: python + [options.entry_points] + console_scripts = + hello-world = timmins:hello_world - setup( - #... - entry_points = """ - [console_scripts] - helloworld = mypkg:helloworld - """ - ) +After installing the package, a user may invoke that function by simply calling +``hello-world`` on the command line. The syntax for entry points is specified as follows: .. code-block:: - [] - = [..][:.] + = [.[.]][:.] where ``name`` is the name for the script you want to create, the left hand side of ``:`` is the module that contains your function and the right hand -side is the object you want to invoke (e.g. a function). ``type`` specifies the -type of entry point (pertinent to the program that exploits it). ``setuptools`` -natively supports ``[console_script]`` and ``[gui_script]``. +side is the object you want to invoke (e.g. a function). -.. note:: - the syntax is not limited to ``INI`` string as demonstrated above. You can - also pass in the values in the form of a dictionary or list. Check out - :ref:`keyword reference ` for more details +In addition to ``console_scripts``, Setuptools supports ``gui_scripts``, which +will launch a GUI application without running in a terminal window. -After installation, you will be able to invoke that function by simply calling -``helloworld`` on your command line. It will even do command line argument -parsing for you! +Advertising Behavior +==================== -Dynamic discovery of services (aka plugin support) -================================================== -The ability of entry points isn't limited to "advertising" your functions. Its -implementation allows us to accomplish more powerful features, such as creating -plugins. In fact, the aforementioned script wrapping ability is a form of -plugin that was built into ``setuptools``. With that being said, you now have -more options than ``[console_script]`` or ``[gui_script]`` when creating your -package. +Console scripts are one use of the more general concept of entry points. Entry +points more generally allow a packager to advertise behavior for discovery by +other libraries and applications. This feature enables "plug-in"-like +functionality, where one library solicits entry points and any number of other +libraries provide those entry points. -To understand how you can extend this functionality, let's go through how -``setuptool`` does its ``[console_script]`` magic. Again, we use the same -example as above: +A good example of this plug-in behavior can be seen in +`pytest plugins `_, +where pytest is a test framework that allows other libraries to extend +or modify its functionality through the ``pytest11`` entry point. -.. code-block:: ini +The console scripts work similarly, where libraries advertise their commands +and tools like ``pip`` create wrapper scripts that invoke those commands. - [options] - # ... - entry_points = - [console_scripts] - helloworld = mypkg:helloworld +For a project wishing to solicit entry points, Setuptools recommends the +`importlib.metadata `_ +module (part of stdlib since Python 3.8) or its backport, +`importlib_metadata `_. -Package installation contains multiple steps, so at some point, this package -becomes available to your interpreter, and if you run the following code: +For example, to find the console script entry points from the example above:: -.. code-block:: ini +.. code-block:: python - >>> import pkg_resources #a module part of setuptools - >>> [item for item in - pkg_srouces.working_set.iter_entry_points('console_scripts')] - -It will return a list of special objects (called "EntryPoints"), and there -will be one of them that corresponds to the ``helloworld = mypkg:helloworld`` -which we defined above. In fact, this object doesn't just contain the string, -but also an encompassing representation of the package that created it. -In the case of ``console_scripts``, setuptools will automatically invoke -an internal function that utilizes this object and create the wrapper scripts -and place them in your ``bin`` directory for your interpreter. How -``pkg_resource`` look up all the entry points is further detailed in our -:ref:`developer_guide` (WIP). With that being said, if you specify a different -entry point: + >>> from importlib import metadata + >>> eps = metadata.entry_points()['console_scripts'] + +``eps`` is now a list of ``EntryPoint`` objects, one of which corresponds +to the ``hello-world = timmins:hello_world`` defined above. Each ``EntryPoint`` +contains the ``name``, ``group``, and ``value``. It also supplies a ``.load()`` +method to import and load that entry point (module or object). .. code-block:: ini - [options] - # ... - entry_points = - [iam.just.playing.around] - helloworld = mypkg:helloworld + [options.entry_points] + my.plugins = + hello-world = timmins:hello_world -Then, running the same python expression like above: +Then, a different project wishing to load 'my.plugins' plugins could run +the following routine to load (and invoke) such plugins:: .. code-block:: python - >>> import pkg_resources - >>> [item for item in - pkg_srouces.working_set.iter_entry_points('iam.just.playing.around') - ] - -will create another ``EntryPoints`` object that contains the -``helloworld = mypkg:helloworld`` and you can create custom -functions to exploit its information however you want. For example, one of -the installed programs on your system may contain a startup script that -scans the system for all the packages that specify this -``iam.just.playing.around`` entry points, such that when you install this new -package, it becomes immediately available without having to reconfigure -the already installed program. This in fact is the very idea of a plugin! - - -Dependencies management for entry points -======================================== -Some entry points may require additional dependencies for them to work and -others may trigger the installation of additional dependencies only when they -are run. While this is elaborated in more excrutiating details on -:ref:`guide on dependencies management `, we will -provide a brief overview on the entry point aspect. - -Dependencies of this manner are declared using the ``extra_requires`` keywords, -which takes a mapping of the arbitary name of the functionality and a list of -its depencencies, optionally suffixed with its :ref:`version specifier -`. For example, our package provides "pdf" output capability -which requires at least 0.3 version of "ReportLab" and whatever version of "RXP" - -.. code-block:: ini + >>> from importlib import metadata + >>> eps = metadata.entry_points()['my.plugins'] + >>> for ep in eps: + ... plugin = ep.load() + ... plugin() - [options.extras_require] - PDF = ReportLab>=1.2; RXP +The project soliciting the entry points needs not to have any dependency +or prior knowledge about the libraries implementing the entry points, and +downstream users are able to compose functionality by pulling together +libraries implementing the entry points. -.. code-block:: python - setup( - extras_require = { - "PDF": ["ReportLab>=1.2", "RXP"], - } - ) +Dependency Management +===================== - -And we only want them to be installed if the console script entry point -``rst2pdf`` is run: +Some entry points may require additional dependencies to properly function. +For such an entry point, declare in square brakets any number of dependency +``extras`` following the entry point definition. Such entry points will only +be viable if their extras were declared and installed. See the +:ref:`guide on dependencies management ` for +more information on defining extra requirements. Consider from the +above example:: .. code-block:: ini - [options] - entry_points = - ['console_script'] - rst2pdf = project_a.tools.pdfgen [PDF] - rst2html = project_a.tools.htmlgen - -.. code-block:: python + [options.entry_points] + console_scripts = + hello-world = timmins:hello_world [pretty-printer] - setup( - entry_points = """ - ['console_script'] - rst2pdf = project_a.tools.pdfgen [PDF] - rst2html = project_a.tools.htmlgen - """ - ) +In this case, the ``hello-world`` script is only viable if the ``pretty-printer`` +extra is indicated, and so a plugin host might exclude that entry point +(i.e. not install a console script) if the relevant extra dependencies are not +installed. -- cgit v1.2.1 From dbc968a808791a0cd494c4d993592e832d2e5fed Mon Sep 17 00:00:00 2001 From: alvy Date: Wed, 29 Jul 2020 21:41:20 -0400 Subject: docs: remove editorial message and lengthy description of dependency type --- docs/userguide/dependency_management.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.txt b/docs/userguide/dependency_management.txt index ca2ac75a..1c9cf638 100644 --- a/docs/userguide/dependency_management.txt +++ b/docs/userguide/dependency_management.txt @@ -2,10 +2,8 @@ Dependencies Management in Setuptools ===================================== -``Setuptools``'s dependency management is meticulous, or agonizing, depending -on your level of familiarity. There are three types of dependency styles. -1) those required to run the packaging program (build system requirement), -2) those your package depends on (required dependency) and 3) optional +There are three types of dependency styles offered by setuptools: +1) build system requirement, required dependency and 3) optional dependency. .. Note:: -- cgit v1.2.1 From 3268c199118dd5400e40b1afc401ea75a37dabb1 Mon Sep 17 00:00:00 2001 From: alvy Date: Wed, 29 Jul 2020 21:49:08 -0400 Subject: docs: reference PEP440 for versions specifiers --- docs/userguide/dependency_management.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.txt b/docs/userguide/dependency_management.txt index 1c9cf638..8bca4fd7 100644 --- a/docs/userguide/dependency_management.txt +++ b/docs/userguide/dependency_management.txt @@ -7,8 +7,9 @@ There are three types of dependency styles offered by setuptools: dependency. .. Note:: - For all the packages you intend to add to dependency, you can optionally - specify the version following :ref:`reference on version specifyer ` + Packages that are added to dependency can be optionally specified with the + version by following `PEP 440 `_ + .. contents:: -- cgit v1.2.1 From bd3d57dfe66bade541faf5573c14669f311a6e5c Mon Sep 17 00:00:00 2001 From: alvy Date: Wed, 29 Jul 2020 21:51:21 -0400 Subject: docs: give python requirement a dedicated section --- docs/userguide/dependency_management.txt | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.txt b/docs/userguide/dependency_management.txt index 8bca4fd7..97d3b662 100644 --- a/docs/userguide/dependency_management.txt +++ b/docs/userguide/dependency_management.txt @@ -40,14 +40,6 @@ other two types of dependency keyword, this one is specified in your deprecated practice (WIP)` -Python requirement ------------------- -In some cases, you might need to specify the minimum required python version. -This is handled with the ``python_requires`` keyword supplied to ``setup.cfg`` -or ``setup.py``. - -Example WIP - Declaring required dependency ============================= @@ -313,3 +305,12 @@ not need to change, but the right packages will still be installed if needed. 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). + + +Python requirement +================== +In some cases, you might need to specify the minimum required python version. +This is handled with the ``python_requires`` keyword supplied to ``setup.cfg`` +or ``setup.py``. + +Example WIP \ No newline at end of file -- cgit v1.2.1 From e716c1821969d07c8b629b15e1b0782a247b6b57 Mon Sep 17 00:00:00 2001 From: alvy Date: Wed, 29 Jul 2020 21:54:31 -0400 Subject: docs: remove mentioning of multiversion install --- docs/userguide/dependency_management.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.txt b/docs/userguide/dependency_management.txt index 97d3b662..b2be4177 100644 --- a/docs/userguide/dependency_management.txt +++ b/docs/userguide/dependency_management.txt @@ -70,9 +70,7 @@ finess to it, let's start with a simple example. When your project is installed (e.g. using pip), all of the dependencies not already installed will be located (via PyPI), downloaded, built (if necessary), and installed and 2) 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). +that verify the availability of the specified dependencies at runtime. .. note:: if you declare your dependencies in ``setup.py``, you do -- cgit v1.2.1 From 5df7ee405dc7455b842daa82989d199689d8650e Mon Sep 17 00:00:00 2001 From: alvy Date: Wed, 29 Jul 2020 21:56:08 -0400 Subject: docs: remove note on "require" functionality --- docs/userguide/dependency_management.txt | 6 ------ 1 file changed, 6 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.txt b/docs/userguide/dependency_management.txt index b2be4177..50f061c9 100644 --- a/docs/userguide/dependency_management.txt +++ b/docs/userguide/dependency_management.txt @@ -71,12 +71,6 @@ When your project is installed (e.g. using pip), all of the dependencies not already installed will be located (via PyPI), downloaded, built (if necessary), and installed and 2) Any scripts in your project will be installed with wrappers that verify the availability of the specified dependencies at runtime. - -.. note:: - 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. Platform specific dependencies -- cgit v1.2.1 From dee83be182df63d05f4a1d52639c61f34b64234f Mon Sep 17 00:00:00 2001 From: alvy Date: Wed, 29 Jul 2020 22:08:52 -0400 Subject: docs: rephrased the introduction for optional dependencies note the use case for tests and docs functions and that "test_require" is deprecated, shorten description of the example --- docs/userguide/dependency_management.txt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.txt b/docs/userguide/dependency_management.txt index 50f061c9..a26ab6c3 100644 --- a/docs/userguide/dependency_management.txt +++ b/docs/userguide/dependency_management.txt @@ -199,12 +199,16 @@ distributions, if the package's dependencies aren't already installed: Optional dependencies ===================== Setuptools allows you to declare dependencies that only get installed under -specific circumstances. For example, let's say that Project-A offers optional -PDF support and requires some additional package for it to work. Such a -dependency will be specified with ``extras_require`` keyword and they are only -installed if another package depends on it (either directly or indirectly). +specific circumstances. These dependencies are specified with ``extras_require`` +keyword and are only installed if another package depends on it (either +directly or indirectly) This makes it convenient to declare dependencies for +ancillary functions such as "tests" and "docs". -Let's first see how to specify such package: +.. note:: + ``tests_require`` is now deprecated + +For example, Package-A offers optional PDF support and requires two other +dependencies for it to work: .. code-block:: ini -- cgit v1.2.1 From 73e379cc55ac1e9ec63c4ac30b75ecc82418f513 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 23 Sep 2020 20:29:14 -0400 Subject: Use canonical extension for docs. --- docs/userguide/commands.rst | 566 +++++++++++++++++++++++++++++ docs/userguide/commands.txt | 566 ----------------------------- docs/userguide/datafiles.rst | 174 +++++++++ docs/userguide/datafiles.txt | 174 --------- docs/userguide/declarative_config.rst | 246 +++++++++++++ docs/userguide/declarative_config.txt | 246 ------------- docs/userguide/dependency_management.rst | 312 ++++++++++++++++ docs/userguide/dependency_management.txt | 312 ---------------- docs/userguide/development_mode.rst | 60 +++ docs/userguide/development_mode.txt | 60 --- docs/userguide/distribution.rst | 240 ++++++++++++ docs/userguide/distribution.txt | 240 ------------ docs/userguide/entry_point.rst | 154 ++++++++ docs/userguide/entry_point.txt | 154 -------- docs/userguide/extension.rst | 235 ++++++++++++ docs/userguide/extension.txt | 235 ------------ docs/userguide/functionalities_rewrite.rst | 9 + docs/userguide/functionalities_rewrite.txt | 9 - docs/userguide/index.rst | 26 ++ docs/userguide/index.txt | 26 -- docs/userguide/keywords.rst | 175 +++++++++ docs/userguide/keywords.txt | 175 --------- docs/userguide/miscellaneous.rst | 94 +++++ docs/userguide/miscellaneous.txt | 94 ----- docs/userguide/package_discovery.rst | 232 ++++++++++++ docs/userguide/package_discovery.txt | 232 ------------ docs/userguide/quickstart.rst | 210 +++++++++++ docs/userguide/quickstart.txt | 210 ----------- 28 files changed, 2733 insertions(+), 2733 deletions(-) create mode 100644 docs/userguide/commands.rst delete mode 100644 docs/userguide/commands.txt create mode 100644 docs/userguide/datafiles.rst delete mode 100644 docs/userguide/datafiles.txt create mode 100644 docs/userguide/declarative_config.rst delete mode 100644 docs/userguide/declarative_config.txt create mode 100644 docs/userguide/dependency_management.rst delete mode 100644 docs/userguide/dependency_management.txt create mode 100644 docs/userguide/development_mode.rst delete mode 100644 docs/userguide/development_mode.txt create mode 100644 docs/userguide/distribution.rst delete mode 100644 docs/userguide/distribution.txt create mode 100644 docs/userguide/entry_point.rst delete mode 100644 docs/userguide/entry_point.txt create mode 100644 docs/userguide/extension.rst delete mode 100644 docs/userguide/extension.txt create mode 100644 docs/userguide/functionalities_rewrite.rst delete mode 100644 docs/userguide/functionalities_rewrite.txt create mode 100644 docs/userguide/index.rst delete mode 100644 docs/userguide/index.txt create mode 100644 docs/userguide/keywords.rst delete mode 100644 docs/userguide/keywords.txt create mode 100644 docs/userguide/miscellaneous.rst delete mode 100644 docs/userguide/miscellaneous.txt create mode 100644 docs/userguide/package_discovery.rst delete mode 100644 docs/userguide/package_discovery.txt create mode 100644 docs/userguide/quickstart.rst delete mode 100644 docs/userguide/quickstart.txt (limited to 'docs/userguide') diff --git a/docs/userguide/commands.rst b/docs/userguide/commands.rst new file mode 100644 index 00000000..c64f62bf --- /dev/null +++ b/docs/userguide/commands.rst @@ -0,0 +1,566 @@ +----------------- +Command Reference +----------------- + +.. _alias: + +``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:: + + setup.py alias --global-config daily egg_info --tag-build=development + +Once the alias is defined, it can then be used with other setup commands, +e.g.:: + + 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-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:: + + 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.:: + + 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 +=================================================== + +.. warning:: + **eggs** are deprecated in favor of wheels, and not supported by pip. + +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: + +``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 any changes to the project's setup script or C extensions, +you should rerun the ``develop`` command against all relevant staging areas to +keep the project's scripts, metadata and extensions up-to-date. Most other +kinds of changes to your project should not require any build operations or +rerunning ``develop``, but keep in mind that even minor changes to the setup +script (e.g. changing an entry point definition) require you to re-run the +``develop`` or ``test`` commands to keep the distribution updated. + +Here are some of 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 pip 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 pip to install 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``. (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-path=DIR`` + Force the generated ``.egg-link`` file to use a specified relative path + to the source directory. This can be useful in circumstances where your + installation directory is being shared by code running under multiple + platforms (e.g. Mac and Windows) which have different absolute locations + for the code under development, but the same *relative* locations with + respect to the installation directory. If you use this option when + installing, you must supply the same relative path when uninstalling. + +In addition to the above options, the ``develop`` command also accepts all of +the same options accepted by ``easy_install``. If you've configured any +``easy_install`` settings in your ``setup.cfg`` (or other distutils config +files), the ``develop`` command will use them as defaults, unless you override +them in a ``[develop]`` section or on the command line. + + +.. _egg_info: + +``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 while executing other +commands. (It also generates the ``.egg-info/SOURCES.txt`` manifest file, which +is used when you are building source distributions.) + +In addition to writing the core egg metadata defined by ``setuptools`` and +required by ``pkg_resources``, this command can be extended to write other +metadata files as well, by defining entry points in the ``egg_info.writers`` +group. See the section on `Adding new EGG-INFO Files`_ below for more details. +Note that using additional metadata writers may require you to include a +``setup_requires`` argument to ``setup()`` in order to ensure that the desired +writers are available on ``sys.path``. + + +Release Tagging Options +----------------------- + +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 then use one or both of the following + options.) + + If you have a default build tag set in your ``setup.cfg``, you can suppress + it on the command line using ``-b ""`` or ``--tag-build=""`` as an argument + to the ``egg_info`` command. + +``--tag-date, -d`` + Add a date stamp of the form "-YYYYMMDD" (e.g. "-20050528") to the + project's version number. + +``--no-date, -D`` + Don't include a date stamp in the version number. This option is included + so you can override a default setting in ``setup.cfg``. + + +(Note: Because these options modify the version number used for source and +binary distributions of your project, you should first make sure that you know +how the resulting version numbers will be interpreted by automated tools +like pip. See the section above on `Specifying Your Project's Version`_ for an +explanation of pre- and post-release tags, as well as tips on how to choose and +verify a versioning scheme for your project.) + +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: + + +Other ``egg_info`` Options +-------------------------- + +``--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. + + +``egg_info`` Examples +--------------------- + +Creating a dated "nightly build" snapshot egg:: + + setup.py egg_info --tag-date --tag-build=DEV bdist_egg + +Creating a release with no version tags, even if some default tags are +specified in ``setup.cfg``:: + + setup.py egg_info -RDb "" sdist bdist_egg + +(Notice that ``egg_info`` must always appear on the command line *before* any +commands that you want the version changes to apply to.) + +.. _rotate: + +``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:: + + 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:: + + setup.py rotate --match=-py2.3*.egg,-py2.4*.egg --keep=1 + + +.. _saveopts: + +``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):: + + setup.py build --compiler=mingw32 saveopts + +The ``saveopts`` command saves all options for every command 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:: + + 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:: + + 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: + +``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):: + + 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):: + + 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: + +``test`` - Build package and run a unittest suite +================================================= + +.. warning:: + ``test`` is deprecated and will be removed in a future version. Users + looking for a generic test entry point independent of test runner are + encouraged to use `tox `_. + +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 +or package containing ``TestCase`` classes. If the named suite is a module, +and the module has an ``additional_tests()`` function, it is called and the +result (which must be a ``unittest.TestSuite``) is added to the tests to be +run. If the named suite is a package, any submodules and subpackages are +recursively added to the overall test suite. (Note: if your project specifies +a ``test_loader``, the rules for processing the chosen ``test_suite`` may +differ; see the :ref:`test_loader ` documentation for more details.) + +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.:: + + 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. + +New in 41.5.0: Deprecated the test command. + + +.. _upload: + +``upload`` - Upload source and/or egg distributions to PyPI +=========================================================== + +The ``upload`` command was deprecated in version 40.0 and removed in version +42.0. Use `twine `_ instead. + +For more information on the current best practices in uploading your packages +to PyPI, see the Python Packaging User Guide's "Packaging Python Projects" +tutorial specifically the section on `uploading the distribution archives +`_. diff --git a/docs/userguide/commands.txt b/docs/userguide/commands.txt deleted file mode 100644 index c64f62bf..00000000 --- a/docs/userguide/commands.txt +++ /dev/null @@ -1,566 +0,0 @@ ------------------ -Command Reference ------------------ - -.. _alias: - -``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:: - - setup.py alias --global-config daily egg_info --tag-build=development - -Once the alias is defined, it can then be used with other setup commands, -e.g.:: - - 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-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:: - - 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.:: - - 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 -=================================================== - -.. warning:: - **eggs** are deprecated in favor of wheels, and not supported by pip. - -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: - -``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 any changes to the project's setup script or C extensions, -you should rerun the ``develop`` command against all relevant staging areas to -keep the project's scripts, metadata and extensions up-to-date. Most other -kinds of changes to your project should not require any build operations or -rerunning ``develop``, but keep in mind that even minor changes to the setup -script (e.g. changing an entry point definition) require you to re-run the -``develop`` or ``test`` commands to keep the distribution updated. - -Here are some of 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 pip 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 pip to install 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``. (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-path=DIR`` - Force the generated ``.egg-link`` file to use a specified relative path - to the source directory. This can be useful in circumstances where your - installation directory is being shared by code running under multiple - platforms (e.g. Mac and Windows) which have different absolute locations - for the code under development, but the same *relative* locations with - respect to the installation directory. If you use this option when - installing, you must supply the same relative path when uninstalling. - -In addition to the above options, the ``develop`` command also accepts all of -the same options accepted by ``easy_install``. If you've configured any -``easy_install`` settings in your ``setup.cfg`` (or other distutils config -files), the ``develop`` command will use them as defaults, unless you override -them in a ``[develop]`` section or on the command line. - - -.. _egg_info: - -``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 while executing other -commands. (It also generates the ``.egg-info/SOURCES.txt`` manifest file, which -is used when you are building source distributions.) - -In addition to writing the core egg metadata defined by ``setuptools`` and -required by ``pkg_resources``, this command can be extended to write other -metadata files as well, by defining entry points in the ``egg_info.writers`` -group. See the section on `Adding new EGG-INFO Files`_ below for more details. -Note that using additional metadata writers may require you to include a -``setup_requires`` argument to ``setup()`` in order to ensure that the desired -writers are available on ``sys.path``. - - -Release Tagging Options ------------------------ - -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 then use one or both of the following - options.) - - If you have a default build tag set in your ``setup.cfg``, you can suppress - it on the command line using ``-b ""`` or ``--tag-build=""`` as an argument - to the ``egg_info`` command. - -``--tag-date, -d`` - Add a date stamp of the form "-YYYYMMDD" (e.g. "-20050528") to the - project's version number. - -``--no-date, -D`` - Don't include a date stamp in the version number. This option is included - so you can override a default setting in ``setup.cfg``. - - -(Note: Because these options modify the version number used for source and -binary distributions of your project, you should first make sure that you know -how the resulting version numbers will be interpreted by automated tools -like pip. See the section above on `Specifying Your Project's Version`_ for an -explanation of pre- and post-release tags, as well as tips on how to choose and -verify a versioning scheme for your project.) - -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: - - -Other ``egg_info`` Options --------------------------- - -``--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. - - -``egg_info`` Examples ---------------------- - -Creating a dated "nightly build" snapshot egg:: - - setup.py egg_info --tag-date --tag-build=DEV bdist_egg - -Creating a release with no version tags, even if some default tags are -specified in ``setup.cfg``:: - - setup.py egg_info -RDb "" sdist bdist_egg - -(Notice that ``egg_info`` must always appear on the command line *before* any -commands that you want the version changes to apply to.) - -.. _rotate: - -``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:: - - 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:: - - setup.py rotate --match=-py2.3*.egg,-py2.4*.egg --keep=1 - - -.. _saveopts: - -``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):: - - setup.py build --compiler=mingw32 saveopts - -The ``saveopts`` command saves all options for every command 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:: - - 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:: - - 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: - -``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):: - - 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):: - - 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: - -``test`` - Build package and run a unittest suite -================================================= - -.. warning:: - ``test`` is deprecated and will be removed in a future version. Users - looking for a generic test entry point independent of test runner are - encouraged to use `tox `_. - -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 -or package containing ``TestCase`` classes. If the named suite is a module, -and the module has an ``additional_tests()`` function, it is called and the -result (which must be a ``unittest.TestSuite``) is added to the tests to be -run. If the named suite is a package, any submodules and subpackages are -recursively added to the overall test suite. (Note: if your project specifies -a ``test_loader``, the rules for processing the chosen ``test_suite`` may -differ; see the :ref:`test_loader ` documentation for more details.) - -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.:: - - 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. - -New in 41.5.0: Deprecated the test command. - - -.. _upload: - -``upload`` - Upload source and/or egg distributions to PyPI -=========================================================== - -The ``upload`` command was deprecated in version 40.0 and removed in version -42.0. Use `twine `_ instead. - -For more information on the current best practices in uploading your packages -to PyPI, see the Python Packaging User Guide's "Packaging Python Projects" -tutorial specifically the section on `uploading the distribution archives -`_. diff --git a/docs/userguide/datafiles.rst b/docs/userguide/datafiles.rst new file mode 100644 index 00000000..315ec724 --- /dev/null +++ b/docs/userguide/datafiles.rst @@ -0,0 +1,174 @@ +==================== +Data Files Support +==================== + +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 offers three ways to specify data files to be included in your +packages. First, you can simply use the ``include_package_data`` keyword, +e.g.:: + + from setuptools import setup, find_packages + setup( + ... + include_package_data=True + ) + +This tells setuptools to install any data files it finds in your packages. +The data files must be specified via the distutils' ``MANIFEST.in`` file. +(They can also be tracked by a revision control system, using an appropriate +plugin. See the section below on `Adding Support for Revision Control +Systems`_ for information on how to write such plugins.) + +If you want finer-grained control over what files are included (for example, +if you have documentation files in your package directories and want to exclude +them from installation), then you can also use the ``package_data`` keyword, +e.g.:: + + 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:: + + setup.py + src/ + mypkg/ + __init__.py + mypkg.txt + data/ + somefile.dat + otherdata.dat + +The setuptools setup file might look like this:: + + 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. + +If datafiles are contained in a subdirectory of a package that isn't a package +itself (no ``__init__.py``), then the subdirectory names (or ``*``) are required +in the ``package_data`` argument (as shown above with ``"data/*.dat"``). + +When building an ``sdist``, the datafiles are also drawn from the +``package_name.egg-info/SOURCES.txt`` file, so make sure that this is removed if +the ``setup.py`` ``package_data`` list is updated before calling ``setup.py``. + +(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 `some documentation for the feature`__ available on the +python.org website. If using the setuptools-specific ``include_package_data`` +argument, files specified by ``package_data`` will *not* be automatically +added to the manifest unless they are listed in the MANIFEST.in file.) + +__ https://docs.python.org/3/distutils/setupscript.html#installing-package-data + +Sometimes, the ``include_package_data`` or ``package_data`` options alone +aren't sufficient to precisely define what files you want included. For +example, you may want to include package README files in your revision control +system and source distributions, but exclude them from being installed. So, +setuptools offers an ``exclude_package_data`` option as well, that allows you +to do things like this:: + + 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 + + include_package_data=True, # include everything in source control + + # ...but exclude README.txt from all packages + exclude_package_data={"": ["README.txt"]}, + ) + +The ``exclude_package_data`` option is a dictionary mapping package names to +lists of wildcard patterns, just like the ``package_data`` option. And, just +as with that option, a key of ``""`` will apply the given pattern(s) to all +packages. However, any files that match these patterns will be *excluded* +from installation, even if they were listed in ``package_data`` or were +included as a result of using ``include_package_data``. + +In summary, the three options allow you to: + +``include_package_data`` + Accept all data files and directories matched by ``MANIFEST.in``. + +``package_data`` + Specify additional patterns to match files that may or may + not be matched by ``MANIFEST.in`` or found in source control. + +``exclude_package_data`` + Specify patterns for data files and directories that should *not* be + included when a package is installed, even if they would otherwise have + been included due to the use of the preceding options. + +NOTE: Due to the way the distutils build process works, a data file that you +include in your project and then stop including may be "orphaned" in your +project's build directories, requiring you to run ``setup.py clean --all`` to +fully remove them. This may also be important for your users and contributors +if they track intermediate revisions of your project using Subversion; be sure +to let them know when you make changes that remove files from inclusion so they +can run ``setup.py clean --all``. + +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 :ref:`ResourceManager 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 `Importlib Resources`_ for +a quick example of converting code that uses ``__file__`` to use +``pkg_resources`` instead. + +.. _Importlib Resources: https://docs.python.org/3/library/importlib.html#module-importlib.resources + + +Non-Package Data Files +---------------------- + +Historically, ``setuptools`` by way of ``easy_install`` would encapsulate data +files from the distribution into the egg (see `the old docs +`_). As eggs are deprecated and pip-based installs +fall back to the platform-specific location for installing data files, there is +no supported facility to reliably retrieve these resources. + +Instead, the PyPA recommends that any data files you wish to be accessible at +run time be included in the package. \ No newline at end of file diff --git a/docs/userguide/datafiles.txt b/docs/userguide/datafiles.txt deleted file mode 100644 index 315ec724..00000000 --- a/docs/userguide/datafiles.txt +++ /dev/null @@ -1,174 +0,0 @@ -==================== -Data Files Support -==================== - -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 offers three ways to specify data files to be included in your -packages. First, you can simply use the ``include_package_data`` keyword, -e.g.:: - - from setuptools import setup, find_packages - setup( - ... - include_package_data=True - ) - -This tells setuptools to install any data files it finds in your packages. -The data files must be specified via the distutils' ``MANIFEST.in`` file. -(They can also be tracked by a revision control system, using an appropriate -plugin. See the section below on `Adding Support for Revision Control -Systems`_ for information on how to write such plugins.) - -If you want finer-grained control over what files are included (for example, -if you have documentation files in your package directories and want to exclude -them from installation), then you can also use the ``package_data`` keyword, -e.g.:: - - 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:: - - setup.py - src/ - mypkg/ - __init__.py - mypkg.txt - data/ - somefile.dat - otherdata.dat - -The setuptools setup file might look like this:: - - 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. - -If datafiles are contained in a subdirectory of a package that isn't a package -itself (no ``__init__.py``), then the subdirectory names (or ``*``) are required -in the ``package_data`` argument (as shown above with ``"data/*.dat"``). - -When building an ``sdist``, the datafiles are also drawn from the -``package_name.egg-info/SOURCES.txt`` file, so make sure that this is removed if -the ``setup.py`` ``package_data`` list is updated before calling ``setup.py``. - -(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 `some documentation for the feature`__ available on the -python.org website. If using the setuptools-specific ``include_package_data`` -argument, files specified by ``package_data`` will *not* be automatically -added to the manifest unless they are listed in the MANIFEST.in file.) - -__ https://docs.python.org/3/distutils/setupscript.html#installing-package-data - -Sometimes, the ``include_package_data`` or ``package_data`` options alone -aren't sufficient to precisely define what files you want included. For -example, you may want to include package README files in your revision control -system and source distributions, but exclude them from being installed. So, -setuptools offers an ``exclude_package_data`` option as well, that allows you -to do things like this:: - - 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 - - include_package_data=True, # include everything in source control - - # ...but exclude README.txt from all packages - exclude_package_data={"": ["README.txt"]}, - ) - -The ``exclude_package_data`` option is a dictionary mapping package names to -lists of wildcard patterns, just like the ``package_data`` option. And, just -as with that option, a key of ``""`` will apply the given pattern(s) to all -packages. However, any files that match these patterns will be *excluded* -from installation, even if they were listed in ``package_data`` or were -included as a result of using ``include_package_data``. - -In summary, the three options allow you to: - -``include_package_data`` - Accept all data files and directories matched by ``MANIFEST.in``. - -``package_data`` - Specify additional patterns to match files that may or may - not be matched by ``MANIFEST.in`` or found in source control. - -``exclude_package_data`` - Specify patterns for data files and directories that should *not* be - included when a package is installed, even if they would otherwise have - been included due to the use of the preceding options. - -NOTE: Due to the way the distutils build process works, a data file that you -include in your project and then stop including may be "orphaned" in your -project's build directories, requiring you to run ``setup.py clean --all`` to -fully remove them. This may also be important for your users and contributors -if they track intermediate revisions of your project using Subversion; be sure -to let them know when you make changes that remove files from inclusion so they -can run ``setup.py clean --all``. - -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 :ref:`ResourceManager 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 `Importlib Resources`_ for -a quick example of converting code that uses ``__file__`` to use -``pkg_resources`` instead. - -.. _Importlib Resources: https://docs.python.org/3/library/importlib.html#module-importlib.resources - - -Non-Package Data Files ----------------------- - -Historically, ``setuptools`` by way of ``easy_install`` would encapsulate data -files from the distribution into the egg (see `the old docs -`_). As eggs are deprecated and pip-based installs -fall back to the platform-specific location for installing data files, there is -no supported facility to reliably retrieve these resources. - -Instead, the PyPA recommends that any data files you wish to be accessible at -run time be included in the package. \ No newline at end of file diff --git a/docs/userguide/declarative_config.rst b/docs/userguide/declarative_config.rst new file mode 100644 index 00000000..51c897c4 --- /dev/null +++ b/docs/userguide/declarative_config.rst @@ -0,0 +1,246 @@ +----------------------------------------- +Configuring setup() using setup.cfg files +----------------------------------------- + +.. note:: New in 30.3.0 (8 Dec 2016). + +.. important:: + If compatibility with legacy builds (i.e. those not using the :pep:`517` + build API) is desired, a ``setup.py`` file containing a ``setup()`` function + call is still required even if your configuration resides in ``setup.cfg``. + +``Setuptools`` allows using configuration files (usually :file:`setup.cfg`) +to define a package’s metadata and other options that are normally supplied +to the ``setup()`` function (declarative config). + +This approach not only allows automation scenarios but also reduces +boilerplate code in some cases. + +.. note:: + + This implementation has limited compatibility with the distutils2-like + ``setup.cfg`` sections used by the ``pbr`` and ``d2to1`` packages. + + Namely: only metadata-related keys from ``metadata`` section are supported + (except for ``description-file``); keys from ``files``, ``entry_points`` + and ``backwards_compat`` are not supported. + + +.. code-block:: ini + + [metadata] + name = my_package + version = attr: src.VERSION + description = My package description + long_description = file: README.rst, CHANGELOG.rst, LICENSE.rst + keywords = one, two + license = BSD 3-Clause License + classifiers = + Framework :: Django + License :: OSI Approved :: BSD License + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.5 + + [options] + zip_safe = False + include_package_data = True + packages = find: + scripts = + bin/first.py + bin/second.py + install_requires = + requests + importlib; python_version == "2.6" + + [options.package_data] + * = *.txt, *.rst + hello = *.msg + + [options.extras_require] + pdf = ReportLab>=1.2; RXP + rest = docutils>=0.3; pack ==1.1, ==1.3 + + [options.packages.find] + exclude = + src.subpackage1 + src.subpackage2 + + [options.data_files] + /etc/my_package = + site.d/00_default.conf + host.d/00_default.conf + data = data/img/logo.png, data/svg/icon.svg + +Metadata and options are set in the config sections of the same name. + +* Keys are the same as the keyword arguments one provides to the ``setup()`` + function. + +* Complex values can be written comma-separated or placed one per line + in *dangling* config values. The following are equivalent: + + .. code-block:: ini + + [metadata] + keywords = one, two + + [metadata] + keywords = + one + two + +* In some cases, complex values can be provided in dedicated subsections for + clarity. + +* Some keys allow ``file:``, ``attr:``, ``find:``, and ``find_namespace:`` directives in + order to cover common usecases. + +* Unknown keys are ignored. + + +Using a ``src/`` layout +======================= + +One commonly used package configuration has all the module source code in a +subdirectory (often called the ``src/`` layout), like this:: + + ├── src + │   └── mypackage + │   ├── __init__.py + │   └── mod1.py + ├── setup.py + └── setup.cfg + +You can set up your ``setup.cfg`` to automatically find all your packages in +the subdirectory like this: + +.. code-block:: ini + + # This example contains just the necessary options for a src-layout, set up + # the rest of the file as described above. + + [options] + package_dir= + =src + packages=find: + + [options.packages.find] + where=src + +Specifying values +================= + +Some values are treated as simple strings, some allow more logic. + +Type names used below: + +* ``str`` - simple string +* ``list-comma`` - dangling list or string of comma-separated values +* ``list-semi`` - dangling list or string of semicolon-separated values +* ``bool`` - ``True`` is 1, yes, true +* ``dict`` - list-comma where keys are separated from values by ``=`` +* ``section`` - values are read from a dedicated (sub)section + + +Special directives: + +* ``attr:`` - Value is read from a module attribute. ``attr:`` supports + callables and iterables; unsupported types are cast using ``str()``. + + In order to support the common case of a literal value assigned to a variable + in a module containing (directly or indirectly) third-party imports, + ``attr:`` first tries to read the value from the module by examining the + module's AST. If that fails, ``attr:`` falls back to importing the module. + +* ``file:`` - Value is read from a list of files and then concatenated + + +.. note:: + The ``file:`` directive is sandboxed and won't reach anything outside + the directory containing ``setup.py``. + + +Metadata +-------- + +.. note:: + The aliases given below are supported for compatibility reasons, + but their use is not advised. + +============================== ================= ================= =============== ===== +Key Aliases Type Minimum Version Notes +============================== ================= ================= =============== ===== +name str +version attr:, file:, str 39.2.0 (1) +url home-page str +download_url download-url str +project_urls dict 38.3.0 +author str +author_email author-email str +maintainer str +maintainer_email maintainer-email str +classifiers classifier file:, list-comma +license str +license_file str +license_files list-comma +description summary file:, str +long_description long-description file:, str +long_description_content_type str 38.6.0 +keywords list-comma +platforms platform list-comma +provides list-comma +requires list-comma +obsoletes list-comma +============================== ================= ================= =============== ===== + +.. note:: + A version loaded using the ``file:`` directive must comply with PEP 440. + It is easy to accidentally put something other than a valid version + string in such a file, so validation is stricter in this case. + +Notes: +1. The `version` file attribute has only been supported since 39.2.0. + +Options +------- + +======================= =================================== =============== ===== +Key Type Minimum Version Notes +======================= =================================== =============== ===== +zip_safe bool +setup_requires list-semi +install_requires list-semi +extras_require section +python_requires str +entry_points file:, section +use_2to3 bool +use_2to3_fixers list-comma +use_2to3_exclude_fixers list-comma +convert_2to3_doctests list-comma +scripts list-comma +eager_resources list-comma +dependency_links list-comma +tests_require list-semi +include_package_data bool +packages find:, find_namespace:, list-comma +package_dir dict +package_data section (1) +exclude_package_data section +namespace_packages list-comma +py_modules list-comma +data_files dict 40.6.0 +======================= =================================== =============== ===== + +.. note:: + + **packages** - The ``find:`` and ``find_namespace:`` directive can be further configured + in a dedicated subsection ``options.packages.find``. This subsection + accepts the same keys as the `setuptools.find_packages` and the + `setuptools.find_namespace_packages` function: + ``where``, ``include``, and ``exclude``. + + **find_namespace directive** - The ``find_namespace:`` directive is supported since Python >=3.3. + +Notes: +1. In the `package_data` section, a key named with a single asterisk (`*`) +refers to all packages, in lieu of the empty string used in `setup.py`. diff --git a/docs/userguide/declarative_config.txt b/docs/userguide/declarative_config.txt deleted file mode 100644 index 51c897c4..00000000 --- a/docs/userguide/declarative_config.txt +++ /dev/null @@ -1,246 +0,0 @@ ------------------------------------------ -Configuring setup() using setup.cfg files ------------------------------------------ - -.. note:: New in 30.3.0 (8 Dec 2016). - -.. important:: - If compatibility with legacy builds (i.e. those not using the :pep:`517` - build API) is desired, a ``setup.py`` file containing a ``setup()`` function - call is still required even if your configuration resides in ``setup.cfg``. - -``Setuptools`` allows using configuration files (usually :file:`setup.cfg`) -to define a package’s metadata and other options that are normally supplied -to the ``setup()`` function (declarative config). - -This approach not only allows automation scenarios but also reduces -boilerplate code in some cases. - -.. note:: - - This implementation has limited compatibility with the distutils2-like - ``setup.cfg`` sections used by the ``pbr`` and ``d2to1`` packages. - - Namely: only metadata-related keys from ``metadata`` section are supported - (except for ``description-file``); keys from ``files``, ``entry_points`` - and ``backwards_compat`` are not supported. - - -.. code-block:: ini - - [metadata] - name = my_package - version = attr: src.VERSION - description = My package description - long_description = file: README.rst, CHANGELOG.rst, LICENSE.rst - keywords = one, two - license = BSD 3-Clause License - classifiers = - Framework :: Django - License :: OSI Approved :: BSD License - Programming Language :: Python :: 3 - Programming Language :: Python :: 3.5 - - [options] - zip_safe = False - include_package_data = True - packages = find: - scripts = - bin/first.py - bin/second.py - install_requires = - requests - importlib; python_version == "2.6" - - [options.package_data] - * = *.txt, *.rst - hello = *.msg - - [options.extras_require] - pdf = ReportLab>=1.2; RXP - rest = docutils>=0.3; pack ==1.1, ==1.3 - - [options.packages.find] - exclude = - src.subpackage1 - src.subpackage2 - - [options.data_files] - /etc/my_package = - site.d/00_default.conf - host.d/00_default.conf - data = data/img/logo.png, data/svg/icon.svg - -Metadata and options are set in the config sections of the same name. - -* Keys are the same as the keyword arguments one provides to the ``setup()`` - function. - -* Complex values can be written comma-separated or placed one per line - in *dangling* config values. The following are equivalent: - - .. code-block:: ini - - [metadata] - keywords = one, two - - [metadata] - keywords = - one - two - -* In some cases, complex values can be provided in dedicated subsections for - clarity. - -* Some keys allow ``file:``, ``attr:``, ``find:``, and ``find_namespace:`` directives in - order to cover common usecases. - -* Unknown keys are ignored. - - -Using a ``src/`` layout -======================= - -One commonly used package configuration has all the module source code in a -subdirectory (often called the ``src/`` layout), like this:: - - ├── src - │   └── mypackage - │   ├── __init__.py - │   └── mod1.py - ├── setup.py - └── setup.cfg - -You can set up your ``setup.cfg`` to automatically find all your packages in -the subdirectory like this: - -.. code-block:: ini - - # This example contains just the necessary options for a src-layout, set up - # the rest of the file as described above. - - [options] - package_dir= - =src - packages=find: - - [options.packages.find] - where=src - -Specifying values -================= - -Some values are treated as simple strings, some allow more logic. - -Type names used below: - -* ``str`` - simple string -* ``list-comma`` - dangling list or string of comma-separated values -* ``list-semi`` - dangling list or string of semicolon-separated values -* ``bool`` - ``True`` is 1, yes, true -* ``dict`` - list-comma where keys are separated from values by ``=`` -* ``section`` - values are read from a dedicated (sub)section - - -Special directives: - -* ``attr:`` - Value is read from a module attribute. ``attr:`` supports - callables and iterables; unsupported types are cast using ``str()``. - - In order to support the common case of a literal value assigned to a variable - in a module containing (directly or indirectly) third-party imports, - ``attr:`` first tries to read the value from the module by examining the - module's AST. If that fails, ``attr:`` falls back to importing the module. - -* ``file:`` - Value is read from a list of files and then concatenated - - -.. note:: - The ``file:`` directive is sandboxed and won't reach anything outside - the directory containing ``setup.py``. - - -Metadata --------- - -.. note:: - The aliases given below are supported for compatibility reasons, - but their use is not advised. - -============================== ================= ================= =============== ===== -Key Aliases Type Minimum Version Notes -============================== ================= ================= =============== ===== -name str -version attr:, file:, str 39.2.0 (1) -url home-page str -download_url download-url str -project_urls dict 38.3.0 -author str -author_email author-email str -maintainer str -maintainer_email maintainer-email str -classifiers classifier file:, list-comma -license str -license_file str -license_files list-comma -description summary file:, str -long_description long-description file:, str -long_description_content_type str 38.6.0 -keywords list-comma -platforms platform list-comma -provides list-comma -requires list-comma -obsoletes list-comma -============================== ================= ================= =============== ===== - -.. note:: - A version loaded using the ``file:`` directive must comply with PEP 440. - It is easy to accidentally put something other than a valid version - string in such a file, so validation is stricter in this case. - -Notes: -1. The `version` file attribute has only been supported since 39.2.0. - -Options -------- - -======================= =================================== =============== ===== -Key Type Minimum Version Notes -======================= =================================== =============== ===== -zip_safe bool -setup_requires list-semi -install_requires list-semi -extras_require section -python_requires str -entry_points file:, section -use_2to3 bool -use_2to3_fixers list-comma -use_2to3_exclude_fixers list-comma -convert_2to3_doctests list-comma -scripts list-comma -eager_resources list-comma -dependency_links list-comma -tests_require list-semi -include_package_data bool -packages find:, find_namespace:, list-comma -package_dir dict -package_data section (1) -exclude_package_data section -namespace_packages list-comma -py_modules list-comma -data_files dict 40.6.0 -======================= =================================== =============== ===== - -.. note:: - - **packages** - The ``find:`` and ``find_namespace:`` directive can be further configured - in a dedicated subsection ``options.packages.find``. This subsection - accepts the same keys as the `setuptools.find_packages` and the - `setuptools.find_namespace_packages` function: - ``where``, ``include``, and ``exclude``. - - **find_namespace directive** - The ``find_namespace:`` directive is supported since Python >=3.3. - -Notes: -1. In the `package_data` section, a key named with a single asterisk (`*`) -refers to all packages, in lieu of the empty string used in `setup.py`. diff --git a/docs/userguide/dependency_management.rst b/docs/userguide/dependency_management.rst new file mode 100644 index 00000000..a26ab6c3 --- /dev/null +++ b/docs/userguide/dependency_management.rst @@ -0,0 +1,312 @@ +===================================== +Dependencies Management in Setuptools +===================================== + +There are three types of dependency styles offered by setuptools: +1) build system requirement, required dependency and 3) optional +dependency. + +.. Note:: + Packages that are added to dependency can be optionally specified with the + version by following `PEP 440 `_ + + +.. contents:: + +Build system requirement +======================== + +Package requirement +------------------- +After organizing all the scripts and files and getting ready for packaging, +there needs to be a way to tell Python what programs it need to actually +do the packgaging (in our case, ``setuptools`` of course). Usually, +you also need the ``wheel`` package as well since it is recommended that you +upload a ``.whl`` file to PyPI alongside your ``.tar.gz`` file. Unlike the +other two types of dependency keyword, this one is specified in your +``pyproject.toml`` file (if you have forgot what this is, go to +:ref:`quickstart` or (WIP)): + +.. code-block:: ini + + [build-system] + requires = ["setuptools", "wheel"] + #... + +.. note:: + This used to be accomplished with the ``setup_requires`` keyword but is + now considered deprecated in favor of the PEP 517 style described above. + To peek into how this legacy keyword is used, consult our :ref:`guide on + deprecated practice (WIP)` + + + +Declaring required dependency +============================= +This is where a package declares its core dependencies, without which it won't +be able to run. ``setuptools`` support automatically download and install +these dependencies when the package is installed. Although there is more +finess to it, let's start with a simple example. + +.. code-block:: ini + + [options] + #... + install_requires = + docutils + BazSpam ==1.1 + +.. code-block:: python + + setup( + #..., + install_requires = [ + 'docutils', + 'BazSpam ==1.1' + ] + ) + + +When your project is installed (e.g. using pip), all of the dependencies not +already installed will be located (via PyPI), downloaded, built (if necessary), +and installed and 2) Any scripts in your project will be installed with wrappers +that verify the availability of the specified dependencies at runtime. + + +Platform specific dependencies +------------------------------ +Setuptools offer the capability to evaluate certain conditions before blindly +installing everything listed in ``install_requires``. This is great for platform +specific dependencies. For example, the ``enum`` package was added in Python +3.4, therefore, package that depends on it can elect to install it only when +the Python version is older than 3.4. To accomplish this + +.. code-block:: ini + + [options] + #... + install_requires = + enum34;python_version<'3.4' + +.. code-block:: python + + setup( + #... + install_requires=[ + "enum34;python_version<'3.4'",] + ) + +Similarly, if you also wish to declare ``pywin32`` with a minimal version of 1.0 +and only install it if the user is using a Windows operating system: + +.. code-block:: ini + + [options] + #... + install_requires = + enum34;python_version<'3.4' + pywin32 >= 1.0;platform_system=='Windows' + +.. code-block:: python + + setup( + #... + install_requires=[ + "enum34;python_version<'3.4'", + "pywin32 >= 1.0;platform_system=='Windows'" + ] + ) + +The environmental markers that may be used for testing platform types are +detailed in `PEP 508 `_. + + +Dependencies that aren't in PyPI +-------------------------------- +.. warning:: + Dependency links support has been dropped by pip starting with version + 19.0 (released 2019-01-22). + +If your project depends on packages that don't exist on PyPI, you may still be +able to depend on them, as long as they are available for download as: + +- an egg, in the standard distutils ``sdist`` format, +- a single ``.py`` file, or +- a VCS repository (Subversion, Mercurial, or Git). + +You just need to add some URLs to the ``dependency_links`` argument to +``setup()``. + +The URLs must be either: + +1. direct download URLs, +2. the URLs of web pages that contain direct download links, or +3. the repository's URL + +In general, it's better to link to web pages, because it is usually less +complex to update a web page than to release a new version of your project. +You can also use a SourceForge ``showfiles.php`` link in the case where a +package you depend on is distributed via SourceForge. + +If you depend on a package that's distributed as a single ``.py`` file, you +must include an ``"#egg=project-version"`` suffix to the URL, to give a project +name and version number. (Be sure to escape any dashes in the name or version +by replacing them with underscores.) EasyInstall will recognize this suffix +and automatically create a trivial ``setup.py`` to wrap the single ``.py`` file +as an egg. + +In the case of a VCS checkout, you should also append ``#egg=project-version`` +in order to identify for what package that checkout should be used. You can +append ``@REV`` to the URL's path (before the fragment) to specify a revision. +Additionally, you can also force the VCS being used by prepending the URL with +a certain prefix. Currently available are: + +- ``svn+URL`` for Subversion, +- ``git+URL`` for Git, and +- ``hg+URL`` for Mercurial + +A more complete example would be: + + ``vcs+proto://host/path@revision#egg=project-version`` + +Be careful with the version. It should match the one inside the project files. +If you want to disregard the version, you have to omit it both in the +``requires`` and in the URL's fragment. + +This will do a checkout (or a clone, in Git and Mercurial parlance) to a +temporary folder and run ``setup.py bdist_egg``. + +The ``dependency_links`` option takes the form of a list of URL strings. For +example, this will cause a search of the specified page for eggs or source +distributions, if the package's dependencies aren't already installed: + +.. code-block:: ini + + [options] + #... + dependency_links = http://peak.telecommunity.com/snapshots/ + +.. code-block:: python + + setup( + #... + dependency_links=[ + "http://peak.telecommunity.com/snapshots/" + ], + ) + + +Optional dependencies +===================== +Setuptools allows you to declare dependencies that only get installed under +specific circumstances. These dependencies are specified with ``extras_require`` +keyword and are only installed if another package depends on it (either +directly or indirectly) This makes it convenient to declare dependencies for +ancillary functions such as "tests" and "docs". + +.. note:: + ``tests_require`` is now deprecated + +For example, Package-A offers optional PDF support and requires two other +dependencies for it to work: + +.. code-block:: ini + + [metadata] + name = Package-A + + [options.extras_require] + PDF = ReportLab>=1.2; RXP + + +.. code-block:: python + + setup( + name="Project-A", + #... + extras_require={ + "PDF": ["ReportLab>=1.2", "RXP"], + } + ) + +The name ``PDF`` is an arbitary identifier of such a list of dependencies, to +which other components can refer and have them installed. There are two common +use cases. + +First is the console_scripts entry point: + +.. code-block:: ini + + [metadata] + name = Project A + #... + + [options] + #... + entry_points= + [console_scripts] + rst2pdf = project_a.tools.pdfgen [PDF] + rst2html = project_a.tools.htmlgen + +.. code-block:: python + + setup( + name = "Project-A" + #..., + entry_points={ + "console_scripts": [ + "rst2pdf = project_a.tools.pdfgen [PDF]", + "rst2html = project_a.tools.htmlgen", + ], + } + ) + +When the script ``rst2pdf`` is run, it will trigger the installation of +the two dependencies ``PDF`` maps to. + +The second use case is that other package can use this "extra" for their +own dependencies. For example, if "Project-B" needs "project A" with PDF support +installed, it might declare the dependency like this:: + +.. code-block:: ini + + [metadata] + name = Project-B + #... + + [options] + #... + install_requires = + Project-A[PDF] + +.. code-block:: 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. + +.. note:: + Best practice: 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). + + +Python requirement +================== +In some cases, you might need to specify the minimum required python version. +This is handled with the ``python_requires`` keyword supplied to ``setup.cfg`` +or ``setup.py``. + +Example WIP \ No newline at end of file diff --git a/docs/userguide/dependency_management.txt b/docs/userguide/dependency_management.txt deleted file mode 100644 index a26ab6c3..00000000 --- a/docs/userguide/dependency_management.txt +++ /dev/null @@ -1,312 +0,0 @@ -===================================== -Dependencies Management in Setuptools -===================================== - -There are three types of dependency styles offered by setuptools: -1) build system requirement, required dependency and 3) optional -dependency. - -.. Note:: - Packages that are added to dependency can be optionally specified with the - version by following `PEP 440 `_ - - -.. contents:: - -Build system requirement -======================== - -Package requirement -------------------- -After organizing all the scripts and files and getting ready for packaging, -there needs to be a way to tell Python what programs it need to actually -do the packgaging (in our case, ``setuptools`` of course). Usually, -you also need the ``wheel`` package as well since it is recommended that you -upload a ``.whl`` file to PyPI alongside your ``.tar.gz`` file. Unlike the -other two types of dependency keyword, this one is specified in your -``pyproject.toml`` file (if you have forgot what this is, go to -:ref:`quickstart` or (WIP)): - -.. code-block:: ini - - [build-system] - requires = ["setuptools", "wheel"] - #... - -.. note:: - This used to be accomplished with the ``setup_requires`` keyword but is - now considered deprecated in favor of the PEP 517 style described above. - To peek into how this legacy keyword is used, consult our :ref:`guide on - deprecated practice (WIP)` - - - -Declaring required dependency -============================= -This is where a package declares its core dependencies, without which it won't -be able to run. ``setuptools`` support automatically download and install -these dependencies when the package is installed. Although there is more -finess to it, let's start with a simple example. - -.. code-block:: ini - - [options] - #... - install_requires = - docutils - BazSpam ==1.1 - -.. code-block:: python - - setup( - #..., - install_requires = [ - 'docutils', - 'BazSpam ==1.1' - ] - ) - - -When your project is installed (e.g. using pip), all of the dependencies not -already installed will be located (via PyPI), downloaded, built (if necessary), -and installed and 2) Any scripts in your project will be installed with wrappers -that verify the availability of the specified dependencies at runtime. - - -Platform specific dependencies ------------------------------- -Setuptools offer the capability to evaluate certain conditions before blindly -installing everything listed in ``install_requires``. This is great for platform -specific dependencies. For example, the ``enum`` package was added in Python -3.4, therefore, package that depends on it can elect to install it only when -the Python version is older than 3.4. To accomplish this - -.. code-block:: ini - - [options] - #... - install_requires = - enum34;python_version<'3.4' - -.. code-block:: python - - setup( - #... - install_requires=[ - "enum34;python_version<'3.4'",] - ) - -Similarly, if you also wish to declare ``pywin32`` with a minimal version of 1.0 -and only install it if the user is using a Windows operating system: - -.. code-block:: ini - - [options] - #... - install_requires = - enum34;python_version<'3.4' - pywin32 >= 1.0;platform_system=='Windows' - -.. code-block:: python - - setup( - #... - install_requires=[ - "enum34;python_version<'3.4'", - "pywin32 >= 1.0;platform_system=='Windows'" - ] - ) - -The environmental markers that may be used for testing platform types are -detailed in `PEP 508 `_. - - -Dependencies that aren't in PyPI --------------------------------- -.. warning:: - Dependency links support has been dropped by pip starting with version - 19.0 (released 2019-01-22). - -If your project depends on packages that don't exist on PyPI, you may still be -able to depend on them, as long as they are available for download as: - -- an egg, in the standard distutils ``sdist`` format, -- a single ``.py`` file, or -- a VCS repository (Subversion, Mercurial, or Git). - -You just need to add some URLs to the ``dependency_links`` argument to -``setup()``. - -The URLs must be either: - -1. direct download URLs, -2. the URLs of web pages that contain direct download links, or -3. the repository's URL - -In general, it's better to link to web pages, because it is usually less -complex to update a web page than to release a new version of your project. -You can also use a SourceForge ``showfiles.php`` link in the case where a -package you depend on is distributed via SourceForge. - -If you depend on a package that's distributed as a single ``.py`` file, you -must include an ``"#egg=project-version"`` suffix to the URL, to give a project -name and version number. (Be sure to escape any dashes in the name or version -by replacing them with underscores.) EasyInstall will recognize this suffix -and automatically create a trivial ``setup.py`` to wrap the single ``.py`` file -as an egg. - -In the case of a VCS checkout, you should also append ``#egg=project-version`` -in order to identify for what package that checkout should be used. You can -append ``@REV`` to the URL's path (before the fragment) to specify a revision. -Additionally, you can also force the VCS being used by prepending the URL with -a certain prefix. Currently available are: - -- ``svn+URL`` for Subversion, -- ``git+URL`` for Git, and -- ``hg+URL`` for Mercurial - -A more complete example would be: - - ``vcs+proto://host/path@revision#egg=project-version`` - -Be careful with the version. It should match the one inside the project files. -If you want to disregard the version, you have to omit it both in the -``requires`` and in the URL's fragment. - -This will do a checkout (or a clone, in Git and Mercurial parlance) to a -temporary folder and run ``setup.py bdist_egg``. - -The ``dependency_links`` option takes the form of a list of URL strings. For -example, this will cause a search of the specified page for eggs or source -distributions, if the package's dependencies aren't already installed: - -.. code-block:: ini - - [options] - #... - dependency_links = http://peak.telecommunity.com/snapshots/ - -.. code-block:: python - - setup( - #... - dependency_links=[ - "http://peak.telecommunity.com/snapshots/" - ], - ) - - -Optional dependencies -===================== -Setuptools allows you to declare dependencies that only get installed under -specific circumstances. These dependencies are specified with ``extras_require`` -keyword and are only installed if another package depends on it (either -directly or indirectly) This makes it convenient to declare dependencies for -ancillary functions such as "tests" and "docs". - -.. note:: - ``tests_require`` is now deprecated - -For example, Package-A offers optional PDF support and requires two other -dependencies for it to work: - -.. code-block:: ini - - [metadata] - name = Package-A - - [options.extras_require] - PDF = ReportLab>=1.2; RXP - - -.. code-block:: python - - setup( - name="Project-A", - #... - extras_require={ - "PDF": ["ReportLab>=1.2", "RXP"], - } - ) - -The name ``PDF`` is an arbitary identifier of such a list of dependencies, to -which other components can refer and have them installed. There are two common -use cases. - -First is the console_scripts entry point: - -.. code-block:: ini - - [metadata] - name = Project A - #... - - [options] - #... - entry_points= - [console_scripts] - rst2pdf = project_a.tools.pdfgen [PDF] - rst2html = project_a.tools.htmlgen - -.. code-block:: python - - setup( - name = "Project-A" - #..., - entry_points={ - "console_scripts": [ - "rst2pdf = project_a.tools.pdfgen [PDF]", - "rst2html = project_a.tools.htmlgen", - ], - } - ) - -When the script ``rst2pdf`` is run, it will trigger the installation of -the two dependencies ``PDF`` maps to. - -The second use case is that other package can use this "extra" for their -own dependencies. For example, if "Project-B" needs "project A" with PDF support -installed, it might declare the dependency like this:: - -.. code-block:: ini - - [metadata] - name = Project-B - #... - - [options] - #... - install_requires = - Project-A[PDF] - -.. code-block:: 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. - -.. note:: - Best practice: 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). - - -Python requirement -================== -In some cases, you might need to specify the minimum required python version. -This is handled with the ``python_requires`` keyword supplied to ``setup.cfg`` -or ``setup.py``. - -Example WIP \ No newline at end of file diff --git a/docs/userguide/development_mode.rst b/docs/userguide/development_mode.rst new file mode 100644 index 00000000..9d4e7581 --- /dev/null +++ b/docs/userguide/development_mode.rst @@ -0,0 +1,60 @@ +"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``, 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. + +If you have enabled the ``use_2to3`` flag, then of course the ``.egg-link`` +will not link directly to your source code when run under Python 3, since +that source code would be made for Python 2 and not work under Python 3. +Instead the ``setup.py develop`` will build Python 3 code under the ``build`` +directory, and link there. This means that after doing code changes you will +have to run ``setup.py build`` before these changes are picked up by your +Python 3 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. + +Note that you can also apply setuptools commands to non-setuptools projects, +using commands like this:: + + python -c "import setuptools; with open('setup.py') as f: exec(compile(f.read(), 'setup.py', 'exec'))" develop + +That is, you can simply list the normal setup commands and options following +the quoted part. \ No newline at end of file diff --git a/docs/userguide/development_mode.txt b/docs/userguide/development_mode.txt deleted file mode 100644 index 9d4e7581..00000000 --- a/docs/userguide/development_mode.txt +++ /dev/null @@ -1,60 +0,0 @@ -"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``, 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. - -If you have enabled the ``use_2to3`` flag, then of course the ``.egg-link`` -will not link directly to your source code when run under Python 3, since -that source code would be made for Python 2 and not work under Python 3. -Instead the ``setup.py develop`` will build Python 3 code under the ``build`` -directory, and link there. This means that after doing code changes you will -have to run ``setup.py build`` before these changes are picked up by your -Python 3 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. - -Note that you can also apply setuptools commands to non-setuptools projects, -using commands like this:: - - python -c "import setuptools; with open('setup.py') as f: exec(compile(f.read(), 'setup.py', 'exec'))" develop - -That is, you can simply list the normal setup commands and options following -the quoted part. \ No newline at end of file diff --git a/docs/userguide/distribution.rst b/docs/userguide/distribution.rst new file mode 100644 index 00000000..77ea2660 --- /dev/null +++ b/docs/userguide/distribution.rst @@ -0,0 +1,240 @@ +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: + +* A manually-specified pre-release tag, such as "build" or "dev", or a + manually-specified post-release tag, such as a build or revision number + (``--tag-build=STRING, -bSTRING``) + +* An 8-character representation of the build date (``--tag-date, -d``), as + a postrelease tag + +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, before you release your project, be sure to see the section above on +`Specifying Your Project's Version`_ for more information about how pre- and +post-release tags affect how version numbers are interpreted. This is +important in order to make sure that dependency processing tools will know +which versions of your project are newer than others.) + +Finally, 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:: + + 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 script or 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 with pluggable endpoints for looking up files to include. If you are +using a revision control system, and your source distributions only need to +include files that you're tracking in revision control, use a corresponding +plugin instead of writing a ``MANIFEST.in`` file. See the section below on +`Adding Support for Revision Control Systems`_ for information on plugins. + +If you need to include automatically generated files, or files that are kept in +an unsupported revision control system, you'll need to create a ``MANIFEST.in`` +file to specify any files that the default file location algorithm doesn't +catch. See the distutils documentation for more information on the format of +the ``MANIFEST.in`` file. + +But, be sure to ignore any part of the distutils documentation that deals with +``MANIFEST`` or how it's generated from ``MANIFEST.in``; setuptools shields you +from these issues and doesn't work the same way in any case. Unlike the +distutils, setuptools regenerates the source distribution manifest file +every time you build a source distribution, and it builds it inside the +project's ``.egg-info`` directory, out of the way of your main project +directory. You therefore need not worry about whether it is up-to-date or not. + +Indeed, because setuptools' approach to determining the contents of a source +distribution is so much simpler, its ``sdist`` command omits nearly all of +the options that the distutils' more complex ``sdist`` process requires. For +all practical purposes, you'll probably use only the ``--formats`` option, if +you use any option at all. + + +Making "Official" (Non-Snapshot) Releases +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When you make an official release, creating source or binary distributions, +you will need to override the tag settings from ``setup.cfg``, so that you +don't end up registering versions like ``foobar-0.7a1.dev-r34832``. This is +easy to do if you are developing on the trunk and using tags or branches for +your releases - just make the change to ``setup.cfg`` after branching or +tagging the release, so the trunk will still produce development snapshots. + +Alternately, if you are not branching for releases, you can override the +default version options on the command line, using something like:: + + setup.py egg_info -Db "" sdist bdist_egg + +The first part of this command (``egg_info -Db ""``) will override the +configured tag information, before creating source and binary eggs. Thus, these +commands will use the plain version from your ``setup.py``, without adding the +build designation string. + +Of course, if you will be doing this a lot, you may wish to create a personal +alias for this operation, e.g.:: + + setup.py alias -u release egg_info -Db "" + +You can then use it like this:: + + setup.py release sdist bdist_egg + +Or of course you can create more elaborate aliases that do all of the above. +See the sections below on the `egg_info`_ and `alias`_ commands for more ideas. + +Distributing Extensions compiled with Cython +-------------------------------------------- + +``setuptools`` will detect at build time whether Cython is installed or not. +If Cython is not found ``setuptools`` will ignore pyx files. + +To ensure Cython is available, include Cython in the build-requires section +of your pyproject.toml:: + + [build-system] + requires=[..., "cython"] + +Built with pip 10 or later, that declaration is sufficient to include Cython +in the build. For broader compatibility, declare the dependency in your +setup-requires of setup.cfg:: + + [options] + setup_requires = + ... + cython + +As long as Cython is present in the build environment, ``setuptools`` includes +transparent support for building Cython extensions, as +long as extensions are defined using ``setuptools.Extension``. + +If you follow these rules, you can safely list ``.pyx`` files as the source +of your ``Extension`` objects in the setup script. If it is, then ``setuptools`` +will use it. + +Of course, for this to work, your source distributions must include the C +code generated by Cython, 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 a revision +control system will be able to build it even if they don't have Cython +installed, and that your source releases will be similarly usable with or +without Cython. + +Specifying Your Project's Version +--------------------------------- + +Setuptools can work well with most versioning schemes; there are, however, a +few special things to watch out for, in order to ensure that setuptools and +other tools can always tell what version of your package is newer than another +version. Knowing these things will also help you correctly specify what +versions of other projects your project depends on. + +A version consists of an alternating series of release numbers and pre-release +or post-release tags. A release number is a series of digits punctuated by +dots, such as ``2.4`` or ``0.5``. Each series of digits is treated +numerically, so releases ``2.1`` and ``2.1.0`` are different ways to spell the +same release number, denoting the first subrelease of release 2. But ``2.10`` +is the *tenth* subrelease of release 2, and so is a different and newer release +from ``2.1`` or ``2.1.0``. Leading zeros within a series of digits are also +ignored, so ``2.01`` is the same as ``2.1``, and different from ``2.0.1``. + +Following a release number, you can have either a pre-release or post-release +tag. Pre-release tags make a version be considered *older* than the version +they are appended to. So, revision ``2.4`` is *newer* than revision ``2.4c1``, +which in turn is newer than ``2.4b1`` or ``2.4a1``. Postrelease tags make +a version be considered *newer* than the version they are appended to. So, +revisions like ``2.4-1`` and ``2.4pl3`` are newer than ``2.4``, but are *older* +than ``2.4.1`` (which has a higher release number). + +A pre-release tag is a series of letters that are alphabetically before +"final". Some examples of prerelease tags would include ``alpha``, ``beta``, +``a``, ``c``, ``dev``, and so on. You do not have to place a dot or dash +before the prerelease tag if it's immediately after a number, but it's okay to +do so if you prefer. Thus, ``2.4c1`` and ``2.4.c1`` and ``2.4-c1`` all +represent release candidate 1 of version ``2.4``, and are treated as identical +by setuptools. + +In addition, there are three special prerelease tags that are treated as if +they were the letter ``c``: ``pre``, ``preview``, and ``rc``. So, version +``2.4rc1``, ``2.4pre1`` and ``2.4preview1`` are all the exact same version as +``2.4c1``, and are treated as identical by setuptools. + +A post-release tag is either a series of letters that are alphabetically +greater than or equal to "final", or a dash (``-``). Post-release tags are +generally used to separate patch numbers, port numbers, build numbers, revision +numbers, or date stamps from the release number. For example, the version +``2.4-r1263`` might denote Subversion revision 1263 of a post-release patch of +version ``2.4``. Or you might use ``2.4-20051127`` to denote a date-stamped +post-release. + +Notice that after each pre or post-release tag, you are free to place another +release number, followed again by more pre- or post-release tags. For example, +``0.6a9.dev-r41475`` could denote Subversion revision 41475 of the in- +development version of the ninth alpha of release 0.6. Notice that ``dev`` is +a pre-release tag, so this version is a *lower* version number than ``0.6a9``, +which would be the actual ninth alpha of release 0.6. But the ``-r41475`` is +a post-release tag, so this version is *newer* than ``0.6a9.dev``. + +For the most part, setuptools' interpretation of version numbers is intuitive, +but here are a few tips that will keep you out of trouble in the corner cases: + +* Don't stick adjoining pre-release tags together without a dot or number + between them. Version ``1.9adev`` is the ``adev`` prerelease of ``1.9``, + *not* a development pre-release of ``1.9a``. Use ``.dev`` instead, as in + ``1.9a.dev``, or separate the prerelease tags with a number, as in + ``1.9a0dev``. ``1.9a.dev``, ``1.9a0dev``, and even ``1.9.a.dev`` are + identical versions from setuptools' point of view, so you can use whatever + scheme you prefer. + +* If you want to be certain that your chosen numbering scheme works the way + you think it will, you can use the ``pkg_resources.parse_version()`` function + to compare different version numbers:: + + >>> from pkg_resources import parse_version + >>> parse_version("1.9.a.dev") == parse_version("1.9a0dev") + True + >>> parse_version("2.1-rc2") < parse_version("2.1") + True + >>> parse_version("0.6a9dev-r41475") < parse_version("0.6a9") + True + +Once you've decided on a version numbering scheme for your project, you can +have setuptools automatically tag your in-development releases with various +pre- or post-release tags. See the following sections for more details: + +* `Tagging and "Daily Build" or "Snapshot" Releases`_ +* The `egg_info`_ command \ No newline at end of file diff --git a/docs/userguide/distribution.txt b/docs/userguide/distribution.txt deleted file mode 100644 index 77ea2660..00000000 --- a/docs/userguide/distribution.txt +++ /dev/null @@ -1,240 +0,0 @@ -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: - -* A manually-specified pre-release tag, such as "build" or "dev", or a - manually-specified post-release tag, such as a build or revision number - (``--tag-build=STRING, -bSTRING``) - -* An 8-character representation of the build date (``--tag-date, -d``), as - a postrelease tag - -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, before you release your project, be sure to see the section above on -`Specifying Your Project's Version`_ for more information about how pre- and -post-release tags affect how version numbers are interpreted. This is -important in order to make sure that dependency processing tools will know -which versions of your project are newer than others.) - -Finally, 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:: - - 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 script or 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 with pluggable endpoints for looking up files to include. If you are -using a revision control system, and your source distributions only need to -include files that you're tracking in revision control, use a corresponding -plugin instead of writing a ``MANIFEST.in`` file. See the section below on -`Adding Support for Revision Control Systems`_ for information on plugins. - -If you need to include automatically generated files, or files that are kept in -an unsupported revision control system, you'll need to create a ``MANIFEST.in`` -file to specify any files that the default file location algorithm doesn't -catch. See the distutils documentation for more information on the format of -the ``MANIFEST.in`` file. - -But, be sure to ignore any part of the distutils documentation that deals with -``MANIFEST`` or how it's generated from ``MANIFEST.in``; setuptools shields you -from these issues and doesn't work the same way in any case. Unlike the -distutils, setuptools regenerates the source distribution manifest file -every time you build a source distribution, and it builds it inside the -project's ``.egg-info`` directory, out of the way of your main project -directory. You therefore need not worry about whether it is up-to-date or not. - -Indeed, because setuptools' approach to determining the contents of a source -distribution is so much simpler, its ``sdist`` command omits nearly all of -the options that the distutils' more complex ``sdist`` process requires. For -all practical purposes, you'll probably use only the ``--formats`` option, if -you use any option at all. - - -Making "Official" (Non-Snapshot) Releases -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -When you make an official release, creating source or binary distributions, -you will need to override the tag settings from ``setup.cfg``, so that you -don't end up registering versions like ``foobar-0.7a1.dev-r34832``. This is -easy to do if you are developing on the trunk and using tags or branches for -your releases - just make the change to ``setup.cfg`` after branching or -tagging the release, so the trunk will still produce development snapshots. - -Alternately, if you are not branching for releases, you can override the -default version options on the command line, using something like:: - - setup.py egg_info -Db "" sdist bdist_egg - -The first part of this command (``egg_info -Db ""``) will override the -configured tag information, before creating source and binary eggs. Thus, these -commands will use the plain version from your ``setup.py``, without adding the -build designation string. - -Of course, if you will be doing this a lot, you may wish to create a personal -alias for this operation, e.g.:: - - setup.py alias -u release egg_info -Db "" - -You can then use it like this:: - - setup.py release sdist bdist_egg - -Or of course you can create more elaborate aliases that do all of the above. -See the sections below on the `egg_info`_ and `alias`_ commands for more ideas. - -Distributing Extensions compiled with Cython --------------------------------------------- - -``setuptools`` will detect at build time whether Cython is installed or not. -If Cython is not found ``setuptools`` will ignore pyx files. - -To ensure Cython is available, include Cython in the build-requires section -of your pyproject.toml:: - - [build-system] - requires=[..., "cython"] - -Built with pip 10 or later, that declaration is sufficient to include Cython -in the build. For broader compatibility, declare the dependency in your -setup-requires of setup.cfg:: - - [options] - setup_requires = - ... - cython - -As long as Cython is present in the build environment, ``setuptools`` includes -transparent support for building Cython extensions, as -long as extensions are defined using ``setuptools.Extension``. - -If you follow these rules, you can safely list ``.pyx`` files as the source -of your ``Extension`` objects in the setup script. If it is, then ``setuptools`` -will use it. - -Of course, for this to work, your source distributions must include the C -code generated by Cython, 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 a revision -control system will be able to build it even if they don't have Cython -installed, and that your source releases will be similarly usable with or -without Cython. - -Specifying Your Project's Version ---------------------------------- - -Setuptools can work well with most versioning schemes; there are, however, a -few special things to watch out for, in order to ensure that setuptools and -other tools can always tell what version of your package is newer than another -version. Knowing these things will also help you correctly specify what -versions of other projects your project depends on. - -A version consists of an alternating series of release numbers and pre-release -or post-release tags. A release number is a series of digits punctuated by -dots, such as ``2.4`` or ``0.5``. Each series of digits is treated -numerically, so releases ``2.1`` and ``2.1.0`` are different ways to spell the -same release number, denoting the first subrelease of release 2. But ``2.10`` -is the *tenth* subrelease of release 2, and so is a different and newer release -from ``2.1`` or ``2.1.0``. Leading zeros within a series of digits are also -ignored, so ``2.01`` is the same as ``2.1``, and different from ``2.0.1``. - -Following a release number, you can have either a pre-release or post-release -tag. Pre-release tags make a version be considered *older* than the version -they are appended to. So, revision ``2.4`` is *newer* than revision ``2.4c1``, -which in turn is newer than ``2.4b1`` or ``2.4a1``. Postrelease tags make -a version be considered *newer* than the version they are appended to. So, -revisions like ``2.4-1`` and ``2.4pl3`` are newer than ``2.4``, but are *older* -than ``2.4.1`` (which has a higher release number). - -A pre-release tag is a series of letters that are alphabetically before -"final". Some examples of prerelease tags would include ``alpha``, ``beta``, -``a``, ``c``, ``dev``, and so on. You do not have to place a dot or dash -before the prerelease tag if it's immediately after a number, but it's okay to -do so if you prefer. Thus, ``2.4c1`` and ``2.4.c1`` and ``2.4-c1`` all -represent release candidate 1 of version ``2.4``, and are treated as identical -by setuptools. - -In addition, there are three special prerelease tags that are treated as if -they were the letter ``c``: ``pre``, ``preview``, and ``rc``. So, version -``2.4rc1``, ``2.4pre1`` and ``2.4preview1`` are all the exact same version as -``2.4c1``, and are treated as identical by setuptools. - -A post-release tag is either a series of letters that are alphabetically -greater than or equal to "final", or a dash (``-``). Post-release tags are -generally used to separate patch numbers, port numbers, build numbers, revision -numbers, or date stamps from the release number. For example, the version -``2.4-r1263`` might denote Subversion revision 1263 of a post-release patch of -version ``2.4``. Or you might use ``2.4-20051127`` to denote a date-stamped -post-release. - -Notice that after each pre or post-release tag, you are free to place another -release number, followed again by more pre- or post-release tags. For example, -``0.6a9.dev-r41475`` could denote Subversion revision 41475 of the in- -development version of the ninth alpha of release 0.6. Notice that ``dev`` is -a pre-release tag, so this version is a *lower* version number than ``0.6a9``, -which would be the actual ninth alpha of release 0.6. But the ``-r41475`` is -a post-release tag, so this version is *newer* than ``0.6a9.dev``. - -For the most part, setuptools' interpretation of version numbers is intuitive, -but here are a few tips that will keep you out of trouble in the corner cases: - -* Don't stick adjoining pre-release tags together without a dot or number - between them. Version ``1.9adev`` is the ``adev`` prerelease of ``1.9``, - *not* a development pre-release of ``1.9a``. Use ``.dev`` instead, as in - ``1.9a.dev``, or separate the prerelease tags with a number, as in - ``1.9a0dev``. ``1.9a.dev``, ``1.9a0dev``, and even ``1.9.a.dev`` are - identical versions from setuptools' point of view, so you can use whatever - scheme you prefer. - -* If you want to be certain that your chosen numbering scheme works the way - you think it will, you can use the ``pkg_resources.parse_version()`` function - to compare different version numbers:: - - >>> from pkg_resources import parse_version - >>> parse_version("1.9.a.dev") == parse_version("1.9a0dev") - True - >>> parse_version("2.1-rc2") < parse_version("2.1") - True - >>> parse_version("0.6a9dev-r41475") < parse_version("0.6a9") - True - -Once you've decided on a version numbering scheme for your project, you can -have setuptools automatically tag your in-development releases with various -pre- or post-release tags. See the following sections for more details: - -* `Tagging and "Daily Build" or "Snapshot" Releases`_ -* The `egg_info`_ command \ No newline at end of file diff --git a/docs/userguide/entry_point.rst b/docs/userguide/entry_point.rst new file mode 100644 index 00000000..7f5165a8 --- /dev/null +++ b/docs/userguide/entry_point.rst @@ -0,0 +1,154 @@ +.. _`entry_points`: + +============ +Entry Points +============ + +Packages may provide commands to be run at the console (console scripts), +such as the ``pip`` command. These commands are defined for a package +as a specific kind of entry point in the ``setup.cfg`` or +``setup.py``. + + +Console Scripts +=============== + +First consider an example without entry points. Imagine a package +defined thus:: + +.. code-block:: bash + + timmins/ + timmins/__init__.py + timmins/__main__.py + setup.cfg # or setup.py + #other necessary files + +with ``__init__.py`` as: + +.. code-block:: python + + def helloworld(): + print("Hello world") + +and ``__main__.py`` providing a hook: + + from . import hello_world + if __name__ == '__main__': + hello_world() + +After installing the package, the function may be invoked through the +`runpy `_ module:: + +.. code-block:: bash + + python -m timmins + +Adding a console script entry point allows the package to define a +user-friendly name for installers of the package to execute. Installers +like pip will create wrapper scripts to execute a function. In the +above example, to create a command ``hello-world`` that invokes +``timmins.hello_world``, add a console script entry point to +``setup.cfg``:: + +.. code-block:: ini + + [options.entry_points] + console_scripts = + hello-world = timmins:hello_world + +After installing the package, a user may invoke that function by simply calling +``hello-world`` on the command line. + +The syntax for entry points is specified as follows: + +.. code-block:: + + = [.[.]][:.] + +where ``name`` is the name for the script you want to create, the left hand +side of ``:`` is the module that contains your function and the right hand +side is the object you want to invoke (e.g. a function). + +In addition to ``console_scripts``, Setuptools supports ``gui_scripts``, which +will launch a GUI application without running in a terminal window. + + +Advertising Behavior +==================== + +Console scripts are one use of the more general concept of entry points. Entry +points more generally allow a packager to advertise behavior for discovery by +other libraries and applications. This feature enables "plug-in"-like +functionality, where one library solicits entry points and any number of other +libraries provide those entry points. + +A good example of this plug-in behavior can be seen in +`pytest plugins `_, +where pytest is a test framework that allows other libraries to extend +or modify its functionality through the ``pytest11`` entry point. + +The console scripts work similarly, where libraries advertise their commands +and tools like ``pip`` create wrapper scripts that invoke those commands. + +For a project wishing to solicit entry points, Setuptools recommends the +`importlib.metadata `_ +module (part of stdlib since Python 3.8) or its backport, +`importlib_metadata `_. + +For example, to find the console script entry points from the example above:: + +.. code-block:: python + + >>> from importlib import metadata + >>> eps = metadata.entry_points()['console_scripts'] + +``eps`` is now a list of ``EntryPoint`` objects, one of which corresponds +to the ``hello-world = timmins:hello_world`` defined above. Each ``EntryPoint`` +contains the ``name``, ``group``, and ``value``. It also supplies a ``.load()`` +method to import and load that entry point (module or object). + +.. code-block:: ini + + [options.entry_points] + my.plugins = + hello-world = timmins:hello_world + +Then, a different project wishing to load 'my.plugins' plugins could run +the following routine to load (and invoke) such plugins:: + +.. code-block:: python + + >>> from importlib import metadata + >>> eps = metadata.entry_points()['my.plugins'] + >>> for ep in eps: + ... plugin = ep.load() + ... plugin() + +The project soliciting the entry points needs not to have any dependency +or prior knowledge about the libraries implementing the entry points, and +downstream users are able to compose functionality by pulling together +libraries implementing the entry points. + + +Dependency Management +===================== + +Some entry points may require additional dependencies to properly function. +For such an entry point, declare in square brakets any number of dependency +``extras`` following the entry point definition. Such entry points will only +be viable if their extras were declared and installed. See the +:ref:`guide on dependencies management ` for +more information on defining extra requirements. Consider from the +above example:: + +.. code-block:: ini + + [options.entry_points] + console_scripts = + hello-world = timmins:hello_world [pretty-printer] + +In this case, the ``hello-world`` script is only viable if the ``pretty-printer`` +extra is indicated, and so a plugin host might exclude that entry point +(i.e. not install a console script) if the relevant extra dependencies are not +installed. diff --git a/docs/userguide/entry_point.txt b/docs/userguide/entry_point.txt deleted file mode 100644 index 7f5165a8..00000000 --- a/docs/userguide/entry_point.txt +++ /dev/null @@ -1,154 +0,0 @@ -.. _`entry_points`: - -============ -Entry Points -============ - -Packages may provide commands to be run at the console (console scripts), -such as the ``pip`` command. These commands are defined for a package -as a specific kind of entry point in the ``setup.cfg`` or -``setup.py``. - - -Console Scripts -=============== - -First consider an example without entry points. Imagine a package -defined thus:: - -.. code-block:: bash - - timmins/ - timmins/__init__.py - timmins/__main__.py - setup.cfg # or setup.py - #other necessary files - -with ``__init__.py`` as: - -.. code-block:: python - - def helloworld(): - print("Hello world") - -and ``__main__.py`` providing a hook: - - from . import hello_world - if __name__ == '__main__': - hello_world() - -After installing the package, the function may be invoked through the -`runpy `_ module:: - -.. code-block:: bash - - python -m timmins - -Adding a console script entry point allows the package to define a -user-friendly name for installers of the package to execute. Installers -like pip will create wrapper scripts to execute a function. In the -above example, to create a command ``hello-world`` that invokes -``timmins.hello_world``, add a console script entry point to -``setup.cfg``:: - -.. code-block:: ini - - [options.entry_points] - console_scripts = - hello-world = timmins:hello_world - -After installing the package, a user may invoke that function by simply calling -``hello-world`` on the command line. - -The syntax for entry points is specified as follows: - -.. code-block:: - - = [.[.]][:.] - -where ``name`` is the name for the script you want to create, the left hand -side of ``:`` is the module that contains your function and the right hand -side is the object you want to invoke (e.g. a function). - -In addition to ``console_scripts``, Setuptools supports ``gui_scripts``, which -will launch a GUI application without running in a terminal window. - - -Advertising Behavior -==================== - -Console scripts are one use of the more general concept of entry points. Entry -points more generally allow a packager to advertise behavior for discovery by -other libraries and applications. This feature enables "plug-in"-like -functionality, where one library solicits entry points and any number of other -libraries provide those entry points. - -A good example of this plug-in behavior can be seen in -`pytest plugins `_, -where pytest is a test framework that allows other libraries to extend -or modify its functionality through the ``pytest11`` entry point. - -The console scripts work similarly, where libraries advertise their commands -and tools like ``pip`` create wrapper scripts that invoke those commands. - -For a project wishing to solicit entry points, Setuptools recommends the -`importlib.metadata `_ -module (part of stdlib since Python 3.8) or its backport, -`importlib_metadata `_. - -For example, to find the console script entry points from the example above:: - -.. code-block:: python - - >>> from importlib import metadata - >>> eps = metadata.entry_points()['console_scripts'] - -``eps`` is now a list of ``EntryPoint`` objects, one of which corresponds -to the ``hello-world = timmins:hello_world`` defined above. Each ``EntryPoint`` -contains the ``name``, ``group``, and ``value``. It also supplies a ``.load()`` -method to import and load that entry point (module or object). - -.. code-block:: ini - - [options.entry_points] - my.plugins = - hello-world = timmins:hello_world - -Then, a different project wishing to load 'my.plugins' plugins could run -the following routine to load (and invoke) such plugins:: - -.. code-block:: python - - >>> from importlib import metadata - >>> eps = metadata.entry_points()['my.plugins'] - >>> for ep in eps: - ... plugin = ep.load() - ... plugin() - -The project soliciting the entry points needs not to have any dependency -or prior knowledge about the libraries implementing the entry points, and -downstream users are able to compose functionality by pulling together -libraries implementing the entry points. - - -Dependency Management -===================== - -Some entry points may require additional dependencies to properly function. -For such an entry point, declare in square brakets any number of dependency -``extras`` following the entry point definition. Such entry points will only -be viable if their extras were declared and installed. See the -:ref:`guide on dependencies management ` for -more information on defining extra requirements. Consider from the -above example:: - -.. code-block:: ini - - [options.entry_points] - console_scripts = - hello-world = timmins:hello_world [pretty-printer] - -In this case, the ``hello-world`` script is only viable if the ``pretty-printer`` -extra is indicated, and so a plugin host might exclude that entry point -(i.e. not install a console script) if the relevant extra dependencies are not -installed. diff --git a/docs/userguide/extension.rst b/docs/userguide/extension.rst new file mode 100644 index 00000000..1e4846fc --- /dev/null +++ b/docs/userguide/extension.rst @@ -0,0 +1,235 @@ +Creating ``distutils`` Extensions +================================= + +It can be hard to add new commands or setup arguments to the distutils. But +the ``setuptools`` package makes it a bit easier, by allowing you to distribute +a distutils extension as a separate project, and then have projects that need +the extension just refer to it in their ``setup_requires`` argument. + +With ``setuptools``, your distutils extension projects can hook in new +commands and ``setup()`` arguments just by defining "entry points". These +are mappings from command or argument names to a specification of where to +import a handler from. (See the section on `Dynamic Discovery of Services and +Plugins`_ above for some more background on entry points.) + + +Adding Commands +--------------- + +You can add new ``setup`` commands by defining entry points in the +``distutils.commands`` group. For example, if you wanted to add a ``foo`` +command, you might add something like this to your distutils extension +project's setup script:: + + setup( + # ... + entry_points={ + "distutils.commands": [ + "foo = mypackage.some_module:foo", + ], + }, + ) + +(Assuming, of course, that the ``foo`` class in ``mypackage.some_module`` is +a ``setuptools.Command`` subclass.) + +Once a project containing such entry points has been activated on ``sys.path``, +(e.g. by running "install" or "develop" with a site-packages installation +directory) the command(s) will be available to any ``setuptools``-based setup +scripts. It is not necessary to use the ``--command-packages`` option or +to monkeypatch the ``distutils.command`` package to install your commands; +``setuptools`` automatically adds a wrapper to the distutils to search for +entry points in the active distributions on ``sys.path``. In fact, this is +how setuptools' own commands are installed: the setuptools project's setup +script defines entry points for them! + +Adding ``setup()`` Arguments +---------------------------- + +.. warning:: Adding arguments to setup is discouraged as such arguments + are only supported through imperative execution and not supported through + declarative config. + +Sometimes, your commands may need additional arguments to the ``setup()`` +call. You can enable this by defining entry points in the +``distutils.setup_keywords`` group. For example, if you wanted a ``setup()`` +argument called ``bar_baz``, you might add something like this to your +distutils extension project's setup script:: + + setup( + # ... + entry_points={ + "distutils.commands": [ + "foo = mypackage.some_module:foo", + ], + "distutils.setup_keywords": [ + "bar_baz = mypackage.some_module:validate_bar_baz", + ], + }, + ) + +The idea here is that the entry point defines a function that will be called +to validate the ``setup()`` argument, if it's supplied. The ``Distribution`` +object will have the initial value of the attribute set to ``None``, and the +validation function will only be called if the ``setup()`` call sets it to +a non-None value. Here's an example validation function:: + + def assert_bool(dist, attr, value): + """Verify that value is True, False, 0, or 1""" + if bool(value) != value: + raise DistutilsSetupError( + "%r must be a boolean value (got %r)" % (attr,value) + ) + +Your function should accept three arguments: the ``Distribution`` object, +the attribute name, and the attribute value. It should raise a +``DistutilsSetupError`` (from the ``distutils.errors`` module) if the argument +is invalid. Remember, your function will only be called with non-None values, +and the default value of arguments defined this way is always None. So, your +commands should always be prepared for the possibility that the attribute will +be ``None`` when they access it later. + +If more than one active distribution defines an entry point for the same +``setup()`` argument, *all* of them will be called. This allows multiple +distutils extensions to define a common argument, as long as they agree on +what values of that argument are valid. + +Also note that as with commands, it is not necessary to subclass or monkeypatch +the distutils ``Distribution`` class in order to add your arguments; it is +sufficient to define the entry points in your extension, as long as any setup +script using your extension lists your project in its ``setup_requires`` +argument. + + +Customizing Distribution Options +-------------------------------- + +Plugins may wish to extend or alter the options on a Distribution object to +suit the purposes of that project. For example, a tool that infers the +``Distribution.version`` from SCM-metadata may need to hook into the +option finalization. To enable this feature, Setuptools offers an entry +point "setuptools.finalize_distribution_options". That entry point must +be a callable taking one argument (the Distribution instance). + +If the callable has an ``.order`` property, that value will be used to +determine the order in which the hook is called. Lower numbers are called +first and the default is zero (0). + +Plugins may read, alter, and set properties on the distribution, but each +plugin is encouraged to load the configuration/settings for their behavior +independently. + + +Adding new EGG-INFO Files +------------------------- + +Some extensible applications or frameworks may want to allow third parties to +develop plugins with application or framework-specific metadata included in +the plugins' EGG-INFO directory, for easy access via the ``pkg_resources`` +metadata API. The easiest way to allow this is to create a distutils extension +to be used from the plugin projects' setup scripts (via ``setup_requires``) +that defines a new setup keyword, and then uses that data to write an EGG-INFO +file when the ``egg_info`` command is run. + +The ``egg_info`` command looks for extension points in an ``egg_info.writers`` +group, and calls them to write the files. Here's a simple example of a +distutils extension defining a setup argument ``foo_bar``, which is a list of +lines that will be written to ``foo_bar.txt`` in the EGG-INFO directory of any +project that uses the argument:: + + setup( + # ... + entry_points={ + "distutils.setup_keywords": [ + "foo_bar = setuptools.dist:assert_string_list", + ], + "egg_info.writers": [ + "foo_bar.txt = setuptools.command.egg_info:write_arg", + ], + }, + ) + +This simple example makes use of two utility functions defined by setuptools +for its own use: a routine to validate that a setup keyword is a sequence of +strings, and another one that looks up a setup argument and writes it to +a file. Here's what the writer utility looks like:: + + def write_arg(cmd, basename, filename): + argname = os.path.splitext(basename)[0] + value = getattr(cmd.distribution, argname, None) + if value is not None: + value = "\n".join(value) + "\n" + cmd.write_or_delete_file(argname, filename, value) + +As you can see, ``egg_info.writers`` entry points must be a function taking +three arguments: a ``egg_info`` command instance, the basename of the file to +write (e.g. ``foo_bar.txt``), and the actual full filename that should be +written to. + +In general, writer functions should honor the command object's ``dry_run`` +setting when writing files, and use the ``distutils.log`` object to do any +console output. The easiest way to conform to this requirement is to use +the ``cmd`` object's ``write_file()``, ``delete_file()``, and +``write_or_delete_file()`` methods exclusively for your file operations. See +those methods' docstrings for more details. + +Adding Support for Revision Control Systems +------------------------------------------------- + +If the files you want to include in the source distribution are tracked using +Git, Mercurial or SVN, you can use the following packages to achieve that: + +- Git and Mercurial: `setuptools_scm `_ +- SVN: `setuptools_svn `_ + +If you would like to create a plugin for ``setuptools`` to find files tracked +by another revision control system, you can do so by adding an entry point to +the ``setuptools.file_finders`` group. The entry point should be a function +accepting a single directory name, and should yield all the filenames within +that directory (and any subdirectories thereof) that are under revision +control. + +For example, if you were going to create a plugin for a revision control system +called "foobar", you would write a function something like this: + +.. code-block:: python + + def find_files_for_foobar(dirname): + # loop to yield paths that start with `dirname` + +And you would register it in a setup script using something like this:: + + entry_points={ + "setuptools.file_finders": [ + "foobar = my_foobar_module:find_files_for_foobar", + ] + } + +Then, anyone who wants to use your plugin can simply install it, and their +local setuptools installation will be able to find the necessary files. + +It is not necessary to distribute source control plugins with projects that +simply use the other source control system, or to specify the plugins in +``setup_requires``. When you create a source distribution with the ``sdist`` +command, setuptools automatically records what files were found in the +``SOURCES.txt`` file. That way, recipients of source distributions don't need +to have revision control at all. However, if someone is working on a package +by checking out with that system, they will need the same plugin(s) that the +original author is using. + +A few important points for writing revision control file finders: + +* Your finder function MUST return relative paths, created by appending to the + passed-in directory name. Absolute paths are NOT allowed, nor are relative + paths that reference a parent directory of the passed-in directory. + +* Your finder function MUST accept an empty string as the directory name, + meaning the current directory. You MUST NOT convert this to a dot; just + yield relative paths. So, yielding a subdirectory named ``some/dir`` under + the current directory should NOT be rendered as ``./some/dir`` or + ``/somewhere/some/dir``, but *always* as simply ``some/dir`` + +* Your finder function SHOULD NOT raise any errors, and SHOULD deal gracefully + with the absence of needed programs (i.e., ones belonging to the revision + control system itself. It *may*, however, use ``distutils.log.warn()`` to + inform the user of the missing program(s). \ No newline at end of file diff --git a/docs/userguide/extension.txt b/docs/userguide/extension.txt deleted file mode 100644 index 1e4846fc..00000000 --- a/docs/userguide/extension.txt +++ /dev/null @@ -1,235 +0,0 @@ -Creating ``distutils`` Extensions -================================= - -It can be hard to add new commands or setup arguments to the distutils. But -the ``setuptools`` package makes it a bit easier, by allowing you to distribute -a distutils extension as a separate project, and then have projects that need -the extension just refer to it in their ``setup_requires`` argument. - -With ``setuptools``, your distutils extension projects can hook in new -commands and ``setup()`` arguments just by defining "entry points". These -are mappings from command or argument names to a specification of where to -import a handler from. (See the section on `Dynamic Discovery of Services and -Plugins`_ above for some more background on entry points.) - - -Adding Commands ---------------- - -You can add new ``setup`` commands by defining entry points in the -``distutils.commands`` group. For example, if you wanted to add a ``foo`` -command, you might add something like this to your distutils extension -project's setup script:: - - setup( - # ... - entry_points={ - "distutils.commands": [ - "foo = mypackage.some_module:foo", - ], - }, - ) - -(Assuming, of course, that the ``foo`` class in ``mypackage.some_module`` is -a ``setuptools.Command`` subclass.) - -Once a project containing such entry points has been activated on ``sys.path``, -(e.g. by running "install" or "develop" with a site-packages installation -directory) the command(s) will be available to any ``setuptools``-based setup -scripts. It is not necessary to use the ``--command-packages`` option or -to monkeypatch the ``distutils.command`` package to install your commands; -``setuptools`` automatically adds a wrapper to the distutils to search for -entry points in the active distributions on ``sys.path``. In fact, this is -how setuptools' own commands are installed: the setuptools project's setup -script defines entry points for them! - -Adding ``setup()`` Arguments ----------------------------- - -.. warning:: Adding arguments to setup is discouraged as such arguments - are only supported through imperative execution and not supported through - declarative config. - -Sometimes, your commands may need additional arguments to the ``setup()`` -call. You can enable this by defining entry points in the -``distutils.setup_keywords`` group. For example, if you wanted a ``setup()`` -argument called ``bar_baz``, you might add something like this to your -distutils extension project's setup script:: - - setup( - # ... - entry_points={ - "distutils.commands": [ - "foo = mypackage.some_module:foo", - ], - "distutils.setup_keywords": [ - "bar_baz = mypackage.some_module:validate_bar_baz", - ], - }, - ) - -The idea here is that the entry point defines a function that will be called -to validate the ``setup()`` argument, if it's supplied. The ``Distribution`` -object will have the initial value of the attribute set to ``None``, and the -validation function will only be called if the ``setup()`` call sets it to -a non-None value. Here's an example validation function:: - - def assert_bool(dist, attr, value): - """Verify that value is True, False, 0, or 1""" - if bool(value) != value: - raise DistutilsSetupError( - "%r must be a boolean value (got %r)" % (attr,value) - ) - -Your function should accept three arguments: the ``Distribution`` object, -the attribute name, and the attribute value. It should raise a -``DistutilsSetupError`` (from the ``distutils.errors`` module) if the argument -is invalid. Remember, your function will only be called with non-None values, -and the default value of arguments defined this way is always None. So, your -commands should always be prepared for the possibility that the attribute will -be ``None`` when they access it later. - -If more than one active distribution defines an entry point for the same -``setup()`` argument, *all* of them will be called. This allows multiple -distutils extensions to define a common argument, as long as they agree on -what values of that argument are valid. - -Also note that as with commands, it is not necessary to subclass or monkeypatch -the distutils ``Distribution`` class in order to add your arguments; it is -sufficient to define the entry points in your extension, as long as any setup -script using your extension lists your project in its ``setup_requires`` -argument. - - -Customizing Distribution Options --------------------------------- - -Plugins may wish to extend or alter the options on a Distribution object to -suit the purposes of that project. For example, a tool that infers the -``Distribution.version`` from SCM-metadata may need to hook into the -option finalization. To enable this feature, Setuptools offers an entry -point "setuptools.finalize_distribution_options". That entry point must -be a callable taking one argument (the Distribution instance). - -If the callable has an ``.order`` property, that value will be used to -determine the order in which the hook is called. Lower numbers are called -first and the default is zero (0). - -Plugins may read, alter, and set properties on the distribution, but each -plugin is encouraged to load the configuration/settings for their behavior -independently. - - -Adding new EGG-INFO Files -------------------------- - -Some extensible applications or frameworks may want to allow third parties to -develop plugins with application or framework-specific metadata included in -the plugins' EGG-INFO directory, for easy access via the ``pkg_resources`` -metadata API. The easiest way to allow this is to create a distutils extension -to be used from the plugin projects' setup scripts (via ``setup_requires``) -that defines a new setup keyword, and then uses that data to write an EGG-INFO -file when the ``egg_info`` command is run. - -The ``egg_info`` command looks for extension points in an ``egg_info.writers`` -group, and calls them to write the files. Here's a simple example of a -distutils extension defining a setup argument ``foo_bar``, which is a list of -lines that will be written to ``foo_bar.txt`` in the EGG-INFO directory of any -project that uses the argument:: - - setup( - # ... - entry_points={ - "distutils.setup_keywords": [ - "foo_bar = setuptools.dist:assert_string_list", - ], - "egg_info.writers": [ - "foo_bar.txt = setuptools.command.egg_info:write_arg", - ], - }, - ) - -This simple example makes use of two utility functions defined by setuptools -for its own use: a routine to validate that a setup keyword is a sequence of -strings, and another one that looks up a setup argument and writes it to -a file. Here's what the writer utility looks like:: - - def write_arg(cmd, basename, filename): - argname = os.path.splitext(basename)[0] - value = getattr(cmd.distribution, argname, None) - if value is not None: - value = "\n".join(value) + "\n" - cmd.write_or_delete_file(argname, filename, value) - -As you can see, ``egg_info.writers`` entry points must be a function taking -three arguments: a ``egg_info`` command instance, the basename of the file to -write (e.g. ``foo_bar.txt``), and the actual full filename that should be -written to. - -In general, writer functions should honor the command object's ``dry_run`` -setting when writing files, and use the ``distutils.log`` object to do any -console output. The easiest way to conform to this requirement is to use -the ``cmd`` object's ``write_file()``, ``delete_file()``, and -``write_or_delete_file()`` methods exclusively for your file operations. See -those methods' docstrings for more details. - -Adding Support for Revision Control Systems -------------------------------------------------- - -If the files you want to include in the source distribution are tracked using -Git, Mercurial or SVN, you can use the following packages to achieve that: - -- Git and Mercurial: `setuptools_scm `_ -- SVN: `setuptools_svn `_ - -If you would like to create a plugin for ``setuptools`` to find files tracked -by another revision control system, you can do so by adding an entry point to -the ``setuptools.file_finders`` group. The entry point should be a function -accepting a single directory name, and should yield all the filenames within -that directory (and any subdirectories thereof) that are under revision -control. - -For example, if you were going to create a plugin for a revision control system -called "foobar", you would write a function something like this: - -.. code-block:: python - - def find_files_for_foobar(dirname): - # loop to yield paths that start with `dirname` - -And you would register it in a setup script using something like this:: - - entry_points={ - "setuptools.file_finders": [ - "foobar = my_foobar_module:find_files_for_foobar", - ] - } - -Then, anyone who wants to use your plugin can simply install it, and their -local setuptools installation will be able to find the necessary files. - -It is not necessary to distribute source control plugins with projects that -simply use the other source control system, or to specify the plugins in -``setup_requires``. When you create a source distribution with the ``sdist`` -command, setuptools automatically records what files were found in the -``SOURCES.txt`` file. That way, recipients of source distributions don't need -to have revision control at all. However, if someone is working on a package -by checking out with that system, they will need the same plugin(s) that the -original author is using. - -A few important points for writing revision control file finders: - -* Your finder function MUST return relative paths, created by appending to the - passed-in directory name. Absolute paths are NOT allowed, nor are relative - paths that reference a parent directory of the passed-in directory. - -* Your finder function MUST accept an empty string as the directory name, - meaning the current directory. You MUST NOT convert this to a dot; just - yield relative paths. So, yielding a subdirectory named ``some/dir`` under - the current directory should NOT be rendered as ``./some/dir`` or - ``/somewhere/some/dir``, but *always* as simply ``some/dir`` - -* Your finder function SHOULD NOT raise any errors, and SHOULD deal gracefully - with the absence of needed programs (i.e., ones belonging to the revision - control system itself. It *may*, however, use ``distutils.log.warn()`` to - inform the user of the missing program(s). \ No newline at end of file diff --git a/docs/userguide/functionalities_rewrite.rst b/docs/userguide/functionalities_rewrite.rst new file mode 100644 index 00000000..d0997ca6 --- /dev/null +++ b/docs/userguide/functionalities_rewrite.rst @@ -0,0 +1,9 @@ +======================================================== +Using setuptools to package and distribute your project +======================================================== + +``setuptools`` offers a variety of functionalities that make it easy to +build and distribute your python package. Here we provide an overview on +the commonly used ones. + + diff --git a/docs/userguide/functionalities_rewrite.txt b/docs/userguide/functionalities_rewrite.txt deleted file mode 100644 index d0997ca6..00000000 --- a/docs/userguide/functionalities_rewrite.txt +++ /dev/null @@ -1,9 +0,0 @@ -======================================================== -Using setuptools to package and distribute your project -======================================================== - -``setuptools`` offers a variety of functionalities that make it easy to -build and distribute your python package. Here we provide an overview on -the commonly used ones. - - diff --git a/docs/userguide/index.rst b/docs/userguide/index.rst new file mode 100644 index 00000000..abee331a --- /dev/null +++ b/docs/userguide/index.rst @@ -0,0 +1,26 @@ +================================================== +Building and Distributing Packages with Setuptools +================================================== + +``Setuptools`` is a collection of enhancements to the Python ``distutils`` +that allow developers 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``. + +.. toctree:: + :maxdepth: 1 + + quickstart + package_discovery + entry_point + dependency_management + datafiles + development_mode + distribution + extension + declarative_config + keywords + commands diff --git a/docs/userguide/index.txt b/docs/userguide/index.txt deleted file mode 100644 index abee331a..00000000 --- a/docs/userguide/index.txt +++ /dev/null @@ -1,26 +0,0 @@ -================================================== -Building and Distributing Packages with Setuptools -================================================== - -``Setuptools`` is a collection of enhancements to the Python ``distutils`` -that allow developers 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``. - -.. toctree:: - :maxdepth: 1 - - quickstart - package_discovery - entry_point - dependency_management - datafiles - development_mode - distribution - extension - declarative_config - keywords - commands diff --git a/docs/userguide/keywords.rst b/docs/userguide/keywords.rst new file mode 100644 index 00000000..e2852b34 --- /dev/null +++ b/docs/userguide/keywords.rst @@ -0,0 +1,175 @@ +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. + +``include_package_data`` + If set to ``True``, this tells ``setuptools`` to automatically include any + data files it finds inside your package directories that are specified by + your ``MANIFEST.in`` file. For more information, see the section below on + `Including Data Files`_. + +``exclude_package_data`` + A dictionary mapping package names to lists of glob patterns that should + be *excluded* from your package directories. You can use this to trim back + any excess files included by ``include_package_data``. For a complete + description and examples, see the section below on `Including Data Files`_. + +``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`_. You do not need to use this option if you are using + ``include_package_data``, unless you need to add e.g. files that are + generated by your setup script and build process. (And are therefore not + in source control or are files that you don't want to include in your + source distribution.) + +``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 builds 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. + +``entry_points`` + A dictionary mapping entry point group names to strings or lists of strings + defining the entry points. Entry points are used to support dynamic + discovery of services or plugins provided by a project. See `Dynamic + Discovery of Services and Plugins`_ for details and examples of the format + of this argument. In addition, this keyword is used to support `Automatic + Script Creation`_. + +``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. + +``python_requires`` + A string corresponding to a version specifier (as defined in PEP 440) for + the Python version, used to specify the Requires-Python defined in PEP 345. + +``setup_requires`` + A string or list of strings specifying what other distributions need to + be present in order for the *setup script* to run. ``setuptools`` will + attempt to obtain these (using pip if available) before processing the + rest of the setup script or commands. This argument is needed if you + are using distutils extensions as part of your build process; for + example, extensions that process setup() arguments and turn them into + EGG-INFO metadata files. + + (Note: projects listed in ``setup_requires`` will NOT be automatically + installed on the system where the setup script is being run. They are + simply downloaded to the ./.eggs directory if they're not locally available + already. If you want them to be installed, as well as being available + when the setup script is run, you should add them to ``install_requires`` + **and** ``setup_requires``.) + +``dependency_links`` + A list of strings naming URLs to be searched when satisfying dependencies. + These links will be used if needed to install packages specified by + ``setup_requires`` or ``tests_require``. They will also be written into + the egg's metadata for use during install by tools that support them. + +``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 other than a namespace declaration. See the + section below on `Namespace Packages`_ for more information. + +``test_suite`` + A string naming a ``unittest.TestCase`` subclass (or a package or 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``. If the named suite is a module, and the module + has an ``additional_tests()`` function, it is called and the results are + added to the tests to be run. If the named suite is a package, any + submodules and subpackages are recursively added to the overall test suite. + + 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. + + New in 41.5.0: Deprecated the test command. + +``tests_require`` + If your project's tests need one or more additional packages besides those + needed to install it, you can use this option to specify them. It should + be a string or list of strings specifying what other distributions need to + be present for the package's tests to run. When you run the ``test`` + command, ``setuptools`` will attempt to obtain these (using pip if + available). Note that these required projects will *not* be installed on + the system where the tests are run, but only downloaded to the project's setup + directory if they're not already installed locally. + + New in 41.5.0: Deprecated the test command. + +.. _test_loader: + +``test_loader`` + If you would like to use a different way of finding tests to run than what + setuptools normally uses, you can specify a module name and class name in + this argument. The named class must be instantiable with no arguments, and + its instances must support the ``loadTestsFromNames()`` method as defined + in the Python ``unittest`` module's ``TestLoader`` class. Setuptools will + pass only one test "name" in the `names` argument: the value supplied for + the ``test_suite`` argument. The loader you specify may interpret this + string in any way it likes, as there are no restrictions on what may be + contained in a ``test_suite`` string. + + The module name and class name must be separated by a ``:``. The default + value of this argument is ``"setuptools.command.test:ScanningLoader"``. If + you want to use the default ``unittest`` behavior, you can specify + ``"unittest:TestLoader"`` as your ``test_loader`` argument instead. This + will prevent automatic scanning of submodules and subpackages. + + The module and class you specify here may be contained in another package, + as long as you use the ``tests_require`` option to ensure that the package + containing the loader class is available when the ``test`` command is run. + + New in 41.5.0: Deprecated the test command. + +``eager_resources`` + A list of strings naming resources that should be extracted together, if + any of them is needed, or if any C extensions included in the project are + imported. This argument is only useful if the project will be installed as + a zipfile, and there is a need to have all of the listed resources be + extracted to the filesystem *as a unit*. Resources listed here + should be "/"-separated paths, relative to the source root, so to list a + resource ``foo.png`` in package ``bar.baz``, you would include the string + ``bar/baz/foo.png`` in this argument. + + If you only need to obtain resources one at a time, or you don't have any C + extensions that access other files in the project (such as data files or + shared libraries), you probably do NOT need this argument and shouldn't + mess with it. For more details on how this argument works, see the section + below on `Automatic Resource Extraction`_. + +``use_2to3`` + Convert the source code from Python 2 to Python 3 with 2to3 during the + build process. See :doc:`python3` for more details. + +``convert_2to3_doctests`` + List of doctest source files that need to be converted with 2to3. + See :doc:`python3` for more details. + +``use_2to3_fixers`` + A list of modules to search for additional fixers to be used during + the 2to3 conversion. See :doc:`python3` for more details. + +``project_urls`` + An arbitrary map of URL names to hyperlinks, allowing more extensible + documentation of where various resources can be found than the simple + ``url`` and ``download_url`` options provide. \ No newline at end of file diff --git a/docs/userguide/keywords.txt b/docs/userguide/keywords.txt deleted file mode 100644 index e2852b34..00000000 --- a/docs/userguide/keywords.txt +++ /dev/null @@ -1,175 +0,0 @@ -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. - -``include_package_data`` - If set to ``True``, this tells ``setuptools`` to automatically include any - data files it finds inside your package directories that are specified by - your ``MANIFEST.in`` file. For more information, see the section below on - `Including Data Files`_. - -``exclude_package_data`` - A dictionary mapping package names to lists of glob patterns that should - be *excluded* from your package directories. You can use this to trim back - any excess files included by ``include_package_data``. For a complete - description and examples, see the section below on `Including Data Files`_. - -``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`_. You do not need to use this option if you are using - ``include_package_data``, unless you need to add e.g. files that are - generated by your setup script and build process. (And are therefore not - in source control or are files that you don't want to include in your - source distribution.) - -``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 builds 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. - -``entry_points`` - A dictionary mapping entry point group names to strings or lists of strings - defining the entry points. Entry points are used to support dynamic - discovery of services or plugins provided by a project. See `Dynamic - Discovery of Services and Plugins`_ for details and examples of the format - of this argument. In addition, this keyword is used to support `Automatic - Script Creation`_. - -``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. - -``python_requires`` - A string corresponding to a version specifier (as defined in PEP 440) for - the Python version, used to specify the Requires-Python defined in PEP 345. - -``setup_requires`` - A string or list of strings specifying what other distributions need to - be present in order for the *setup script* to run. ``setuptools`` will - attempt to obtain these (using pip if available) before processing the - rest of the setup script or commands. This argument is needed if you - are using distutils extensions as part of your build process; for - example, extensions that process setup() arguments and turn them into - EGG-INFO metadata files. - - (Note: projects listed in ``setup_requires`` will NOT be automatically - installed on the system where the setup script is being run. They are - simply downloaded to the ./.eggs directory if they're not locally available - already. If you want them to be installed, as well as being available - when the setup script is run, you should add them to ``install_requires`` - **and** ``setup_requires``.) - -``dependency_links`` - A list of strings naming URLs to be searched when satisfying dependencies. - These links will be used if needed to install packages specified by - ``setup_requires`` or ``tests_require``. They will also be written into - the egg's metadata for use during install by tools that support them. - -``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 other than a namespace declaration. See the - section below on `Namespace Packages`_ for more information. - -``test_suite`` - A string naming a ``unittest.TestCase`` subclass (or a package or 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``. If the named suite is a module, and the module - has an ``additional_tests()`` function, it is called and the results are - added to the tests to be run. If the named suite is a package, any - submodules and subpackages are recursively added to the overall test suite. - - 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. - - New in 41.5.0: Deprecated the test command. - -``tests_require`` - If your project's tests need one or more additional packages besides those - needed to install it, you can use this option to specify them. It should - be a string or list of strings specifying what other distributions need to - be present for the package's tests to run. When you run the ``test`` - command, ``setuptools`` will attempt to obtain these (using pip if - available). Note that these required projects will *not* be installed on - the system where the tests are run, but only downloaded to the project's setup - directory if they're not already installed locally. - - New in 41.5.0: Deprecated the test command. - -.. _test_loader: - -``test_loader`` - If you would like to use a different way of finding tests to run than what - setuptools normally uses, you can specify a module name and class name in - this argument. The named class must be instantiable with no arguments, and - its instances must support the ``loadTestsFromNames()`` method as defined - in the Python ``unittest`` module's ``TestLoader`` class. Setuptools will - pass only one test "name" in the `names` argument: the value supplied for - the ``test_suite`` argument. The loader you specify may interpret this - string in any way it likes, as there are no restrictions on what may be - contained in a ``test_suite`` string. - - The module name and class name must be separated by a ``:``. The default - value of this argument is ``"setuptools.command.test:ScanningLoader"``. If - you want to use the default ``unittest`` behavior, you can specify - ``"unittest:TestLoader"`` as your ``test_loader`` argument instead. This - will prevent automatic scanning of submodules and subpackages. - - The module and class you specify here may be contained in another package, - as long as you use the ``tests_require`` option to ensure that the package - containing the loader class is available when the ``test`` command is run. - - New in 41.5.0: Deprecated the test command. - -``eager_resources`` - A list of strings naming resources that should be extracted together, if - any of them is needed, or if any C extensions included in the project are - imported. This argument is only useful if the project will be installed as - a zipfile, and there is a need to have all of the listed resources be - extracted to the filesystem *as a unit*. Resources listed here - should be "/"-separated paths, relative to the source root, so to list a - resource ``foo.png`` in package ``bar.baz``, you would include the string - ``bar/baz/foo.png`` in this argument. - - If you only need to obtain resources one at a time, or you don't have any C - extensions that access other files in the project (such as data files or - shared libraries), you probably do NOT need this argument and shouldn't - mess with it. For more details on how this argument works, see the section - below on `Automatic Resource Extraction`_. - -``use_2to3`` - Convert the source code from Python 2 to Python 3 with 2to3 during the - build process. See :doc:`python3` for more details. - -``convert_2to3_doctests`` - List of doctest source files that need to be converted with 2to3. - See :doc:`python3` for more details. - -``use_2to3_fixers`` - A list of modules to search for additional fixers to be used during - the 2to3 conversion. See :doc:`python3` for more details. - -``project_urls`` - An arbitrary map of URL names to hyperlinks, allowing more extensible - documentation of where various resources can be found than the simple - ``url`` and ``download_url`` options provide. \ No newline at end of file diff --git a/docs/userguide/miscellaneous.rst b/docs/userguide/miscellaneous.rst new file mode 100644 index 00000000..65e075cd --- /dev/null +++ b/docs/userguide/miscellaneous.rst @@ -0,0 +1,94 @@ +Automatic Resource Extraction +----------------------------- + +If you are using tools that expect your resources to be "real" files, or your +project includes non-extension native libraries or other files that your C +extensions expect to be able to access, you may need to list those files in +the ``eager_resources`` argument to ``setup()``, so that the files will be +extracted together, whenever a C extension in the project is imported. + +This is especially important if your project includes shared libraries *other* +than distutils-built C extensions, and those shared libraries use file +extensions other than ``.dll``, ``.so``, or ``.dylib``, which are the +extensions that setuptools 0.6a8 and higher automatically detects as shared +libraries and adds to the ``native_libs.txt`` file for you. Any shared +libraries whose names do not end with one of those extensions should be listed +as ``eager_resources``, because they need to be present in the filesystem when +he C extensions that link to them are used. + +The ``pkg_resources`` runtime for compressed packages will automatically +extract *all* C extensions and ``eager_resources`` at the same time, whenever +*any* C extension or eager resource is requested via the ``resource_filename()`` +API. (C extensions are imported using ``resource_filename()`` internally.) +This ensures that C extensions will see all of the "real" files that they +expect to see. + +Note also that you can list directory resource names in ``eager_resources`` as +well, in which case the directory's contents (including subdirectories) will be +extracted whenever any C extension or eager resource is requested. + +Please note that if you're not sure whether you need to use this argument, you +don't! It's really intended to support projects with lots of non-Python +dependencies and as a last resort for crufty projects that can't otherwise +handle being compressed. If your package is pure Python, Python plus data +files, or Python plus C, you really don't need this. You've got to be using +either C or an external program that needs "real" files in your project before +there's any possibility of ``eager_resources`` being relevant to your project. + +Defining Additional Metadata +---------------------------- + +Some extensible applications and frameworks may need to define their own kinds +of metadata to include in eggs, which they can then access using the +``pkg_resources`` metadata APIs. Ordinarily, this is done by having plugin +developers include additional files in their ``ProjectName.egg-info`` +directory. However, since it can be tedious to create such files by hand, you +may want to create a distutils extension that will create the necessary files +from arguments to ``setup()``, in much the same way that ``setuptools`` does +for many of the ``setup()`` arguments it adds. See the section below on +`Creating distutils Extensions`_ for more details, especially the subsection on +`Adding new EGG-INFO Files`_. + +Setting the ``zip_safe`` flag +----------------------------- + +For some use cases (such as bundling as part of a larger application), Python +packages may be run directly from a zip file. +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. + +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`` to try to guess +whether your project can work as a zipfile. diff --git a/docs/userguide/miscellaneous.txt b/docs/userguide/miscellaneous.txt deleted file mode 100644 index 65e075cd..00000000 --- a/docs/userguide/miscellaneous.txt +++ /dev/null @@ -1,94 +0,0 @@ -Automatic Resource Extraction ------------------------------ - -If you are using tools that expect your resources to be "real" files, or your -project includes non-extension native libraries or other files that your C -extensions expect to be able to access, you may need to list those files in -the ``eager_resources`` argument to ``setup()``, so that the files will be -extracted together, whenever a C extension in the project is imported. - -This is especially important if your project includes shared libraries *other* -than distutils-built C extensions, and those shared libraries use file -extensions other than ``.dll``, ``.so``, or ``.dylib``, which are the -extensions that setuptools 0.6a8 and higher automatically detects as shared -libraries and adds to the ``native_libs.txt`` file for you. Any shared -libraries whose names do not end with one of those extensions should be listed -as ``eager_resources``, because they need to be present in the filesystem when -he C extensions that link to them are used. - -The ``pkg_resources`` runtime for compressed packages will automatically -extract *all* C extensions and ``eager_resources`` at the same time, whenever -*any* C extension or eager resource is requested via the ``resource_filename()`` -API. (C extensions are imported using ``resource_filename()`` internally.) -This ensures that C extensions will see all of the "real" files that they -expect to see. - -Note also that you can list directory resource names in ``eager_resources`` as -well, in which case the directory's contents (including subdirectories) will be -extracted whenever any C extension or eager resource is requested. - -Please note that if you're not sure whether you need to use this argument, you -don't! It's really intended to support projects with lots of non-Python -dependencies and as a last resort for crufty projects that can't otherwise -handle being compressed. If your package is pure Python, Python plus data -files, or Python plus C, you really don't need this. You've got to be using -either C or an external program that needs "real" files in your project before -there's any possibility of ``eager_resources`` being relevant to your project. - -Defining Additional Metadata ----------------------------- - -Some extensible applications and frameworks may need to define their own kinds -of metadata to include in eggs, which they can then access using the -``pkg_resources`` metadata APIs. Ordinarily, this is done by having plugin -developers include additional files in their ``ProjectName.egg-info`` -directory. However, since it can be tedious to create such files by hand, you -may want to create a distutils extension that will create the necessary files -from arguments to ``setup()``, in much the same way that ``setuptools`` does -for many of the ``setup()`` arguments it adds. See the section below on -`Creating distutils Extensions`_ for more details, especially the subsection on -`Adding new EGG-INFO Files`_. - -Setting the ``zip_safe`` flag ------------------------------ - -For some use cases (such as bundling as part of a larger application), Python -packages may be run directly from a zip file. -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. - -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`` to try to guess -whether your project can work as a zipfile. diff --git a/docs/userguide/package_discovery.rst b/docs/userguide/package_discovery.rst new file mode 100644 index 00000000..0e0d27c5 --- /dev/null +++ b/docs/userguide/package_discovery.rst @@ -0,0 +1,232 @@ +.. _`package_discovery`: + +======================================== +Package Discovery and Namespace Package +======================================== + +.. note:: + a full specification for the keyword supplied to ``setup.cfg`` or + ``setup.py`` can be found at :ref:`keywords reference ` + +.. note:: + the examples provided here are only to demonstrate the functionality + introduced. More metadata and options arguments need to be supplied + if you want to replicate them on your system. If you are completely + new to setuptools, the :ref:`quickstart section ` is a good + place to start. + +``Setuptools`` provide powerful tools to handle package discovery, including +support for namespace package. Normally, you would specify the package to be +included manually in the following manner: + +.. code-block:: ini + + [options] + #... + packages = + mypkg1 + mypkg2 + +.. code-block:: python + + setup( + #... + packages = ['mypkg1', 'mypkg2'] + ) + +This can get tiresome reallly quickly. To speed things up, we introduce two +functions provided by setuptools: + +.. code-block:: ini + + [options] + packages = find: + #or + packages = find_namespace: + +.. code-block:: python + + from setuptools import find_packages + #or + from setuptools import find_namespace_packages + + +Using ``find:`` or ``find_packages`` +==================================== +Let's start with the first tool. ``find:`` (``find_packages``) takes a source +directory and two lists of package name patterns to exclude and include, and +then return a list of ``str`` representing the packages it could find. To use +it, consider the following directory + +.. code-block:: bash + + mypkg/ + src/ + pkg1/__init__.py + pkg2/__init__.py + additional/__init__.py + + setup.cfg #or setup.py + +To have your setup.cfg or setup.py to automatically include packages found +in ``src`` that starts with the name ``pkg`` and not ``additional``: + +.. code-block:: ini + + [options] + packages = find: + package_dir = + =src + + [options.packages.find] + where = src + include = pkg* + exclude = additional + +.. code-block:: python + + setup( + #... + packages = find_packages( + where = 'src', + include = ['pkg*',], + exclude = ['tests',] + ), + package_dir = {"":"src"} + #... + ) + + +Using ``find_namespace:`` or ``find_namespace_packages`` +======================================================== +``setuptools`` provides the ``find_namespace:`` (``find_namespace_packages``) +which behaves similarly to ``find:`` but works with namespace package. Before +diving in, it is important to have a good understanding of what namespace +packages are. Here is a quick recap: + +Suppose you have two packages named as follows: + +.. code-block:: bash + + /Users/Desktop/timmins/foo/__init__.py + /Library/timmins/bar/__init__.py + +If both ``Desktop`` and ``Library`` are on your ``PYTHONPATH``, then a +namespace package called ``timmins`` will be created automatically for you when +you invoke the import mechanism, allowing you to accomplish the following + +.. code-block:: python + + >>> import timmins.foo + >>> import timmins.bar + +as if there is only one ``timmins`` on your system. The two packages can then +be distributed separately and installed individually without affecting the +other one. Suppose you are packaging the ``foo`` part: + +.. code-block:: bash + + foo/ + src/ + timmins/foo/__init__.py + setup.cfg # or setup.py + +and you want the ``foo`` to be automatically included, ``find:`` won't work +because timmins doesn't contain ``__init__.py`` directly, instead, you have +to use ``find_namespace:``: + +.. code-block:: ini + + [options] + package_dir = + =src + packages = find_namespace: + + [options.packages.find_namespace] + where = src + +When you install the zipped distribution, ``timmins.foo`` would become +available to your interpreter. + +You can think of ``find_namespace:`` as identical to ``find:`` except it +would count a directory as a package even if it doesn't contain ``__init__.py`` +file directly. As a result, this creates an interesting side effect. If you +organize your package like this: + +.. code-block:: bash + + foo/ + timmins/ + foo/__init__.py + setup.cfg # or setup.py + tests/ + test_foo/__init__.py + +a naive ``find_namespace:`` would include tests as part of your package to +be installed. A simple way to fix it is to adopt the aforementioned +``src`` layout. + + +Legacy Namespace Packages +========================= +The fact you can create namespace package so effortlessly above is credited +to `PEP 420 `_. It use to be more +cumbersome to accomplish the same result. Historically, there were two methods +to create namespace packages. One is the ``pkg_resources`` style supported by +``setuptools`` and the other one being ``pkgutils`` style offered by +``pkgutils`` module in Python. Both are now considered deprecated despite the +fact they still linger in many existing packages. These two differ in many +subtle yet significant aspects and you can find out more on `Python packaging +user guide `_ + + +``pkg_resource`` style namespace package +---------------------------------------- +This is the method ``setuptools`` directly supports. Starting with the same +layout, there are two pieces you need to add to it. First, an ``__init__.py`` +file directly under your namespace package directory that contains the +following: + +.. code-block:: python + + __import__("pkg_resources").declare_namespace(__name__) + +And the ``namespace_packages`` keyword in your ``setup.cfg`` or ``setup.py``: + +.. code-block:: ini + + [options] + namespace_packages = timmins + +.. code-block:: python + + setup( + # ... + namespace_packages = ['timmins'] + ) + +And your directory should look like this + +.. code-block:: bash + + /foo/ + src/ + timmins/ + __init__.py + foo/__init__.py + setup.cfg #or setup.py + +Repeat the same for other packages and you can achieve the same result as +the previous section. + +``pkgutil`` style namespace package +----------------------------------- +This method is almost identical to the ``pkg_resource`` except that the +``namespace_packages`` declaration is omitted and the ``__init__.py`` +file contains the following: + +.. code-block:: python + + __path__ = __import__('pkgutil').extend_path(__path__, __name__) + +The project layout remains the same and ``setup.cfg`` remains the same. diff --git a/docs/userguide/package_discovery.txt b/docs/userguide/package_discovery.txt deleted file mode 100644 index 0e0d27c5..00000000 --- a/docs/userguide/package_discovery.txt +++ /dev/null @@ -1,232 +0,0 @@ -.. _`package_discovery`: - -======================================== -Package Discovery and Namespace Package -======================================== - -.. note:: - a full specification for the keyword supplied to ``setup.cfg`` or - ``setup.py`` can be found at :ref:`keywords reference ` - -.. note:: - the examples provided here are only to demonstrate the functionality - introduced. More metadata and options arguments need to be supplied - if you want to replicate them on your system. If you are completely - new to setuptools, the :ref:`quickstart section ` is a good - place to start. - -``Setuptools`` provide powerful tools to handle package discovery, including -support for namespace package. Normally, you would specify the package to be -included manually in the following manner: - -.. code-block:: ini - - [options] - #... - packages = - mypkg1 - mypkg2 - -.. code-block:: python - - setup( - #... - packages = ['mypkg1', 'mypkg2'] - ) - -This can get tiresome reallly quickly. To speed things up, we introduce two -functions provided by setuptools: - -.. code-block:: ini - - [options] - packages = find: - #or - packages = find_namespace: - -.. code-block:: python - - from setuptools import find_packages - #or - from setuptools import find_namespace_packages - - -Using ``find:`` or ``find_packages`` -==================================== -Let's start with the first tool. ``find:`` (``find_packages``) takes a source -directory and two lists of package name patterns to exclude and include, and -then return a list of ``str`` representing the packages it could find. To use -it, consider the following directory - -.. code-block:: bash - - mypkg/ - src/ - pkg1/__init__.py - pkg2/__init__.py - additional/__init__.py - - setup.cfg #or setup.py - -To have your setup.cfg or setup.py to automatically include packages found -in ``src`` that starts with the name ``pkg`` and not ``additional``: - -.. code-block:: ini - - [options] - packages = find: - package_dir = - =src - - [options.packages.find] - where = src - include = pkg* - exclude = additional - -.. code-block:: python - - setup( - #... - packages = find_packages( - where = 'src', - include = ['pkg*',], - exclude = ['tests',] - ), - package_dir = {"":"src"} - #... - ) - - -Using ``find_namespace:`` or ``find_namespace_packages`` -======================================================== -``setuptools`` provides the ``find_namespace:`` (``find_namespace_packages``) -which behaves similarly to ``find:`` but works with namespace package. Before -diving in, it is important to have a good understanding of what namespace -packages are. Here is a quick recap: - -Suppose you have two packages named as follows: - -.. code-block:: bash - - /Users/Desktop/timmins/foo/__init__.py - /Library/timmins/bar/__init__.py - -If both ``Desktop`` and ``Library`` are on your ``PYTHONPATH``, then a -namespace package called ``timmins`` will be created automatically for you when -you invoke the import mechanism, allowing you to accomplish the following - -.. code-block:: python - - >>> import timmins.foo - >>> import timmins.bar - -as if there is only one ``timmins`` on your system. The two packages can then -be distributed separately and installed individually without affecting the -other one. Suppose you are packaging the ``foo`` part: - -.. code-block:: bash - - foo/ - src/ - timmins/foo/__init__.py - setup.cfg # or setup.py - -and you want the ``foo`` to be automatically included, ``find:`` won't work -because timmins doesn't contain ``__init__.py`` directly, instead, you have -to use ``find_namespace:``: - -.. code-block:: ini - - [options] - package_dir = - =src - packages = find_namespace: - - [options.packages.find_namespace] - where = src - -When you install the zipped distribution, ``timmins.foo`` would become -available to your interpreter. - -You can think of ``find_namespace:`` as identical to ``find:`` except it -would count a directory as a package even if it doesn't contain ``__init__.py`` -file directly. As a result, this creates an interesting side effect. If you -organize your package like this: - -.. code-block:: bash - - foo/ - timmins/ - foo/__init__.py - setup.cfg # or setup.py - tests/ - test_foo/__init__.py - -a naive ``find_namespace:`` would include tests as part of your package to -be installed. A simple way to fix it is to adopt the aforementioned -``src`` layout. - - -Legacy Namespace Packages -========================= -The fact you can create namespace package so effortlessly above is credited -to `PEP 420 `_. It use to be more -cumbersome to accomplish the same result. Historically, there were two methods -to create namespace packages. One is the ``pkg_resources`` style supported by -``setuptools`` and the other one being ``pkgutils`` style offered by -``pkgutils`` module in Python. Both are now considered deprecated despite the -fact they still linger in many existing packages. These two differ in many -subtle yet significant aspects and you can find out more on `Python packaging -user guide `_ - - -``pkg_resource`` style namespace package ----------------------------------------- -This is the method ``setuptools`` directly supports. Starting with the same -layout, there are two pieces you need to add to it. First, an ``__init__.py`` -file directly under your namespace package directory that contains the -following: - -.. code-block:: python - - __import__("pkg_resources").declare_namespace(__name__) - -And the ``namespace_packages`` keyword in your ``setup.cfg`` or ``setup.py``: - -.. code-block:: ini - - [options] - namespace_packages = timmins - -.. code-block:: python - - setup( - # ... - namespace_packages = ['timmins'] - ) - -And your directory should look like this - -.. code-block:: bash - - /foo/ - src/ - timmins/ - __init__.py - foo/__init__.py - setup.cfg #or setup.py - -Repeat the same for other packages and you can achieve the same result as -the previous section. - -``pkgutil`` style namespace package ------------------------------------ -This method is almost identical to the ``pkg_resource`` except that the -``namespace_packages`` declaration is omitted and the ``__init__.py`` -file contains the following: - -.. code-block:: python - - __path__ = __import__('pkgutil').extend_path(__path__, __name__) - -The project layout remains the same and ``setup.cfg`` remains the same. diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst new file mode 100644 index 00000000..52829751 --- /dev/null +++ b/docs/userguide/quickstart.rst @@ -0,0 +1,210 @@ +========================== +``setuptools`` Quickstart +========================== + +.. contents:: + +Installation +============ + +To install the latest version of setuptools, use:: + + pip install --upgrade setuptools + + +Python packaging at a glance +============================ +The landscape of Python packaging is shifting and ``Setuptools`` has evolved to +only provide backend support, no longer being the de-facto packaging tool in +the market. All python package must provide a ``pyproject.toml`` and specify +the backend (build system) it wants to use. The distribution can then +be generated with whatever tools that provides a ``build sdist``-alike +functionality. While this may appear cumbersome, given the added pieces, +it in fact tremendously enhances the portability of your package. The +change is driven under `PEP 517 ``. To learn more about Python packaging in general, +navigate to the `bottom `_ of this page. + + +Basic Use +========= +For basic use of setuptools, you will need a ``pyproject.toml`` with the +exact following info, which declares you want to use ``setuptools`` to +package your project: + +.. code-block:: toml + + [build-system] + requires = ["setuptools", "wheel"] + build-backend = "setuptools.build_meta" + +Then, you will need a ``setup.cfg`` to specify your package information, +such as metadata, contents, dependencies, etc. Here we demonstrate the minimum + +.. code-block:: ini + + [metadata] + name = "mypackage" + version = 0.0.1 + + [options] + packages = "mypackage" + install_requires = + requests + importlib; python_version == "2.6" + +This is what your project would look like:: + + ~/mypackage/ + pyproject.toml + setup.cfg + mypackage/__init__.py + +Then, you need an installer, such as `pep517 `_ +which you can obtain via ``pip install pep517``. After downloading it, invoke +the installer:: + + python -m pep517.build + +You now have your distribution ready (e.g. a ``tar.gz`` file and a ``.whl`` +file in the ``dist`` directory), which you can upload to PyPI! + +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. In the next few section, +we will walk through those additional but essential information you need +to specify to properly package your project. + + +Automatic package discovery +=========================== +For simple projects, it's usually easy enough to manually add packages to +the ``packages`` keyword in ``setup.cfg``. However, for very large projects +, it can be a big burden to keep the package list updated. ``setuptools`` +therefore provides two convenient tools to ease the burden: ``find: `` and +``find_namespace: ``. To use it in your project: + +.. code-block:: ini + + [options] + packages = find: + + [options.packages.find] #optional + include=pkg1, pkg2 + exclude=pk3, pk4 + +When you pass the above information, alongside other necessary ones, +``setuptools`` walks through the directory specified in ``where`` (omitted +here as the package reside in current directory) and filters the packages +it can find following the ``include`` (default to none), then remove +those that match the ``exclude`` and return a list of Python packages. Note +that each entry in the ``[options.packages.find]`` is optional. The above +setup also allows you to adopt a ``src/`` layout. For more details and advanced +use, go to :ref:`package_discovery` + + +Entry points and automatic script creation +=========================================== +Setuptools support automatic creation of scripts upon installation, that runs +code within your package if you specify them with the ``entry_point`` keyword. +This is what allows you to run commands like ``pip install`` instead of having +to type ``python -m pip install``. To accomplish this, add the entry_points +keyword in your ``setup.cfg``: + +.. code-block:: ini + + [options] + entry_points = + [console_script] + main = mypkg:some_func + +When this project is installed, a ``main`` script will be installed and will +invoke the ``some_func`` in the ``__init__.py`` file when called by the user. +For detailed usage, including managing the additional or optional dependencies, +go to :ref:`entry_point`. + + +Dependency management +===================== +``setuptools`` supports automatically installing dependencies when a package is +installed. The simplest way to include requirement specifiers is to use the +``install_requires`` argument to ``setup.cfg``. It takes a string or list of +strings containing requirement specifiers (A version specifier is one of the +operators <, >, <=, >=, == or !=, followed by a version identifier): + +.. code-block:: ini + + [options] + install_requires = + docutils >= 0.3 + requests <= 0.4 + +When your project is installed, all of the dependencies not already installed +will be located (via PyPI), downloaded, built (if necessary), and installed. +This, of course, is a simplified scenarios. ``setuptools`` also provide +additional keywords such as ``setup_requires`` that allows you to install +dependencies before running the script, and ``extras_requires`` that take +care of those needed by automatically generated scripts. It also provides +mechanisms to handle dependencies that are not in PyPI. For more advanced use, +see :ref:`dependency_management` + + +Including Data Files +==================== +The distutils have traditionally allowed installation of "data files", which +are placed in a platform-specific location. Setuptools offers three ways to +specify data files to be included in your packages. For the simpliest use, you +can simply use the ``include_package_data`` keyword: + +.. code-block:: ini + + [options] + include_package_data = True + +This tells setuptools to install any data files it finds in your packages. +The data files must be specified via the distutils' ``MANIFEST.in`` file. +For more details, see :ref:`datafiles` + + +Development mode +================ +``setuptools`` allows you to install a package without copying any files +to your interpretor directory (e.g. the ``site-packages`` directory). This +allows you to modify your source code and have the changes take effect without +you having to rebuild and reinstall. This is currently incompatible with +PEP 517 and therefore it requires a ``setup.py`` script with the following +content:: + + import setuptools + setuptools.setup() + +Then:: + + pip install --editable . + +This creates a link file in your interpretor site package directory which +associate with your source code. For more information, see: (WIP) + + +Uploading your package to PyPI +============================== +After generating the distribution files, next step would be to upload your +distribution so others can use it. This functionality is provided by +``twine `` and we will only demonstrate the +basic use here. + + +Transitioning from ``setup.py`` to ``setup.cfg`` +================================================== +To avoid executing arbitary scripts and boilerplate code, we are transitioning +into a full-fledged ``setup.cfg`` to declare your package information instead +of running ``setup()``. This inevitably brings challenges due to a different +syntax. Here we provide a quick guide to understanding how ``setup.cfg`` is +parsed by ``setuptool`` to ease the pain of transition. + + +Resources on Python packaging +============================= +Packaging in Python is hard. Here we provide a list of links for those that +want to learn more. diff --git a/docs/userguide/quickstart.txt b/docs/userguide/quickstart.txt deleted file mode 100644 index 52829751..00000000 --- a/docs/userguide/quickstart.txt +++ /dev/null @@ -1,210 +0,0 @@ -========================== -``setuptools`` Quickstart -========================== - -.. contents:: - -Installation -============ - -To install the latest version of setuptools, use:: - - pip install --upgrade setuptools - - -Python packaging at a glance -============================ -The landscape of Python packaging is shifting and ``Setuptools`` has evolved to -only provide backend support, no longer being the de-facto packaging tool in -the market. All python package must provide a ``pyproject.toml`` and specify -the backend (build system) it wants to use. The distribution can then -be generated with whatever tools that provides a ``build sdist``-alike -functionality. While this may appear cumbersome, given the added pieces, -it in fact tremendously enhances the portability of your package. The -change is driven under `PEP 517 ``. To learn more about Python packaging in general, -navigate to the `bottom `_ of this page. - - -Basic Use -========= -For basic use of setuptools, you will need a ``pyproject.toml`` with the -exact following info, which declares you want to use ``setuptools`` to -package your project: - -.. code-block:: toml - - [build-system] - requires = ["setuptools", "wheel"] - build-backend = "setuptools.build_meta" - -Then, you will need a ``setup.cfg`` to specify your package information, -such as metadata, contents, dependencies, etc. Here we demonstrate the minimum - -.. code-block:: ini - - [metadata] - name = "mypackage" - version = 0.0.1 - - [options] - packages = "mypackage" - install_requires = - requests - importlib; python_version == "2.6" - -This is what your project would look like:: - - ~/mypackage/ - pyproject.toml - setup.cfg - mypackage/__init__.py - -Then, you need an installer, such as `pep517 `_ -which you can obtain via ``pip install pep517``. After downloading it, invoke -the installer:: - - python -m pep517.build - -You now have your distribution ready (e.g. a ``tar.gz`` file and a ``.whl`` -file in the ``dist`` directory), which you can upload to PyPI! - -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. In the next few section, -we will walk through those additional but essential information you need -to specify to properly package your project. - - -Automatic package discovery -=========================== -For simple projects, it's usually easy enough to manually add packages to -the ``packages`` keyword in ``setup.cfg``. However, for very large projects -, it can be a big burden to keep the package list updated. ``setuptools`` -therefore provides two convenient tools to ease the burden: ``find: `` and -``find_namespace: ``. To use it in your project: - -.. code-block:: ini - - [options] - packages = find: - - [options.packages.find] #optional - include=pkg1, pkg2 - exclude=pk3, pk4 - -When you pass the above information, alongside other necessary ones, -``setuptools`` walks through the directory specified in ``where`` (omitted -here as the package reside in current directory) and filters the packages -it can find following the ``include`` (default to none), then remove -those that match the ``exclude`` and return a list of Python packages. Note -that each entry in the ``[options.packages.find]`` is optional. The above -setup also allows you to adopt a ``src/`` layout. For more details and advanced -use, go to :ref:`package_discovery` - - -Entry points and automatic script creation -=========================================== -Setuptools support automatic creation of scripts upon installation, that runs -code within your package if you specify them with the ``entry_point`` keyword. -This is what allows you to run commands like ``pip install`` instead of having -to type ``python -m pip install``. To accomplish this, add the entry_points -keyword in your ``setup.cfg``: - -.. code-block:: ini - - [options] - entry_points = - [console_script] - main = mypkg:some_func - -When this project is installed, a ``main`` script will be installed and will -invoke the ``some_func`` in the ``__init__.py`` file when called by the user. -For detailed usage, including managing the additional or optional dependencies, -go to :ref:`entry_point`. - - -Dependency management -===================== -``setuptools`` supports automatically installing dependencies when a package is -installed. The simplest way to include requirement specifiers is to use the -``install_requires`` argument to ``setup.cfg``. It takes a string or list of -strings containing requirement specifiers (A version specifier is one of the -operators <, >, <=, >=, == or !=, followed by a version identifier): - -.. code-block:: ini - - [options] - install_requires = - docutils >= 0.3 - requests <= 0.4 - -When your project is installed, all of the dependencies not already installed -will be located (via PyPI), downloaded, built (if necessary), and installed. -This, of course, is a simplified scenarios. ``setuptools`` also provide -additional keywords such as ``setup_requires`` that allows you to install -dependencies before running the script, and ``extras_requires`` that take -care of those needed by automatically generated scripts. It also provides -mechanisms to handle dependencies that are not in PyPI. For more advanced use, -see :ref:`dependency_management` - - -Including Data Files -==================== -The distutils have traditionally allowed installation of "data files", which -are placed in a platform-specific location. Setuptools offers three ways to -specify data files to be included in your packages. For the simpliest use, you -can simply use the ``include_package_data`` keyword: - -.. code-block:: ini - - [options] - include_package_data = True - -This tells setuptools to install any data files it finds in your packages. -The data files must be specified via the distutils' ``MANIFEST.in`` file. -For more details, see :ref:`datafiles` - - -Development mode -================ -``setuptools`` allows you to install a package without copying any files -to your interpretor directory (e.g. the ``site-packages`` directory). This -allows you to modify your source code and have the changes take effect without -you having to rebuild and reinstall. This is currently incompatible with -PEP 517 and therefore it requires a ``setup.py`` script with the following -content:: - - import setuptools - setuptools.setup() - -Then:: - - pip install --editable . - -This creates a link file in your interpretor site package directory which -associate with your source code. For more information, see: (WIP) - - -Uploading your package to PyPI -============================== -After generating the distribution files, next step would be to upload your -distribution so others can use it. This functionality is provided by -``twine `` and we will only demonstrate the -basic use here. - - -Transitioning from ``setup.py`` to ``setup.cfg`` -================================================== -To avoid executing arbitary scripts and boilerplate code, we are transitioning -into a full-fledged ``setup.cfg`` to declare your package information instead -of running ``setup()``. This inevitably brings challenges due to a different -syntax. Here we provide a quick guide to understanding how ``setup.cfg`` is -parsed by ``setuptool`` to ease the pain of transition. - - -Resources on Python packaging -============================= -Packaging in Python is hard. Here we provide a list of links for those that -want to learn more. -- cgit v1.2.1 From a6673f11935c8ff7e88b66b95de59721a00c3201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=AD=E4=B9=9D=E9=BC=8E?= <109224573@qq.com> Date: Fri, 2 Oct 2020 19:04:57 +0800 Subject: editorial fix --- docs/userguide/package_discovery.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/package_discovery.rst b/docs/userguide/package_discovery.rst index 0e0d27c5..02eab172 100644 --- a/docs/userguide/package_discovery.rst +++ b/docs/userguide/package_discovery.rst @@ -90,7 +90,7 @@ in ``src`` that starts with the name ``pkg`` and not ``additional``: packages = find_packages( where = 'src', include = ['pkg*',], - exclude = ['tests',] + exclude = ['additional',] ), package_dir = {"":"src"} #... -- cgit v1.2.1 From c218cc5443dbcec77c81a03391c6ae2a566a7a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=AD=E4=B9=9D=E9=BC=8E?= <109224573@qq.com> Date: Fri, 2 Oct 2020 20:07:58 +0800 Subject: docs: code-block style fix --- docs/userguide/entry_point.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/entry_point.rst b/docs/userguide/entry_point.rst index 7f5165a8..f4c43c6e 100644 --- a/docs/userguide/entry_point.rst +++ b/docs/userguide/entry_point.rst @@ -14,7 +14,7 @@ Console Scripts =============== First consider an example without entry points. Imagine a package -defined thus:: +defined thus: .. code-block:: bash @@ -38,7 +38,7 @@ and ``__main__.py`` providing a hook: hello_world() After installing the package, the function may be invoked through the -`runpy `_ module:: +`runpy `_ module: .. code-block:: bash @@ -49,7 +49,7 @@ user-friendly name for installers of the package to execute. Installers like pip will create wrapper scripts to execute a function. In the above example, to create a command ``hello-world`` that invokes ``timmins.hello_world``, add a console script entry point to -``setup.cfg``:: +``setup.cfg``: .. code-block:: ini @@ -96,7 +96,7 @@ For a project wishing to solicit entry points, Setuptools recommends the module (part of stdlib since Python 3.8) or its backport, `importlib_metadata `_. -For example, to find the console script entry points from the example above:: +For example, to find the console script entry points from the example above: .. code-block:: python @@ -115,7 +115,7 @@ method to import and load that entry point (module or object). hello-world = timmins:hello_world Then, a different project wishing to load 'my.plugins' plugins could run -the following routine to load (and invoke) such plugins:: +the following routine to load (and invoke) such plugins: .. code-block:: python @@ -140,7 +140,7 @@ For such an entry point, declare in square brakets any number of dependency be viable if their extras were declared and installed. See the :ref:`guide on dependencies management ` for more information on defining extra requirements. Consider from the -above example:: +above example: .. code-block:: ini -- cgit v1.2.1 From 1ba4f4e0240d4e09585463dc7ebb9b7a47b1eb48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=AD=E4=B9=9D=E9=BC=8E?= <109224573@qq.com> Date: Sat, 3 Oct 2020 10:12:36 +0800 Subject: fix inline-code style --- docs/userguide/quickstart.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 52829751..fdc7ff14 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -82,8 +82,8 @@ Automatic package discovery For simple projects, it's usually easy enough to manually add packages to the ``packages`` keyword in ``setup.cfg``. However, for very large projects , it can be a big burden to keep the package list updated. ``setuptools`` -therefore provides two convenient tools to ease the burden: ``find: `` and -``find_namespace: ``. To use it in your project: +therefore provides two convenient tools to ease the burden: ``find:`` and +``find_namespace:``. To use it in your project: .. code-block:: ini -- cgit v1.2.1 From 754f710a10c15b7456c086c2839f01ad2556b3fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=AD=E4=B9=9D=E9=BC=8E?= <109224573@qq.com> Date: Sat, 3 Oct 2020 10:30:49 +0800 Subject: Update dependency_management.rst --- docs/userguide/dependency_management.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.rst b/docs/userguide/dependency_management.rst index a26ab6c3..ae2192d8 100644 --- a/docs/userguide/dependency_management.rst +++ b/docs/userguide/dependency_management.rst @@ -266,7 +266,7 @@ the two dependencies ``PDF`` maps to. The second use case is that other package can use this "extra" for their own dependencies. For example, if "Project-B" needs "project A" with PDF support -installed, it might declare the dependency like this:: +installed, it might declare the dependency like this: .. code-block:: ini @@ -309,4 +309,4 @@ In some cases, you might need to specify the minimum required python version. This is handled with the ``python_requires`` keyword supplied to ``setup.cfg`` or ``setup.py``. -Example WIP \ No newline at end of file +Example WIP -- cgit v1.2.1 From 81cf64f294d8152707cf7d8f242f50b9c64c62d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=AD=E4=B9=9D=E9=BC=8E?= <109224573@qq.com> Date: Sat, 3 Oct 2020 10:32:19 +0800 Subject: Update entry_point.rst --- docs/userguide/entry_point.rst | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docs/userguide') diff --git a/docs/userguide/entry_point.rst b/docs/userguide/entry_point.rst index f4c43c6e..a91fd5dc 100644 --- a/docs/userguide/entry_point.rst +++ b/docs/userguide/entry_point.rst @@ -33,6 +33,8 @@ with ``__init__.py`` as: and ``__main__.py`` providing a hook: +.. code-block:: python + from . import hello_world if __name__ == '__main__': hello_world() -- cgit v1.2.1 From 6722c069db857991b95fb95a5ddf90ec4913094a Mon Sep 17 00:00:00 2001 From: Marius Gedminas Date: Mon, 5 Oct 2020 09:52:31 +0300 Subject: Fix ReST syntax error in the PEP 517 link --- docs/userguide/quickstart.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 52829751..37d33b26 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -22,7 +22,7 @@ be generated with whatever tools that provides a ``build sdist``-alike functionality. While this may appear cumbersome, given the added pieces, it in fact tremendously enhances the portability of your package. The change is driven under `PEP 517 ``. To learn more about Python packaging in general, +build-requirements>`_. To learn more about Python packaging in general, navigate to the `bottom `_ of this page. -- cgit v1.2.1 From f516f011b0361a329304c3ed6dc611fc97053e2b Mon Sep 17 00:00:00 2001 From: Marius Gedminas Date: Mon, 5 Oct 2020 17:56:12 +0300 Subject: And another malformed link --- docs/userguide/quickstart.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 37d33b26..3af6d566 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -191,7 +191,7 @@ Uploading your package to PyPI ============================== After generating the distribution files, next step would be to upload your distribution so others can use it. This functionality is provided by -``twine `` and we will only demonstrate the +`twine `_ and we will only demonstrate the basic use here. -- cgit v1.2.1 From a3aafcd7f572ee56c8b43e2d1d60cd252483a02f Mon Sep 17 00:00:00 2001 From: alvy Date: Wed, 7 Oct 2020 17:43:14 -0400 Subject: add a paragraph in index to linkt build_meta doc --- docs/userguide/index.rst | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'docs/userguide') diff --git a/docs/userguide/index.rst b/docs/userguide/index.rst index abee331a..8470e268 100644 --- a/docs/userguide/index.rst +++ b/docs/userguide/index.rst @@ -10,6 +10,15 @@ packages. Packages built and distributed using ``setuptools`` look to the user like ordinary Python packages based on the ``distutils``. +Transition to PEP517 +==================== + +Since setuptools no longer serves as the default build tool, one must explicitly +opt in (by providing a ``pyproject.toml`` file) to use this library. The user +facing part is provided by `PEP517 `_ and +backend interface is described :ref:`in this document <../build_meta>`. The +quickstart provides an overview of the new workflow. + .. toctree:: :maxdepth: 1 -- cgit v1.2.1 From bcb6d47f1618fc37bbab24b54f79e268435f849c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=AD=E4=B9=9D=E9=BC=8E?= <109224573@qq.com> Date: Mon, 12 Oct 2020 08:46:07 +0800 Subject: Update docs/userguide/quickstart.rst Co-authored-by: Sviatoslav Sydorenko --- docs/userguide/quickstart.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index fdc7ff14..f2f5e41d 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -82,8 +82,8 @@ Automatic package discovery For simple projects, it's usually easy enough to manually add packages to the ``packages`` keyword in ``setup.cfg``. However, for very large projects , it can be a big burden to keep the package list updated. ``setuptools`` -therefore provides two convenient tools to ease the burden: ``find:`` and -``find_namespace:``. To use it in your project: +therefore provides two convenient tools to ease the burden: ``find:\ `` and +``find_namespace:\ ``. To use it in your project: .. code-block:: ini -- cgit v1.2.1 From b66e45a90e82c9170cc48f21e4dac9d206193953 Mon Sep 17 00:00:00 2001 From: Marius Gedminas Date: Mon, 12 Oct 2020 16:42:51 +0300 Subject: Use the :pep: role instead of a manual link Co-Authored-By: Sviatoslav Sydorenko --- docs/userguide/quickstart.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 3af6d566..a07afae7 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -21,8 +21,8 @@ the backend (build system) it wants to use. The distribution can then be generated with whatever tools that provides a ``build sdist``-alike functionality. While this may appear cumbersome, given the added pieces, it in fact tremendously enhances the portability of your package. The -change is driven under `PEP 517 `_. To learn more about Python packaging in general, +change is driven under :pep:`PEP 517 <517#build-requirements>`_. +To learn more about Python packaging in general, navigate to the `bottom `_ of this page. -- cgit v1.2.1 From f04cd3b21f1bd8ef5c8dedc42fb8708dfdf0fccd Mon Sep 17 00:00:00 2001 From: alvy Date: Mon, 12 Oct 2020 19:23:00 -0400 Subject: make suggested edits --- docs/userguide/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/index.rst b/docs/userguide/index.rst index 8470e268..7abc7903 100644 --- a/docs/userguide/index.rst +++ b/docs/userguide/index.rst @@ -14,8 +14,8 @@ Transition to PEP517 ==================== Since setuptools no longer serves as the default build tool, one must explicitly -opt in (by providing a ``pyproject.toml`` file) to use this library. The user -facing part is provided by `PEP517 `_ and +opt in (by providing a :file:`pyproject.toml` file) to use this library. The user +facing part is provided by tools such as pip and backend interface is described :ref:`in this document <../build_meta>`. The quickstart provides an overview of the new workflow. -- cgit v1.2.1 From edfa441febf6c5d8af8973ce952b3a0c19b7b575 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Fri, 16 Oct 2020 01:14:51 +0200 Subject: =?UTF-8?q?=F0=9F=93=9D=20Recover=20interdoc=20links=20&=20correct?= =?UTF-8?q?=20broken=20syntax?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/userguide/commands.rst | 4 +-- docs/userguide/datafiles.rst | 9 ++++--- docs/userguide/declarative_config.rst | 2 ++ docs/userguide/dependency_management.rst | 11 +++++---- docs/userguide/development_mode.rst | 4 +-- docs/userguide/distribution.rst | 18 ++++++++------ docs/userguide/entry_point.rst | 10 +++++--- docs/userguide/extension.rst | 13 +++++++--- docs/userguide/index.rst | 2 ++ docs/userguide/keywords.rst | 42 ++++++++++++++++---------------- docs/userguide/miscellaneous.rst | 8 +++--- docs/userguide/package_discovery.rst | 6 +++-- docs/userguide/quickstart.rst | 12 +++++---- 13 files changed, 85 insertions(+), 56 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/commands.rst b/docs/userguide/commands.rst index c64f62bf..e632e550 100644 --- a/docs/userguide/commands.rst +++ b/docs/userguide/commands.rst @@ -275,7 +275,7 @@ is used when you are building source distributions.) In addition to writing the core egg metadata defined by ``setuptools`` and required by ``pkg_resources``, this command can be extended to write other metadata files as well, by defining entry points in the ``egg_info.writers`` -group. See the section on `Adding new EGG-INFO Files`_ below for more details. +group. See the section on :ref:`Adding new EGG-INFO Files` below for more details. Note that using additional metadata writers may require you to include a ``setup_requires`` argument to ``setup()`` in order to ensure that the desired writers are available on ``sys.path``. @@ -315,7 +315,7 @@ added in the following order: (Note: Because these options modify the version number used for source and binary distributions of your project, you should first make sure that you know how the resulting version numbers will be interpreted by automated tools -like pip. See the section above on `Specifying Your Project's Version`_ for an +like pip. See the section above on :ref:`Specifying Your Project's Version` for an explanation of pre- and post-release tags, as well as tips on how to choose and verify a versioning scheme for your project.) diff --git a/docs/userguide/datafiles.rst b/docs/userguide/datafiles.rst index 315ec724..69cf36e6 100644 --- a/docs/userguide/datafiles.rst +++ b/docs/userguide/datafiles.rst @@ -20,8 +20,8 @@ e.g.:: This tells setuptools to install any data files it finds in your packages. The data files must be specified via the distutils' ``MANIFEST.in`` file. (They can also be tracked by a revision control system, using an appropriate -plugin. See the section below on `Adding Support for Revision Control -Systems`_ for information on how to write such plugins.) +plugin. See the section below on :ref:`Adding Support for Revision +Control Systems` for information on how to write such plugins.) If you want finer-grained control over what files are included (for example, if you have documentation files in your package directories and want to exclude @@ -144,6 +144,9 @@ if they track intermediate revisions of your project using Subversion; be sure to let them know when you make changes that remove files from inclusion so they can run ``setup.py clean --all``. + +.. _Accessing Data Files at Runtime: + Accessing Data Files at Runtime ------------------------------- @@ -171,4 +174,4 @@ fall back to the platform-specific location for installing data files, there is no supported facility to reliably retrieve these resources. Instead, the PyPA recommends that any data files you wish to be accessible at -run time be included in the package. \ No newline at end of file +run time be included in the package. diff --git a/docs/userguide/declarative_config.rst b/docs/userguide/declarative_config.rst index 51c897c4..2228bd15 100644 --- a/docs/userguide/declarative_config.rst +++ b/docs/userguide/declarative_config.rst @@ -1,3 +1,5 @@ +.. _declarative config: + ----------------------------------------- Configuring setup() using setup.cfg files ----------------------------------------- diff --git a/docs/userguide/dependency_management.rst b/docs/userguide/dependency_management.rst index a26ab6c3..354a9f8c 100644 --- a/docs/userguide/dependency_management.rst +++ b/docs/userguide/dependency_management.rst @@ -25,7 +25,7 @@ you also need the ``wheel`` package as well since it is recommended that you upload a ``.whl`` file to PyPI alongside your ``.tar.gz`` file. Unlike the other two types of dependency keyword, this one is specified in your ``pyproject.toml`` file (if you have forgot what this is, go to -:ref:`quickstart` or (WIP)): +:doc:`quickstart` or (WIP)): .. code-block:: ini @@ -36,10 +36,11 @@ other two types of dependency keyword, this one is specified in your .. note:: This used to be accomplished with the ``setup_requires`` keyword but is now considered deprecated in favor of the PEP 517 style described above. - To peek into how this legacy keyword is used, consult our :ref:`guide on - deprecated practice (WIP)` + To peek into how this legacy keyword is used, consult our :doc:`guide on + deprecated practice (WIP) <../deprecated/index>` +.. _Declaring Dependencies: Declaring required dependency ============================= @@ -266,7 +267,7 @@ the two dependencies ``PDF`` maps to. The second use case is that other package can use this "extra" for their own dependencies. For example, if "Project-B" needs "project A" with PDF support -installed, it might declare the dependency like this:: +installed, it might declare the dependency like this: .. code-block:: ini @@ -309,4 +310,4 @@ In some cases, you might need to specify the minimum required python version. This is handled with the ``python_requires`` keyword supplied to ``setup.cfg`` or ``setup.py``. -Example WIP \ No newline at end of file +Example WIP diff --git a/docs/userguide/development_mode.rst b/docs/userguide/development_mode.rst index 9d4e7581..bce724a7 100644 --- a/docs/userguide/development_mode.rst +++ b/docs/userguide/development_mode.rst @@ -49,7 +49,7 @@ 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. +command; see the section on the :ref:`develop ` command below for more details. Note that you can also apply setuptools commands to non-setuptools projects, using commands like this:: @@ -57,4 +57,4 @@ using commands like this:: python -c "import setuptools; with open('setup.py') as f: exec(compile(f.read(), 'setup.py', 'exec'))" develop That is, you can simply list the normal setup commands and options following -the quoted part. \ No newline at end of file +the quoted part. diff --git a/docs/userguide/distribution.rst b/docs/userguide/distribution.rst index 77ea2660..377f7bb4 100644 --- a/docs/userguide/distribution.rst +++ b/docs/userguide/distribution.rst @@ -23,17 +23,17 @@ egg distributions by adding one or more of the following to the project's 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. +:ref:`egg_info ` command for more details. (Also, before you release your project, be sure to see the section above on -`Specifying Your Project's Version`_ for more information about how pre- and +:ref:`Specifying Your Project's Version` for more information about how pre- and post-release tags affect how version numbers are interpreted. This is important in order to make sure that dependency processing tools will know which versions of your project are newer than others.) Finally, 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 +probably also check out the :ref:`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:: @@ -46,7 +46,7 @@ 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`` +:ref:`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 script or cron job could just run ``setup.py daily`` in each project directory. (And, you could also define sitewide or per-user default versions @@ -61,7 +61,7 @@ selection with pluggable endpoints for looking up files to include. If you are using a revision control system, and your source distributions only need to include files that you're tracking in revision control, use a corresponding plugin instead of writing a ``MANIFEST.in`` file. See the section below on -`Adding Support for Revision Control Systems`_ for information on plugins. +:ref:`Adding Support for Revision Control Systems` for information on plugins. If you need to include automatically generated files, or files that are kept in an unsupported revision control system, you'll need to create a ``MANIFEST.in`` @@ -114,7 +114,8 @@ You can then use it like this:: setup.py release sdist bdist_egg Or of course you can create more elaborate aliases that do all of the above. -See the sections below on the `egg_info`_ and `alias`_ commands for more ideas. +See the sections below on the :ref:`egg_info ` and +:ref:`alias ` commands for more ideas. Distributing Extensions compiled with Cython -------------------------------------------- @@ -154,6 +155,9 @@ control system will be able to build it even if they don't have Cython installed, and that your source releases will be similarly usable with or without Cython. + +.. _Specifying Your Project's Version: + Specifying Your Project's Version --------------------------------- @@ -237,4 +241,4 @@ have setuptools automatically tag your in-development releases with various pre- or post-release tags. See the following sections for more details: * `Tagging and "Daily Build" or "Snapshot" Releases`_ -* The `egg_info`_ command \ No newline at end of file +* The :ref:`egg_info ` command diff --git a/docs/userguide/entry_point.rst b/docs/userguide/entry_point.rst index 7f5165a8..d1127ae4 100644 --- a/docs/userguide/entry_point.rst +++ b/docs/userguide/entry_point.rst @@ -33,6 +33,8 @@ with ``__init__.py`` as: and ``__main__.py`` providing a hook: +.. code-block:: python + from . import hello_world if __name__ == '__main__': hello_world() @@ -49,7 +51,7 @@ user-friendly name for installers of the package to execute. Installers like pip will create wrapper scripts to execute a function. In the above example, to create a command ``hello-world`` that invokes ``timmins.hello_world``, add a console script entry point to -``setup.cfg``:: +``setup.cfg``: .. code-block:: ini @@ -74,6 +76,8 @@ In addition to ``console_scripts``, Setuptools supports ``gui_scripts``, which will launch a GUI application without running in a terminal window. +.. _dynamic discovery of services and plugins: + Advertising Behavior ==================== @@ -138,9 +142,9 @@ Some entry points may require additional dependencies to properly function. For such an entry point, declare in square brakets any number of dependency ``extras`` following the entry point definition. Such entry points will only be viable if their extras were declared and installed. See the -:ref:`guide on dependencies management ` for +:doc:`guide on dependencies management ` for more information on defining extra requirements. Consider from the -above example:: +above example: .. code-block:: ini diff --git a/docs/userguide/extension.rst b/docs/userguide/extension.rst index 1e4846fc..4de24ec9 100644 --- a/docs/userguide/extension.rst +++ b/docs/userguide/extension.rst @@ -1,3 +1,5 @@ +.. _Creating ``distutils`` Extensions: + Creating ``distutils`` Extensions ================================= @@ -9,8 +11,8 @@ the extension just refer to it in their ``setup_requires`` argument. With ``setuptools``, your distutils extension projects can hook in new commands and ``setup()`` arguments just by defining "entry points". These are mappings from command or argument names to a specification of where to -import a handler from. (See the section on `Dynamic Discovery of Services and -Plugins`_ above for some more background on entry points.) +import a handler from. (See the section on :ref:`Dynamic Discovery of +Services and Plugins` above for some more background on entry points.) Adding Commands @@ -120,6 +122,8 @@ plugin is encouraged to load the configuration/settings for their behavior independently. +.. _Adding new EGG-INFO Files: + Adding new EGG-INFO Files ------------------------- @@ -173,6 +177,9 @@ the ``cmd`` object's ``write_file()``, ``delete_file()``, and ``write_or_delete_file()`` methods exclusively for your file operations. See those methods' docstrings for more details. + +.. _Adding Support for Revision Control Systems: + Adding Support for Revision Control Systems ------------------------------------------------- @@ -232,4 +239,4 @@ A few important points for writing revision control file finders: * Your finder function SHOULD NOT raise any errors, and SHOULD deal gracefully with the absence of needed programs (i.e., ones belonging to the revision control system itself. It *may*, however, use ``distutils.log.warn()`` to - inform the user of the missing program(s). \ No newline at end of file + inform the user of the missing program(s). diff --git a/docs/userguide/index.rst b/docs/userguide/index.rst index abee331a..57b059e5 100644 --- a/docs/userguide/index.rst +++ b/docs/userguide/index.rst @@ -24,3 +24,5 @@ ordinary Python packages based on the ``distutils``. declarative_config keywords commands + functionalities_rewrite + miscellaneous diff --git a/docs/userguide/keywords.rst b/docs/userguide/keywords.rst index e2852b34..58fe74bc 100644 --- a/docs/userguide/keywords.rst +++ b/docs/userguide/keywords.rst @@ -8,19 +8,19 @@ unless you need the associated ``setuptools`` feature. ``include_package_data`` If set to ``True``, this tells ``setuptools`` to automatically include any data files it finds inside your package directories that are specified by - your ``MANIFEST.in`` file. For more information, see the section below on - `Including Data Files`_. + your ``MANIFEST.in`` file. For more information, see the section on + :ref:`Including Data Files`. ``exclude_package_data`` A dictionary mapping package names to lists of glob patterns that should be *excluded* from your package directories. You can use this to trim back any excess files included by ``include_package_data``. For a complete - description and examples, see the section below on `Including Data Files`_. + description and examples, see the section on :ref:`Including Data Files`. ``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`_. You do not need to use this option if you are using + complete description and examples, see the section on :ref:`Including + Data Files`. You do not need to use this option if you are using ``include_package_data``, unless you need to add e.g. files that are generated by your setup script and build process. (And are therefore not in source control or are files that you don't want to include in your @@ -34,22 +34,22 @@ unless you need the associated ``setuptools`` feature. ``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. + be installed when this one is. See the section on :ref:`Declaring + Dependencies` for details and examples of the format of this argument. ``entry_points`` A dictionary mapping entry point group names to strings or lists of strings defining the entry points. Entry points are used to support dynamic - discovery of services or plugins provided by a project. See `Dynamic - Discovery of Services and Plugins`_ for details and examples of the format - of this argument. In addition, this keyword is used to support `Automatic - Script Creation`_. + discovery of services or plugins provided by a project. See :ref:`Dynamic + Discovery of Services and Plugins` for details and examples of the format + of this argument. In addition, this keyword is used to support + :ref:`Automatic Script Creation `. ``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. + installed to support those features. See the section on :ref:`Declaring + Dependencies` for details and examples of the format of this argument. ``python_requires`` A string corresponding to a version specifier (as defined in PEP 440) for @@ -87,7 +87,7 @@ unless you need the associated ``setuptools`` feature. 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 other than a namespace declaration. See the - section below on `Namespace Packages`_ for more information. + section below on :ref:`Namespace Packages` for more information. ``test_suite`` A string naming a ``unittest.TestCase`` subclass (or a package or module @@ -98,9 +98,9 @@ unless you need the associated ``setuptools`` feature. added to the tests to be run. If the named suite is a package, any submodules and subpackages are recursively added to the overall test suite. - Specifying this argument enables use of the `test`_ command to run the + Specifying this argument enables use of the :ref:`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. + :ref:`test ` command below for more details. New in 41.5.0: Deprecated the test command. @@ -155,21 +155,21 @@ unless you need the associated ``setuptools`` feature. extensions that access other files in the project (such as data files or shared libraries), you probably do NOT need this argument and shouldn't mess with it. For more details on how this argument works, see the section - below on `Automatic Resource Extraction`_. + below on :ref:`Automatic Resource Extraction`. ``use_2to3`` Convert the source code from Python 2 to Python 3 with 2to3 during the - build process. See :doc:`python3` for more details. + build process. See :doc:`../deprecated/python3` for more details. ``convert_2to3_doctests`` List of doctest source files that need to be converted with 2to3. - See :doc:`python3` for more details. + See :doc:`../deprecated/python3` for more details. ``use_2to3_fixers`` A list of modules to search for additional fixers to be used during - the 2to3 conversion. See :doc:`python3` for more details. + the 2to3 conversion. See :doc:`../deprecated/python3` for more details. ``project_urls`` An arbitrary map of URL names to hyperlinks, allowing more extensible documentation of where various resources can be found than the simple - ``url`` and ``download_url`` options provide. \ No newline at end of file + ``url`` and ``download_url`` options provide. diff --git a/docs/userguide/miscellaneous.rst b/docs/userguide/miscellaneous.rst index 65e075cd..3df327d7 100644 --- a/docs/userguide/miscellaneous.rst +++ b/docs/userguide/miscellaneous.rst @@ -1,3 +1,5 @@ +.. _Automatic Resource Extraction: + Automatic Resource Extraction ----------------------------- @@ -46,8 +48,8 @@ directory. However, since it can be tedious to create such files by hand, you may want to create a distutils extension that will create the necessary files from arguments to ``setup()``, in much the same way that ``setuptools`` does for many of the ``setup()`` arguments it adds. See the section below on -`Creating distutils Extensions`_ for more details, especially the subsection on -`Adding new EGG-INFO Files`_. +:ref:`Creating ``distutils\`\` Extensions` for more details, especially the +subsection on :ref:`Adding new EGG-INFO Files`. Setting the ``zip_safe`` flag ----------------------------- @@ -75,7 +77,7 @@ 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.) +See the :ref:`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 diff --git a/docs/userguide/package_discovery.rst b/docs/userguide/package_discovery.rst index 0e0d27c5..3915408d 100644 --- a/docs/userguide/package_discovery.rst +++ b/docs/userguide/package_discovery.rst @@ -6,13 +6,13 @@ Package Discovery and Namespace Package .. note:: a full specification for the keyword supplied to ``setup.cfg`` or - ``setup.py`` can be found at :ref:`keywords reference ` + ``setup.py`` can be found at :doc:`keywords reference ` .. note:: the examples provided here are only to demonstrate the functionality introduced. More metadata and options arguments need to be supplied if you want to replicate them on your system. If you are completely - new to setuptools, the :ref:`quickstart section ` is a good + new to setuptools, the :doc:`quickstart section ` is a good place to start. ``Setuptools`` provide powerful tools to handle package discovery, including @@ -97,6 +97,8 @@ in ``src`` that starts with the name ``pkg`` and not ``additional``: ) +.. _Namespace Packages: + Using ``find_namespace:`` or ``find_namespace_packages`` ======================================================== ``setuptools`` provides the ``find_namespace:`` (``find_namespace_packages``) diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 52829751..3ee4fc8c 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -82,8 +82,8 @@ Automatic package discovery For simple projects, it's usually easy enough to manually add packages to the ``packages`` keyword in ``setup.cfg``. However, for very large projects , it can be a big burden to keep the package list updated. ``setuptools`` -therefore provides two convenient tools to ease the burden: ``find: `` and -``find_namespace: ``. To use it in your project: +therefore provides two convenient tools to ease the burden: :literal:`find:\ ` and +:literal:`find_namespace:\ `. To use it in your project: .. code-block:: ini @@ -122,7 +122,7 @@ keyword in your ``setup.cfg``: When this project is installed, a ``main`` script will be installed and will invoke the ``some_func`` in the ``__init__.py`` file when called by the user. For detailed usage, including managing the additional or optional dependencies, -go to :ref:`entry_point`. +go to :doc:`entry_point`. Dependency management @@ -147,9 +147,11 @@ additional keywords such as ``setup_requires`` that allows you to install dependencies before running the script, and ``extras_requires`` that take care of those needed by automatically generated scripts. It also provides mechanisms to handle dependencies that are not in PyPI. For more advanced use, -see :ref:`dependency_management` +see :doc:`dependency_management` +.. _Including Data Files: + Including Data Files ==================== The distutils have traditionally allowed installation of "data files", which @@ -164,7 +166,7 @@ can simply use the ``include_package_data`` keyword: This tells setuptools to install any data files it finds in your packages. The data files must be specified via the distutils' ``MANIFEST.in`` file. -For more details, see :ref:`datafiles` +For more details, see :doc:`datafiles` Development mode -- cgit v1.2.1 From 883f33613572e3c92021b58522b54958b00cdc87 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Fri, 16 Oct 2020 01:13:03 +0200 Subject: =?UTF-8?q?=E2=9C=A8Make=20the=20default=20implicit=20role=20autof?= =?UTF-8?q?ind=20targets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/userguide/declarative_config.rst | 10 +++++----- docs/userguide/keywords.rst | 2 +- docs/userguide/quickstart.rst | 3 +-- 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/declarative_config.rst b/docs/userguide/declarative_config.rst index 2228bd15..bc66869b 100644 --- a/docs/userguide/declarative_config.rst +++ b/docs/userguide/declarative_config.rst @@ -201,7 +201,7 @@ obsoletes list-comma string in such a file, so validation is stricter in this case. Notes: -1. The `version` file attribute has only been supported since 39.2.0. +1. The ``version`` file attribute has only been supported since 39.2.0. Options ------- @@ -237,12 +237,12 @@ data_files dict 40.6.0 **packages** - The ``find:`` and ``find_namespace:`` directive can be further configured in a dedicated subsection ``options.packages.find``. This subsection - accepts the same keys as the `setuptools.find_packages` and the - `setuptools.find_namespace_packages` function: + accepts the same keys as the ``setuptools.find_packages`` and the + ``setuptools.find_namespace_packages`` function: ``where``, ``include``, and ``exclude``. **find_namespace directive** - The ``find_namespace:`` directive is supported since Python >=3.3. Notes: -1. In the `package_data` section, a key named with a single asterisk (`*`) -refers to all packages, in lieu of the empty string used in `setup.py`. +1. In the ``package_data`` section, a key named with a single asterisk (``*``) +refers to all packages, in lieu of the empty string used in ``setup.py``. diff --git a/docs/userguide/keywords.rst b/docs/userguide/keywords.rst index 58fe74bc..268e4f42 100644 --- a/docs/userguide/keywords.rst +++ b/docs/userguide/keywords.rst @@ -124,7 +124,7 @@ unless you need the associated ``setuptools`` feature. this argument. The named class must be instantiable with no arguments, and its instances must support the ``loadTestsFromNames()`` method as defined in the Python ``unittest`` module's ``TestLoader`` class. Setuptools will - pass only one test "name" in the `names` argument: the value supplied for + pass only one test "name" in the ``names`` argument: the value supplied for the ``test_suite`` argument. The loader you specify may interpret this string in any way it likes, as there are no restrictions on what may be contained in a ``test_suite`` string. diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 3ee4fc8c..24ea3e4b 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -21,8 +21,7 @@ the backend (build system) it wants to use. The distribution can then be generated with whatever tools that provides a ``build sdist``-alike functionality. While this may appear cumbersome, given the added pieces, it in fact tremendously enhances the portability of your package. The -change is driven under `PEP 517 ``. To learn more about Python packaging in general, +change is driven under :pep:`517 <517#build-requirements>`. To learn more about Python packaging in general, navigate to the `bottom `_ of this page. -- cgit v1.2.1 From a7e930914e1d5baed8a646ae5a0be65a9c97d07e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B0=AD=E4=B9=9D=E9=BC=8E?= <109224573@qq.com> Date: Sat, 17 Oct 2020 16:54:56 +0800 Subject: Restore quickstart.rst --- docs/userguide/quickstart.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 64be2cb9..24ea3e4b 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -81,8 +81,8 @@ Automatic package discovery For simple projects, it's usually easy enough to manually add packages to the ``packages`` keyword in ``setup.cfg``. However, for very large projects , it can be a big burden to keep the package list updated. ``setuptools`` -therefore provides two convenient tools to ease the burden: ``find:\ `` and -``find_namespace:\ ``. To use it in your project: +therefore provides two convenient tools to ease the burden: :literal:`find:\ ` and +:literal:`find_namespace:\ `. To use it in your project: .. code-block:: ini -- cgit v1.2.1 From 23f874ca386f8f33beae3e287b866af79f97415f Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 17 Oct 2020 11:56:01 -0400 Subject: Prefer doc role to ref role. Co-authored-by: Sviatoslav Sydorenko --- docs/userguide/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/index.rst b/docs/userguide/index.rst index 7abc7903..18679c54 100644 --- a/docs/userguide/index.rst +++ b/docs/userguide/index.rst @@ -16,7 +16,7 @@ Transition to PEP517 Since setuptools no longer serves as the default build tool, one must explicitly opt in (by providing a :file:`pyproject.toml` file) to use this library. The user facing part is provided by tools such as pip and -backend interface is described :ref:`in this document <../build_meta>`. The +backend interface is described :doc:`in this document <../build_meta>`. The quickstart provides an overview of the new workflow. .. toctree:: -- cgit v1.2.1 From 9ab7bc54cf1eb1a0cb088e8157dc8c88c553b9c7 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sat, 17 Oct 2020 13:14:24 -0400 Subject: Clean up syntax on entry_points.console_scripts. Fixes #2429. --- docs/userguide/quickstart.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index aebcf60f..697087ed 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -106,16 +106,15 @@ use, go to :ref:`package_discovery` Entry points and automatic script creation =========================================== Setuptools support automatic creation of scripts upon installation, that runs -code within your package if you specify them with the ``entry_point`` keyword. +code within your package if you specify them with the ``entry_points`` keyword. This is what allows you to run commands like ``pip install`` instead of having to type ``python -m pip install``. To accomplish this, add the entry_points keyword in your ``setup.cfg``: .. code-block:: ini - [options] - entry_points = - [console_script] + [options.entry_points] + console_scripts = main = mypkg:some_func When this project is installed, a ``main`` script will be installed and will -- cgit v1.2.1 From 0e1fc1c6318864ab70dc0868762e02fa8faaaf8e Mon Sep 17 00:00:00 2001 From: Marius Gedminas Date: Mon, 19 Oct 2020 10:06:57 +0300 Subject: s/517/PEP 517/ --- docs/userguide/quickstart.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 697087ed..874ac086 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -21,7 +21,7 @@ the backend (build system) it wants to use. The distribution can then be generated with whatever tools that provides a ``build sdist``-alike functionality. While this may appear cumbersome, given the added pieces, it in fact tremendously enhances the portability of your package. The -change is driven under :pep:`517 <517#build-requirements>`. To learn more about Python packaging in general, +change is driven under :pep:`PEP 517 <517#build-requirements>`. To learn more about Python packaging in general, navigate to the `bottom `_ of this page. -- cgit v1.2.1 From d7170a28dc3ad02eacc69d1c425bb6f1d5afe619 Mon Sep 17 00:00:00 2001 From: Greg Solon Date: Tue, 20 Oct 2020 21:55:56 +0800 Subject: Update quickstart.rst Removed quotes in setup.cfg which caused build to fail. --- docs/userguide/quickstart.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 697087ed..a9cb76a4 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -43,11 +43,11 @@ such as metadata, contents, dependencies, etc. Here we demonstrate the minimum .. code-block:: ini [metadata] - name = "mypackage" + name = mypackage version = 0.0.1 [options] - packages = "mypackage" + packages = mypackage install_requires = requests importlib; python_version == "2.6" -- cgit v1.2.1 From b20d12e1fb7132fada3e6b58ec1c1c0bd409c5f7 Mon Sep 17 00:00:00 2001 From: Harald Korneliussen Date: Wed, 18 Nov 2020 19:32:18 +0100 Subject: Fixes syntax issues in quickstart (#2448) Quotes in the name and packages field causes an "Invalid distribution name or version syntax" if you follow this quickstart guide directly. pep517.build also requires you to specify the directory. --- docs/userguide/quickstart.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 697087ed..50a984ec 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -43,11 +43,11 @@ such as metadata, contents, dependencies, etc. Here we demonstrate the minimum .. code-block:: ini [metadata] - name = "mypackage" + name = mypackage version = 0.0.1 [options] - packages = "mypackage" + packages = mypackage install_requires = requests importlib; python_version == "2.6" @@ -63,7 +63,7 @@ Then, you need an installer, such as `pep517 ` which you can obtain via ``pip install pep517``. After downloading it, invoke the installer:: - python -m pep517.build + python -m pep517.build . You now have your distribution ready (e.g. a ``tar.gz`` file and a ``.whl`` file in the ``dist`` directory), which you can upload to PyPI! -- cgit v1.2.1 From 9008e48a54bde1cbbabaf4423906630a4edab877 Mon Sep 17 00:00:00 2001 From: Matt Deitke Date: Sun, 13 Dec 2020 20:42:20 -0800 Subject: typo --- docs/userguide/quickstart.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 30989826..1d557d47 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -71,7 +71,7 @@ file in the ``dist`` directory), which you can upload to PyPI! 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. In the next few section, +dependencies, and perhaps some data files and scripts. In the next few sections, we will walk through those additional but essential information you need to specify to properly package your project. -- cgit v1.2.1 From 13d7bcb994097895ed7f6c6af419e3a037fe90a7 Mon Sep 17 00:00:00 2001 From: Daniel Moore Date: Wed, 23 Dec 2020 14:39:27 -0800 Subject: Clarify Development Mode first paragraph --- docs/userguide/development_mode.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/development_mode.rst b/docs/userguide/development_mode.rst index bce724a7..3c477ec1 100644 --- a/docs/userguide/development_mode.rst +++ b/docs/userguide/development_mode.rst @@ -3,9 +3,9 @@ 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. +form. However, if you were to use the ``distutils`` to build a distribution, +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 -- cgit v1.2.1 From 80c11d910346ab7df8349cb54c7b9227664fe3e7 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Mon, 28 Dec 2020 17:49:26 +0000 Subject: Drop table of contents from pages This is included in the sidebar, as part of Furo. --- docs/userguide/dependency_management.rst | 6 ++---- docs/userguide/quickstart.rst | 2 -- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.rst b/docs/userguide/dependency_management.rst index 354a9f8c..81ee226b 100644 --- a/docs/userguide/dependency_management.rst +++ b/docs/userguide/dependency_management.rst @@ -11,8 +11,6 @@ dependency. version by following `PEP 440 `_ -.. contents:: - Build system requirement ======================== @@ -72,7 +70,7 @@ When your project is installed (e.g. using pip), all of the dependencies not already installed will be located (via PyPI), downloaded, built (if necessary), and installed and 2) Any scripts in your project will be installed with wrappers that verify the availability of the specified dependencies at runtime. - + Platform specific dependencies ------------------------------ @@ -202,7 +200,7 @@ Optional dependencies Setuptools allows you to declare dependencies that only get installed under specific circumstances. These dependencies are specified with ``extras_require`` keyword and are only installed if another package depends on it (either -directly or indirectly) This makes it convenient to declare dependencies for +directly or indirectly) This makes it convenient to declare dependencies for ancillary functions such as "tests" and "docs". .. note:: diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 1d557d47..aa09e54d 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -2,8 +2,6 @@ ``setuptools`` Quickstart ========================== -.. contents:: - Installation ============ -- cgit v1.2.1 From c657e826e0d4f24a3702763ab25610d48ceea222 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Mon, 28 Dec 2020 15:05:45 -0500 Subject: Replace incorrect statement about triggering installation of dependencies to indicate that the handling is mostly implementation specific. Ref pypa/setuptools#1471. --- docs/userguide/dependency_management.rst | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.rst b/docs/userguide/dependency_management.rst index 354a9f8c..0eb21864 100644 --- a/docs/userguide/dependency_management.rst +++ b/docs/userguide/dependency_management.rst @@ -72,7 +72,7 @@ When your project is installed (e.g. using pip), all of the dependencies not already installed will be located (via PyPI), downloaded, built (if necessary), and installed and 2) Any scripts in your project will be installed with wrappers that verify the availability of the specified dependencies at runtime. - + Platform specific dependencies ------------------------------ @@ -202,7 +202,7 @@ Optional dependencies Setuptools allows you to declare dependencies that only get installed under specific circumstances. These dependencies are specified with ``extras_require`` keyword and are only installed if another package depends on it (either -directly or indirectly) This makes it convenient to declare dependencies for +directly or indirectly) This makes it convenient to declare dependencies for ancillary functions such as "tests" and "docs". .. note:: @@ -262,8 +262,12 @@ First is the console_scripts entry point: } ) -When the script ``rst2pdf`` is run, it will trigger the installation of -the two dependencies ``PDF`` maps to. +This syntax indicates that the entry point (in this case a console script) +is only valid when the PDF extra is installed. It is up to the installer +to determine how to handle the situation where PDF was not indicated +(e.g. omit the console script, provide a warning when attempting to load +the entry point, assume the extras are present and let the implementation +fail later). The second use case is that other package can use this "extra" for their own dependencies. For example, if "Project-B" needs "project A" with PDF support -- cgit v1.2.1 From c1b2b1a60f7d099e841d6bbcac3531c5cb2efc1b Mon Sep 17 00:00:00 2001 From: YuanPei Li Date: Fri, 8 Jan 2021 17:35:33 +0800 Subject: fix typo Fix a difference between the name of function definition and calling. --- docs/userguide/entry_point.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/entry_point.rst b/docs/userguide/entry_point.rst index edab4465..73820728 100644 --- a/docs/userguide/entry_point.rst +++ b/docs/userguide/entry_point.rst @@ -28,7 +28,7 @@ with ``__init__.py`` as: .. code-block:: python - def helloworld(): + def hello_world(): print("Hello world") and ``__main__.py`` providing a hook: -- cgit v1.2.1 From 14f91af8370eaa1c7c7c19510aa9d4d5a65c069d Mon Sep 17 00:00:00 2001 From: Pablo Woolvett Date: Thu, 4 Feb 2021 13:59:15 -0300 Subject: docs(userguide): Marker example for extras_require Signed-off-by: Pablo Woolvett --- docs/userguide/declarative_config.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'docs/userguide') diff --git a/docs/userguide/declarative_config.rst b/docs/userguide/declarative_config.rst index bc66869b..f2e8b81f 100644 --- a/docs/userguide/declarative_config.rst +++ b/docs/userguide/declarative_config.rst @@ -243,6 +243,19 @@ data_files dict 40.6.0 **find_namespace directive** - The ``find_namespace:`` directive is supported since Python >=3.3. + Notes: 1. In the ``package_data`` section, a key named with a single asterisk (``*``) refers to all packages, in lieu of the empty string used in ``setup.py``. + +2. In the ``extras_require`` section, values are parsed as ``list-semi``. This implies that in +order to include markers, they **must** be *dangling*: + +.. code-block:: ini + + [options.extras_require] + rest = docutils>=0.3; pack ==1.1, ==1.3 + pdf = + ReportLab>=1.2 + RXP + importlib-metadata; python_version < "3.8" -- cgit v1.2.1 From e70c2afc1868a7d9bb2e2887ebf19f6c84dcf283 Mon Sep 17 00:00:00 2001 From: Andrey Bienkowski Date: Tue, 9 Feb 2021 09:20:47 +0300 Subject: quickstart: recommend PyPA build instead of pep517.build see https://github.com/pypa/pep517/issues/91 --- docs/userguide/quickstart.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 1d557d47..e7594ba3 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -59,11 +59,11 @@ This is what your project would look like:: setup.cfg mypackage/__init__.py -Then, you need an installer, such as `pep517 `_ -which you can obtain via ``pip install pep517``. After downloading it, invoke +Then, you need an installer, such as :std:doc:`PyPA build ` +which you can obtain via ``pip install build``. After downloading it, invoke the installer:: - python -m pep517.build . + python -m build You now have your distribution ready (e.g. a ``tar.gz`` file and a ``.whl`` file in the ``dist`` directory), which you can upload to PyPI! -- cgit v1.2.1 From 3dd8e559112d2b2af58caed77a105be7e925f1c4 Mon Sep 17 00:00:00 2001 From: Thea Date: Wed, 24 Feb 2021 23:12:59 +0100 Subject: Add ini to display code block in doc --- docs/userguide/entry_point.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/entry_point.rst b/docs/userguide/entry_point.rst index 73820728..63d30a48 100644 --- a/docs/userguide/entry_point.rst +++ b/docs/userguide/entry_point.rst @@ -64,7 +64,7 @@ After installing the package, a user may invoke that function by simply calling The syntax for entry points is specified as follows: -.. code-block:: +.. code-block:: ini = [.[.]][:.] -- cgit v1.2.1 From 8307bd497dba77f5ef40f504842e023334eba04b Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 28 Feb 2021 16:50:09 -0500 Subject: Term is builder. --- docs/userguide/quickstart.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index e7594ba3..75dc302f 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -59,9 +59,9 @@ This is what your project would look like:: setup.cfg mypackage/__init__.py -Then, you need an installer, such as :std:doc:`PyPA build ` +Then, you need an builder, such as :std:doc:`PyPA build ` which you can obtain via ``pip install build``. After downloading it, invoke -the installer:: +the builder:: python -m build -- cgit v1.2.1 From 474f833a1181ca07b17fe4c52a9680c70335181e Mon Sep 17 00:00:00 2001 From: Amy Date: Sun, 28 Feb 2021 23:07:47 -0500 Subject: Replace adjacent code blocks with tabbed containers --- docs/userguide/dependency_management.rst | 228 +++++++++++++++++-------------- docs/userguide/package_discovery.rst | 112 ++++++++------- docs/userguide/quickstart.rst | 43 ++++-- 3 files changed, 223 insertions(+), 160 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.rst b/docs/userguide/dependency_management.rst index 0eb21864..6108d9b2 100644 --- a/docs/userguide/dependency_management.rst +++ b/docs/userguide/dependency_management.rst @@ -49,23 +49,27 @@ be able to run. ``setuptools`` support automatically download and install these dependencies when the package is installed. Although there is more finess to it, let's start with a simple example. -.. code-block:: ini +.. tab:: setup.cfg - [options] - #... - install_requires = - docutils - BazSpam ==1.1 + .. code-block:: ini + + [options] + #... + install_requires = + docutils + BazSpam ==1.1 + +.. tab:: setup.py -.. code-block:: python + .. code-block:: python - setup( - #..., - install_requires = [ - 'docutils', - 'BazSpam ==1.1' - ] - ) + setup( + #..., + install_requires = [ + 'docutils', + 'BazSpam ==1.1' + ] + ) When your project is installed (e.g. using pip), all of the dependencies not @@ -82,41 +86,49 @@ specific dependencies. For example, the ``enum`` package was added in Python 3.4, therefore, package that depends on it can elect to install it only when the Python version is older than 3.4. To accomplish this -.. code-block:: ini - - [options] - #... - install_requires = - enum34;python_version<'3.4' +.. tab:: setup.cfg -.. code-block:: python + .. code-block:: ini - setup( + [options] #... - install_requires=[ - "enum34;python_version<'3.4'",] - ) + install_requires = + enum34;python_version<'3.4' + +.. tab:: setup.py + + .. code-block:: python + + setup( + #... + install_requires=[ + "enum34;python_version<'3.4'",] + ) Similarly, if you also wish to declare ``pywin32`` with a minimal version of 1.0 and only install it if the user is using a Windows operating system: -.. code-block:: ini - - [options] - #... - install_requires = - enum34;python_version<'3.4' - pywin32 >= 1.0;platform_system=='Windows' +.. tab:: setup.cfg -.. code-block:: python + .. code-block:: ini - setup( + [options] #... - install_requires=[ - "enum34;python_version<'3.4'", - "pywin32 >= 1.0;platform_system=='Windows'" - ] - ) + install_requires = + enum34;python_version<'3.4' + pywin32 >= 1.0;platform_system=='Windows' + +.. tab:: setup.py + + .. code-block:: python + + setup( + #... + install_requires=[ + "enum34;python_version<'3.4'", + "pywin32 >= 1.0;platform_system=='Windows'" + ] + ) The environmental markers that may be used for testing platform types are detailed in `PEP 508 `_. @@ -181,20 +193,24 @@ The ``dependency_links`` option takes the form of a list of URL strings. For example, this will cause a search of the specified page for eggs or source distributions, if the package's dependencies aren't already installed: -.. code-block:: ini - - [options] - #... - dependency_links = http://peak.telecommunity.com/snapshots/ +.. tab:: setup.cfg -.. code-block:: python + .. code-block:: ini - setup( + [options] #... - dependency_links=[ - "http://peak.telecommunity.com/snapshots/" - ], - ) + dependency_links = http://peak.telecommunity.com/snapshots/ + +.. tab:: setup.py + + .. code-block:: python + + setup( + #... + dependency_links=[ + "http://peak.telecommunity.com/snapshots/" + ], + ) Optional dependencies @@ -211,24 +227,28 @@ ancillary functions such as "tests" and "docs". For example, Package-A offers optional PDF support and requires two other dependencies for it to work: -.. code-block:: ini +.. tab:: setup.cfg - [metadata] - name = Package-A + .. code-block:: ini - [options.extras_require] - PDF = ReportLab>=1.2; RXP + [metadata] + name = Package-A + [options.extras_require] + PDF = ReportLab>=1.2; RXP -.. code-block:: python - setup( - name="Project-A", - #... - extras_require={ - "PDF": ["ReportLab>=1.2", "RXP"], - } - ) +.. tab:: setup.py + + .. code-block:: python + + setup( + name="Project-A", + #... + extras_require={ + "PDF": ["ReportLab>=1.2", "RXP"], + } + ) The name ``PDF`` is an arbitary identifier of such a list of dependencies, to which other components can refer and have them installed. There are two common @@ -236,31 +256,35 @@ use cases. First is the console_scripts entry point: -.. code-block:: ini +.. tab:: setup.cfg - [metadata] - name = Project A - #... + .. code-block:: ini - [options] - #... - entry_points= - [console_scripts] - rst2pdf = project_a.tools.pdfgen [PDF] - rst2html = project_a.tools.htmlgen - -.. code-block:: python - - setup( - name = "Project-A" - #..., - entry_points={ - "console_scripts": [ - "rst2pdf = project_a.tools.pdfgen [PDF]", - "rst2html = project_a.tools.htmlgen", - ], - } - ) + [metadata] + name = Project A + #... + + [options] + #... + entry_points= + [console_scripts] + rst2pdf = project_a.tools.pdfgen [PDF] + rst2html = project_a.tools.htmlgen + +.. tab:: setup.py + + .. code-block:: python + + setup( + name = "Project-A" + #..., + entry_points={ + "console_scripts": [ + "rst2pdf = project_a.tools.pdfgen [PDF]", + "rst2html = project_a.tools.htmlgen", + ], + } + ) This syntax indicates that the entry point (in this case a console script) is only valid when the PDF extra is installed. It is up to the installer @@ -273,24 +297,28 @@ The second use case is that other package can use this "extra" for their own dependencies. For example, if "Project-B" needs "project A" with PDF support installed, it might declare the dependency like this: -.. code-block:: ini +.. tab:: setup.cfg - [metadata] - name = Project-B - #... + .. code-block:: ini - [options] - #... - install_requires = - Project-A[PDF] + [metadata] + name = Project-B + #... + + [options] + #... + install_requires = + Project-A[PDF] + +.. tab:: setup.py -.. code-block:: python + .. code-block:: python - setup( - name="Project-B", - install_requires=["Project-A[PDF]"], - ... - ) + 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 diff --git a/docs/userguide/package_discovery.rst b/docs/userguide/package_discovery.rst index de4ef668..842ade82 100644 --- a/docs/userguide/package_discovery.rst +++ b/docs/userguide/package_discovery.rst @@ -19,36 +19,44 @@ Package Discovery and Namespace Package support for namespace package. Normally, you would specify the package to be included manually in the following manner: -.. code-block:: ini - - [options] - #... - packages = - mypkg1 - mypkg2 +.. tab:: setup.cfg -.. code-block:: python + .. code-block:: ini - setup( + [options] #... - packages = ['mypkg1', 'mypkg2'] - ) + packages = + mypkg1 + mypkg2 + +.. tab:: setup.py + + .. code-block:: python + + setup( + #... + packages = ['mypkg1', 'mypkg2'] + ) This can get tiresome reallly quickly. To speed things up, we introduce two functions provided by setuptools: -.. code-block:: ini +.. tab:: setup.cfg - [options] - packages = find: - #or - packages = find_namespace: + .. code-block:: ini -.. code-block:: python + [options] + packages = find: + #or + packages = find_namespace: - from setuptools import find_packages - #or - from setuptools import find_namespace_packages +.. tab:: setup.py + + .. code-block:: python + + from setuptools import find_packages + #or + from setuptools import find_namespace_packages Using ``find:`` or ``find_packages`` @@ -71,30 +79,34 @@ it, consider the following directory To have your setup.cfg or setup.py to automatically include packages found in ``src`` that starts with the name ``pkg`` and not ``additional``: -.. code-block:: ini +.. tab:: setup.cfg - [options] - packages = find: - package_dir = - =src + .. code-block:: ini - [options.packages.find] - where = src - include = pkg* - exclude = additional + [options] + packages = find: + package_dir = + =src -.. code-block:: python + [options.packages.find] + where = src + include = pkg* + exclude = additional - setup( - #... - packages = find_packages( - where = 'src', - include = ['pkg*',], - exclude = ['additional',] - ), - package_dir = {"":"src"} - #... - ) +.. tab:: setup.py + + .. code-block:: python + + setup( + #... + packages = find_packages( + where = 'src', + include = ['pkg*',], + exclude = ['additional',] + ), + package_dir = {"":"src"} + #... + ) .. _Namespace Packages: @@ -195,17 +207,21 @@ following: And the ``namespace_packages`` keyword in your ``setup.cfg`` or ``setup.py``: -.. code-block:: ini +.. tab:: setup.cfg - [options] - namespace_packages = timmins + .. code-block:: ini -.. code-block:: python + [options] + namespace_packages = timmins + +.. tab:: setup.py + + .. code-block:: python - setup( - # ... - namespace_packages = ['timmins'] - ) + setup( + # ... + namespace_packages = ['timmins'] + ) And your directory should look like this diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 1d557d47..16cd4f71 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -37,26 +37,45 @@ package your project: requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" -Then, you will need a ``setup.cfg`` to specify your package information, -such as metadata, contents, dependencies, etc. Here we demonstrate the minimum +Then, you will need a ``setup.cfg`` or ``setup.py`` to specify your package +information, such as metadata, contents, dependencies, etc. Here we demonstrate +the minimum -.. code-block:: ini +.. tab:: setup.cfg - [metadata] - name = mypackage - version = 0.0.1 + .. code-block:: ini - [options] - packages = mypackage - install_requires = - requests - importlib; python_version == "2.6" + [metadata] + name = mypackage + version = 0.0.1 + + [options] + packages = mypackage + install_requires = + requests + importlib; python_version == "2.6" + +.. tab:: setup.py + + .. code-block:: python + + from setuptools import setup + + setup( + name='mypackage"' + version='0.0.1', + packages=['mypackage'], + install_requires=[ + 'requests', + 'importlib; python_version == "2.6"', + ], + ) This is what your project would look like:: ~/mypackage/ pyproject.toml - setup.cfg + setup.cfg # or setup.py mypackage/__init__.py Then, you need an installer, such as `pep517 `_ -- cgit v1.2.1 From c0b90dba0326d637ec44d2b67cb0fadcead1c640 Mon Sep 17 00:00:00 2001 From: Zack Didcott <66186954+Zedeldi@users.noreply.github.com> Date: Mon, 29 Mar 2021 00:26:32 +0000 Subject: Update dependency_management.rst Fix spelling and grammar --- docs/userguide/dependency_management.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.rst b/docs/userguide/dependency_management.rst index 6108d9b2..188083e0 100644 --- a/docs/userguide/dependency_management.rst +++ b/docs/userguide/dependency_management.rst @@ -3,7 +3,7 @@ Dependencies Management in Setuptools ===================================== There are three types of dependency styles offered by setuptools: -1) build system requirement, required dependency and 3) optional +1) build system requirement, 2) required dependency and 3) optional dependency. .. Note:: @@ -19,8 +19,8 @@ Build system requirement Package requirement ------------------- After organizing all the scripts and files and getting ready for packaging, -there needs to be a way to tell Python what programs it need to actually -do the packgaging (in our case, ``setuptools`` of course). Usually, +there needs to be a way to tell Python what programs it needs to actually +do the packaging (in our case, ``setuptools`` of course). Usually, you also need the ``wheel`` package as well since it is recommended that you upload a ``.whl`` file to PyPI alongside your ``.tar.gz`` file. Unlike the other two types of dependency keyword, this one is specified in your @@ -47,7 +47,7 @@ Declaring required dependency This is where a package declares its core dependencies, without which it won't be able to run. ``setuptools`` support automatically download and install these dependencies when the package is installed. Although there is more -finess to it, let's start with a simple example. +finesse to it, let's start with a simple example. .. tab:: setup.cfg -- cgit v1.2.1 From 07d5e663650f594288dda1c92f2cda010a2a899b Mon Sep 17 00:00:00 2001 From: "T. Wouters" Date: Mon, 29 Mar 2021 15:02:41 +0200 Subject: Fix typo in setup.py example in quickstart guide. --- docs/userguide/quickstart.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 7f111dd5..4ee59098 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -62,7 +62,7 @@ the minimum from setuptools import setup setup( - name='mypackage"' + name='mypackage' version='0.0.1', packages=['mypackage'], install_requires=[ -- cgit v1.2.1 From c91153a1bf73ceb65efd611603edf638a996f720 Mon Sep 17 00:00:00 2001 From: "T. Wouters" Date: Mon, 29 Mar 2021 15:10:26 +0200 Subject: Update quickstart.rst --- docs/userguide/quickstart.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 4ee59098..2807f59b 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -62,7 +62,7 @@ the minimum from setuptools import setup setup( - name='mypackage' + name='mypackage', version='0.0.1', packages=['mypackage'], install_requires=[ -- cgit v1.2.1 From 6dffcbe97d556809788afb8bed66ac4860c0d939 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Tue, 30 Mar 2021 22:00:07 -0400 Subject: Section for 'find' and 'find_namespace' options is 'options.packages.find'. Fixes #2406. --- docs/userguide/package_discovery.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/package_discovery.rst b/docs/userguide/package_discovery.rst index 842ade82..0a8070ae 100644 --- a/docs/userguide/package_discovery.rst +++ b/docs/userguide/package_discovery.rst @@ -156,7 +156,7 @@ to use ``find_namespace:``: =src packages = find_namespace: - [options.packages.find_namespace] + [options.packages.find] where = src When you install the zipped distribution, ``timmins.foo`` would become -- cgit v1.2.1 From 91e7956d961ef84080c30eb5253c220fa3b001dc Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Sun, 28 Mar 2021 13:39:35 +0200 Subject: Add documentation + changelog entries --- docs/userguide/declarative_config.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/declarative_config.rst b/docs/userguide/declarative_config.rst index f2e8b81f..7c97ca1c 100644 --- a/docs/userguide/declarative_config.rst +++ b/docs/userguide/declarative_config.rst @@ -184,7 +184,7 @@ maintainer_email maintainer-email str classifiers classifier file:, list-comma license str license_file str -license_files list-comma +license_files list-comma 42.0.0 description summary file:, str long_description long-description file:, str long_description_content_type str 38.6.0 -- cgit v1.2.1 From f42783143ccf803987e2ee82ee3ba12a26a31e01 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Sat, 10 Apr 2021 10:23:44 +0200 Subject: Fixed quickstart packaging resources hyperlink. The implicit link target that should have been created from the title was not being detected correctly. This was causing the link to be interpreted as an external hyperlink reference, resulting in a 404 in the rendered docs. Adding the explicit target and `ref` allows the link to resolve correctly. --- docs/userguide/quickstart.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 2807f59b..53810526 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -22,7 +22,7 @@ be generated with whatever tools that provides a ``build sdist``-alike functionality. While this may appear cumbersome, given the added pieces, it in fact tremendously enhances the portability of your package. The change is driven under :pep:`PEP 517 <517#build-requirements>`. To learn more about Python packaging in general, -navigate to the `bottom `_ of this page. +navigate to the :ref:`bottom ` of this page. Basic Use @@ -215,13 +215,14 @@ basic use here. Transitioning from ``setup.py`` to ``setup.cfg`` -================================================== +================================================ To avoid executing arbitary scripts and boilerplate code, we are transitioning into a full-fledged ``setup.cfg`` to declare your package information instead of running ``setup()``. This inevitably brings challenges due to a different syntax. Here we provide a quick guide to understanding how ``setup.cfg`` is parsed by ``setuptool`` to ease the pain of transition. +.. _packaging-resources: Resources on Python packaging ============================= -- cgit v1.2.1 From 6f727262240e35e315a66ec0bbb845ad718be127 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Mon, 12 Apr 2021 20:39:54 +0200 Subject: Corrected indent in setup.cfg example. --- docs/userguide/quickstart.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 2807f59b..7435d842 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -52,8 +52,8 @@ the minimum [options] packages = mypackage install_requires = - requests - importlib; python_version == "2.6" + requests + importlib; python_version == "2.6" .. tab:: setup.py -- cgit v1.2.1 From dda5620ffae39d23dc303284d28fe693ff5e7b25 Mon Sep 17 00:00:00 2001 From: Carlton Gibson Date: Mon, 10 May 2021 09:31:57 +0200 Subject: Corrected tabs for spaces in quickstart example. --- docs/userguide/quickstart.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index a9f0bbae..69400450 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -52,8 +52,8 @@ the minimum [options] packages = mypackage install_requires = - requests - importlib; python_version == "2.6" + requests + importlib; python_version == "2.6" .. tab:: setup.py -- cgit v1.2.1 From c063b3af1ecbcea0f0cc63b941f5e2038be9efcb Mon Sep 17 00:00:00 2001 From: luz paz Date: Fri, 14 May 2021 08:34:17 -0400 Subject: Fix misc. doc typos Found via `codespell` --- docs/userguide/dependency_management.rst | 2 +- docs/userguide/quickstart.rst | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.rst b/docs/userguide/dependency_management.rst index 188083e0..c6333a10 100644 --- a/docs/userguide/dependency_management.rst +++ b/docs/userguide/dependency_management.rst @@ -250,7 +250,7 @@ dependencies for it to work: } ) -The name ``PDF`` is an arbitary identifier of such a list of dependencies, to +The name ``PDF`` is an arbitrary identifier of such a list of dependencies, to which other components can refer and have them installed. There are two common use cases. diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index a9f0bbae..5d4dd37b 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -173,7 +173,7 @@ Including Data Files ==================== The distutils have traditionally allowed installation of "data files", which are placed in a platform-specific location. Setuptools offers three ways to -specify data files to be included in your packages. For the simpliest use, you +specify data files to be included in your packages. For the simplest use, you can simply use the ``include_package_data`` keyword: .. code-block:: ini @@ -189,7 +189,7 @@ For more details, see :doc:`datafiles` Development mode ================ ``setuptools`` allows you to install a package without copying any files -to your interpretor directory (e.g. the ``site-packages`` directory). This +to your interpreter directory (e.g. the ``site-packages`` directory). This allows you to modify your source code and have the changes take effect without you having to rebuild and reinstall. This is currently incompatible with PEP 517 and therefore it requires a ``setup.py`` script with the following @@ -202,7 +202,7 @@ Then:: pip install --editable . -This creates a link file in your interpretor site package directory which +This creates a link file in your interpreter site package directory which associate with your source code. For more information, see: (WIP) @@ -216,7 +216,7 @@ basic use here. Transitioning from ``setup.py`` to ``setup.cfg`` ================================================ -To avoid executing arbitary scripts and boilerplate code, we are transitioning +To avoid executing arbitrary scripts and boilerplate code, we are transitioning into a full-fledged ``setup.cfg`` to declare your package information instead of running ``setup()``. This inevitably brings challenges due to a different syntax. Here we provide a quick guide to understanding how ``setup.cfg`` is -- cgit v1.2.1 From 3bf8fc6c9a680f0295b9d5529d6f7e334cdbaa21 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Tue, 18 May 2021 08:51:29 +0300 Subject: Docs: Use license_files instead of license_file --- docs/userguide/declarative_config.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/declarative_config.rst b/docs/userguide/declarative_config.rst index 7c97ca1c..6d9d2e2a 100644 --- a/docs/userguide/declarative_config.rst +++ b/docs/userguide/declarative_config.rst @@ -183,8 +183,7 @@ maintainer str maintainer_email maintainer-email str classifiers classifier file:, list-comma license str -license_file str -license_files list-comma 42.0.0 +license_files license_file list-comma 42.0.0 description summary file:, str long_description long-description file:, str long_description_content_type str 38.6.0 -- cgit v1.2.1 From d33912592f2f4fca6c931a78c0ff3e48776cafb7 Mon Sep 17 00:00:00 2001 From: Nicolas CANIART Date: Tue, 9 Mar 2021 09:37:13 +0100 Subject: Entrypoints in declarative config are now supported The documentation still states it is not though. Co-authored-by: Sviatoslav Sydorenko --- docs/userguide/declarative_config.rst | 146 +++++++++++++++++++++------------- 1 file changed, 89 insertions(+), 57 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/declarative_config.rst b/docs/userguide/declarative_config.rst index 6d9d2e2a..128d9f97 100644 --- a/docs/userguide/declarative_config.rst +++ b/docs/userguide/declarative_config.rst @@ -18,15 +18,7 @@ to the ``setup()`` function (declarative config). This approach not only allows automation scenarios but also reduces boilerplate code in some cases. -.. note:: - - This implementation has limited compatibility with the distutils2-like - ``setup.cfg`` sections used by the ``pbr`` and ``d2to1`` packages. - - Namely: only metadata-related keys from ``metadata`` section are supported - (except for ``description-file``); keys from ``files``, ``entry_points`` - and ``backwards_compat`` are not supported. - +.. _example-setup-config: .. code-block:: ini @@ -58,6 +50,10 @@ boilerplate code in some cases. * = *.txt, *.rst hello = *.msg + [options.entry_points] + console_scripts = + executable-name = package.module:function + [options.extras_require] pdf = ReportLab>=1.2; RXP rest = docutils>=0.3; pack ==1.1, ==1.3 @@ -156,10 +152,9 @@ Special directives: * ``file:`` - Value is read from a list of files and then concatenated - -.. note:: - The ``file:`` directive is sandboxed and won't reach anything outside - the directory containing ``setup.py``. + .. note:: + The ``file:`` directive is sandboxed and won't reach anything outside + the directory containing ``setup.py``. Metadata @@ -169,11 +164,11 @@ Metadata The aliases given below are supported for compatibility reasons, but their use is not advised. -============================== ================= ================= =============== ===== +============================== ================= ================= =============== ========== Key Aliases Type Minimum Version Notes -============================== ================= ================= =============== ===== +============================== ================= ================= =============== ========== name str -version attr:, file:, str 39.2.0 (1) +version attr:, file:, str 39.2.0 [#meta-1]_ url home-page str download_url download-url str project_urls dict 38.3.0 @@ -192,28 +187,29 @@ platforms platform list-comma provides list-comma requires list-comma obsoletes list-comma -============================== ================= ================= =============== ===== +============================== ================= ================= =============== ========== -.. note:: - A version loaded using the ``file:`` directive must comply with PEP 440. - It is easy to accidentally put something other than a valid version - string in such a file, so validation is stricter in this case. +**Notes**: + +.. [#meta-1] The ``version`` file attribute has only been supported since 39.2.0. + + A version loaded using the ``file:`` directive must comply with PEP 440. + It is easy to accidentally put something other than a valid version + string in such a file, so validation is stricter in this case. -Notes: -1. The ``version`` file attribute has only been supported since 39.2.0. Options ------- -======================= =================================== =============== ===== +======================= =================================== =============== ========= Key Type Minimum Version Notes -======================= =================================== =============== ===== +======================= =================================== =============== ========= zip_safe bool setup_requires list-semi install_requires list-semi -extras_require section +extras_require section [#opt-2]_ python_requires str -entry_points file:, section +entry_points file:, section 51.0.0 use_2to3 bool use_2to3_fixers list-comma use_2to3_exclude_fixers list-comma @@ -223,38 +219,74 @@ eager_resources list-comma dependency_links list-comma tests_require list-semi include_package_data bool -packages find:, find_namespace:, list-comma +packages find:, find_namespace:, list-comma [#opt-3]_ package_dir dict -package_data section (1) +package_data section [#opt-1]_ exclude_package_data section namespace_packages list-comma py_modules list-comma data_files dict 40.6.0 -======================= =================================== =============== ===== - -.. note:: - - **packages** - The ``find:`` and ``find_namespace:`` directive can be further configured - in a dedicated subsection ``options.packages.find``. This subsection - accepts the same keys as the ``setuptools.find_packages`` and the - ``setuptools.find_namespace_packages`` function: - ``where``, ``include``, and ``exclude``. - - **find_namespace directive** - The ``find_namespace:`` directive is supported since Python >=3.3. - - -Notes: -1. In the ``package_data`` section, a key named with a single asterisk (``*``) -refers to all packages, in lieu of the empty string used in ``setup.py``. - -2. In the ``extras_require`` section, values are parsed as ``list-semi``. This implies that in -order to include markers, they **must** be *dangling*: - -.. code-block:: ini - - [options.extras_require] - rest = docutils>=0.3; pack ==1.1, ==1.3 - pdf = - ReportLab>=1.2 - RXP - importlib-metadata; python_version < "3.8" +======================= =================================== =============== ========= + +**Notes**: + +.. [#opt-1] In the ``package_data`` section, a key named with a single asterisk + (``*``) refers to all packages, in lieu of the empty string used in ``setup.py``. + +.. [#opt-2] In the ``extras_require`` section, values are parsed as ``list-semi``. + This implies that in order to include markers, they **must** be *dangling*: + + .. code-block:: ini + + [options.extras_require] + rest = docutils>=0.3; pack ==1.1, ==1.3 + pdf = + ReportLab>=1.2 + RXP + importlib-metadata; python_version < "3.8" + +.. [#opt-3] The ``find:`` and ``find_namespace:`` directive can be further configured + in a dedicated subsection ``options.packages.find``. This subsection accepts the + same keys as the ``setuptools.find_packages`` and the + ``setuptools.find_namespace_packages`` function: + ``where``, ``include``, and ``exclude``. + + The ``find_namespace:`` directive is supported since Python >=3.3. + + +Compatibility with other tools +============================== + +Historically, several tools explored declarative package configuration +in parallel. And several of them chose to place the packaging +configuration within the project's :file:`setup.cfg` file. +One of the first was ``distutils2``, which development has stopped in +2013. Other include ``pbr`` which is still under active development or +``d2to1``, which was a plug-in that backports declarative configuration +to ``distutils``, but has had no release since Oct. 2015. +As a way to harmonize packaging tools, ``setuptools``, having held the +position of *de facto* standard, has gradually integrated those +features as part of its core features. + +Still this has lead to some confusion and feature incompatibilities: + +- some tools support features others don't; +- some have similar features but the declarative syntax differs; + +The table below tries to summarize the differences. But, please, refer +to each tool documentation for up-to-date information. + +=========================== ========== ========== ===== === +feature setuptools distutils2 d2to1 pbr +=========================== ========== ========== ===== === +[metadata] description-file S Y Y Y +[files] S Y Y Y +entry_points Y Y Y S +[backwards_compat] N Y Y Y +=========================== ========== ========== ===== === + +Y: supported, N: unsupported, S: syntax differs (see +:ref:`above example`). + +Also note that some features were only recently added to ``setuptools``. +Please refer to the previous sections to find out when. -- cgit v1.2.1 From 36b4820f519d93bad998302141ae6de2cb15191c Mon Sep 17 00:00:00 2001 From: Alan Fregtman <941331+darkvertex@users.noreply.github.com> Date: Wed, 30 Jun 2021 01:15:18 -0400 Subject: Implement "glob:" directive for declarative "data_files" option. --- docs/userguide/declarative_config.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/declarative_config.rst b/docs/userguide/declarative_config.rst index 128d9f97..dcab0b3a 100644 --- a/docs/userguide/declarative_config.rst +++ b/docs/userguide/declarative_config.rst @@ -68,6 +68,7 @@ boilerplate code in some cases. site.d/00_default.conf host.d/00_default.conf data = data/img/logo.png, data/svg/icon.svg + fonts = glob: data/fonts/*.ttf, glob: data/fonts/*.otf Metadata and options are set in the config sections of the same name. @@ -156,6 +157,8 @@ Special directives: The ``file:`` directive is sandboxed and won't reach anything outside the directory containing ``setup.py``. +* ``glob:`` - Value will be treated as a glob() pattern and expanded accordingly. + Metadata -------- @@ -225,7 +228,7 @@ package_data section [# exclude_package_data section namespace_packages list-comma py_modules list-comma -data_files dict 40.6.0 +data_files glob:, dict 40.6.0 ======================= =================================== =============== ========= **Notes**: -- cgit v1.2.1 From 45f900b7bf4aa300846727024672c5d49b1b14cf Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Tue, 20 Jul 2021 10:34:10 +0100 Subject: blacken docs --- docs/userguide/dependency_management.rst | 42 +++++++++++++------------------- docs/userguide/entry_point.rst | 12 +++++---- docs/userguide/extension.rst | 2 +- docs/userguide/package_discovery.rst | 31 +++++++++++++---------- docs/userguide/quickstart.rst | 8 +++--- 5 files changed, 47 insertions(+), 48 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.rst b/docs/userguide/dependency_management.rst index 1c610790..9071753d 100644 --- a/docs/userguide/dependency_management.rst +++ b/docs/userguide/dependency_management.rst @@ -62,11 +62,8 @@ finesse to it, let's start with a simple example. .. code-block:: python setup( - #..., - install_requires = [ - 'docutils', - 'BazSpam ==1.1' - ] + # ..., + install_requires=["docutils", "BazSpam ==1.1"] ) @@ -98,9 +95,10 @@ the Python version is older than 3.4. To accomplish this .. code-block:: python setup( - #... + # ... install_requires=[ - "enum34;python_version<'3.4'",] + "enum34;python_version<'3.4'", + ] ) Similarly, if you also wish to declare ``pywin32`` with a minimal version of 1.0 @@ -121,11 +119,11 @@ and only install it if the user is using a Windows operating system: .. code-block:: python setup( - #... + # ... install_requires=[ "enum34;python_version<'3.4'", - "pywin32 >= 1.0;platform_system=='Windows'" - ] + "pywin32 >= 1.0;platform_system=='Windows'", + ] ) The environmental markers that may be used for testing platform types are @@ -204,10 +202,8 @@ distributions, if the package's dependencies aren't already installed: .. code-block:: python setup( - #... - dependency_links=[ - "http://peak.telecommunity.com/snapshots/" - ], + # ... + dependency_links=["http://peak.telecommunity.com/snapshots/"], ) @@ -242,10 +238,10 @@ dependencies for it to work: setup( name="Project-A", - #... + # ... extras_require={ - "PDF": ["ReportLab>=1.2", "RXP"], - } + "PDF": ["ReportLab>=1.2", "RXP"], + }, ) The name ``PDF`` is an arbitrary identifier of such a list of dependencies, to @@ -274,14 +270,14 @@ First is the console_scripts entry point: .. code-block:: python setup( - name = "Project-A" - #..., + name="Project-A", + ..., entry_points={ "console_scripts": [ "rst2pdf = project_a.tools.pdfgen [PDF]", "rst2html = project_a.tools.htmlgen", ], - } + }, ) This syntax indicates that the entry point (in this case a console script) @@ -312,11 +308,7 @@ installed, it might declare the dependency like this: .. code-block:: python - setup( - name="Project-B", - install_requires=["Project-A[PDF]"], - ... - ) + 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 diff --git a/docs/userguide/entry_point.rst b/docs/userguide/entry_point.rst index 63d30a48..3244ce39 100644 --- a/docs/userguide/entry_point.rst +++ b/docs/userguide/entry_point.rst @@ -36,7 +36,8 @@ and ``__main__.py`` providing a hook: .. code-block:: python from . import hello_world - if __name__ == '__main__': + + if __name__ == "__main__": hello_world() After installing the package, the function may be invoked through the @@ -102,10 +103,10 @@ module (part of stdlib since Python 3.8) or its backport, For example, to find the console script entry points from the example above: -.. code-block:: python +.. code-block:: pycon >>> from importlib import metadata - >>> eps = metadata.entry_points()['console_scripts'] + >>> eps = metadata.entry_points()["console_scripts"] ``eps`` is now a list of ``EntryPoint`` objects, one of which corresponds to the ``hello-world = timmins:hello_world`` defined above. Each ``EntryPoint`` @@ -121,13 +122,14 @@ method to import and load that entry point (module or object). Then, a different project wishing to load 'my.plugins' plugins could run the following routine to load (and invoke) such plugins: -.. code-block:: python +.. code-block:: pycon >>> from importlib import metadata - >>> eps = metadata.entry_points()['my.plugins'] + >>> eps = metadata.entry_points()["my.plugins"] >>> for ep in eps: ... plugin = ep.load() ... plugin() + ... The project soliciting the entry points needs not to have any dependency or prior knowledge about the libraries implementing the entry points, and diff --git a/docs/userguide/extension.rst b/docs/userguide/extension.rst index 4de24ec9..93b59501 100644 --- a/docs/userguide/extension.rst +++ b/docs/userguide/extension.rst @@ -202,7 +202,7 @@ called "foobar", you would write a function something like this: .. code-block:: python def find_files_for_foobar(dirname): - # loop to yield paths that start with `dirname` + ... # loop to yield paths that start with `dirname` And you would register it in a setup script using something like this:: diff --git a/docs/userguide/package_discovery.rst b/docs/userguide/package_discovery.rst index 0a8070ae..e371e868 100644 --- a/docs/userguide/package_discovery.rst +++ b/docs/userguide/package_discovery.rst @@ -34,8 +34,8 @@ included manually in the following manner: .. code-block:: python setup( - #... - packages = ['mypkg1', 'mypkg2'] + # ... + packages=["mypkg1", "mypkg2"] ) This can get tiresome reallly quickly. To speed things up, we introduce two @@ -55,7 +55,8 @@ functions provided by setuptools: .. code-block:: python from setuptools import find_packages - #or + + # or from setuptools import find_namespace_packages @@ -98,14 +99,18 @@ in ``src`` that starts with the name ``pkg`` and not ``additional``: .. code-block:: python setup( - #... - packages = find_packages( - where = 'src', - include = ['pkg*',], - exclude = ['additional',] + # ... + packages=find_packages( + where="src", + include=[ + "pkg*", + ], + exclude=[ + "additional", + ], ), - package_dir = {"":"src"} - #... + package_dir={"": "src"} + # ... ) @@ -129,7 +134,7 @@ If both ``Desktop`` and ``Library`` are on your ``PYTHONPATH``, then a namespace package called ``timmins`` will be created automatically for you when you invoke the import mechanism, allowing you to accomplish the following -.. code-block:: python +.. code-block:: pycon >>> import timmins.foo >>> import timmins.bar @@ -220,7 +225,7 @@ And the ``namespace_packages`` keyword in your ``setup.cfg`` or ``setup.py``: setup( # ... - namespace_packages = ['timmins'] + namespace_packages=["timmins"] ) And your directory should look like this @@ -245,6 +250,6 @@ file contains the following: .. code-block:: python - __path__ = __import__('pkgutil').extend_path(__path__, __name__) + __path__ = __import__("pkgutil").extend_path(__path__, __name__) The project layout remains the same and ``setup.cfg`` remains the same. diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 1bd04ded..0ab23ca2 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -60,11 +60,11 @@ the minimum from setuptools import setup setup( - name='mypackage', - version='0.0.1', - packages=['mypackage'], + name="mypackage", + version="0.0.1", + packages=["mypackage"], install_requires=[ - 'requests', + "requests", 'importlib; python_version == "2.6"', ], ) -- cgit v1.2.1 From efb8bdc84abca2c88987c789fe52e968bab5efd1 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Wed, 21 Jul 2021 08:17:00 +0100 Subject: remove magci trailing commas --- docs/userguide/package_discovery.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/package_discovery.rst b/docs/userguide/package_discovery.rst index e371e868..e02035b3 100644 --- a/docs/userguide/package_discovery.rst +++ b/docs/userguide/package_discovery.rst @@ -102,12 +102,8 @@ in ``src`` that starts with the name ``pkg`` and not ``additional``: # ... packages=find_packages( where="src", - include=[ - "pkg*", - ], - exclude=[ - "additional", - ], + include=["pkg*"], + exclude=["additional"], ), package_dir={"": "src"} # ... -- cgit v1.2.1 From cb05fb0c94716b1d328ecca0573346218505b859 Mon Sep 17 00:00:00 2001 From: Alan Fregtman <941331+darkvertex@users.noreply.github.com> Date: Wed, 21 Jul 2021 17:34:14 -0400 Subject: Update globbing for [options.data_files] to be implicit, not requiring a custom directive. --- docs/userguide/declarative_config.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/declarative_config.rst b/docs/userguide/declarative_config.rst index dcab0b3a..3b72611c 100644 --- a/docs/userguide/declarative_config.rst +++ b/docs/userguide/declarative_config.rst @@ -68,7 +68,7 @@ boilerplate code in some cases. site.d/00_default.conf host.d/00_default.conf data = data/img/logo.png, data/svg/icon.svg - fonts = glob: data/fonts/*.ttf, glob: data/fonts/*.otf + fonts = data/fonts/*.ttf, data/fonts/*.otf Metadata and options are set in the config sections of the same name. @@ -157,8 +157,6 @@ Special directives: The ``file:`` directive is sandboxed and won't reach anything outside the directory containing ``setup.py``. -* ``glob:`` - Value will be treated as a glob() pattern and expanded accordingly. - Metadata -------- @@ -228,7 +226,7 @@ package_data section [# exclude_package_data section namespace_packages list-comma py_modules list-comma -data_files glob:, dict 40.6.0 +data_files dict 40.6.0 ======================= =================================== =============== ========= **Notes**: -- cgit v1.2.1 From db3dd226eb52d437dc8859e19dcef82cbbbba547 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Wed, 21 Jul 2021 18:05:12 -0400 Subject: Restore whitespace and single quotes after blacken-docs. --- docs/userguide/dependency_management.rst | 29 +++++++++++++++++++---------- docs/userguide/entry_point.rst | 6 +++--- docs/userguide/package_discovery.rst | 12 ++++++------ docs/userguide/quickstart.rst | 8 ++++---- 4 files changed, 32 insertions(+), 23 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.rst b/docs/userguide/dependency_management.rst index 9071753d..b97896ba 100644 --- a/docs/userguide/dependency_management.rst +++ b/docs/userguide/dependency_management.rst @@ -62,8 +62,11 @@ finesse to it, let's start with a simple example. .. code-block:: python setup( - # ..., - install_requires=["docutils", "BazSpam ==1.1"] + ..., + install_requires=[ + 'docutils', + 'BazSpam ==1.1', + ], ) @@ -95,10 +98,10 @@ the Python version is older than 3.4. To accomplish this .. code-block:: python setup( - # ... + ..., install_requires=[ "enum34;python_version<'3.4'", - ] + ], ) Similarly, if you also wish to declare ``pywin32`` with a minimal version of 1.0 @@ -119,11 +122,11 @@ and only install it if the user is using a Windows operating system: .. code-block:: python setup( - # ... + ..., install_requires=[ "enum34;python_version<'3.4'", "pywin32 >= 1.0;platform_system=='Windows'", - ] + ], ) The environmental markers that may be used for testing platform types are @@ -202,8 +205,10 @@ distributions, if the package's dependencies aren't already installed: .. code-block:: python setup( - # ... - dependency_links=["http://peak.telecommunity.com/snapshots/"], + ..., + dependency_links=[ + "http://peak.telecommunity.com/snapshots/", + ], ) @@ -238,7 +243,7 @@ dependencies for it to work: setup( name="Project-A", - # ... + ..., extras_require={ "PDF": ["ReportLab>=1.2", "RXP"], }, @@ -308,7 +313,11 @@ installed, it might declare the dependency like this: .. code-block:: python - setup(name="Project-B", install_requires=["Project-A[PDF]"], ...) + 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 diff --git a/docs/userguide/entry_point.rst b/docs/userguide/entry_point.rst index 3244ce39..c92ccf76 100644 --- a/docs/userguide/entry_point.rst +++ b/docs/userguide/entry_point.rst @@ -37,7 +37,7 @@ and ``__main__.py`` providing a hook: from . import hello_world - if __name__ == "__main__": + if __name__ == '__main__': hello_world() After installing the package, the function may be invoked through the @@ -106,7 +106,7 @@ For example, to find the console script entry points from the example above: .. code-block:: pycon >>> from importlib import metadata - >>> eps = metadata.entry_points()["console_scripts"] + >>> eps = metadata.entry_points()['console_scripts'] ``eps`` is now a list of ``EntryPoint`` objects, one of which corresponds to the ``hello-world = timmins:hello_world`` defined above. Each ``EntryPoint`` @@ -125,7 +125,7 @@ the following routine to load (and invoke) such plugins: .. code-block:: pycon >>> from importlib import metadata - >>> eps = metadata.entry_points()["my.plugins"] + >>> eps = metadata.entry_points()['my.plugins'] >>> for ep in eps: ... plugin = ep.load() ... plugin() diff --git a/docs/userguide/package_discovery.rst b/docs/userguide/package_discovery.rst index e02035b3..551e02e6 100644 --- a/docs/userguide/package_discovery.rst +++ b/docs/userguide/package_discovery.rst @@ -35,7 +35,7 @@ included manually in the following manner: setup( # ... - packages=["mypkg1", "mypkg2"] + packages=['mypkg1', 'mypkg2'] ) This can get tiresome reallly quickly. To speed things up, we introduce two @@ -101,9 +101,9 @@ in ``src`` that starts with the name ``pkg`` and not ``additional``: setup( # ... packages=find_packages( - where="src", - include=["pkg*"], - exclude=["additional"], + where='src', + include=['pkg*'], + exclude=['additional'], ), package_dir={"": "src"} # ... @@ -221,7 +221,7 @@ And the ``namespace_packages`` keyword in your ``setup.cfg`` or ``setup.py``: setup( # ... - namespace_packages=["timmins"] + namespace_packages=['timmins'] ) And your directory should look like this @@ -246,6 +246,6 @@ file contains the following: .. code-block:: python - __path__ = __import__("pkgutil").extend_path(__path__, __name__) + __path__ = __import__('pkgutil').extend_path(__path__, __name__) The project layout remains the same and ``setup.cfg`` remains the same. diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 0ab23ca2..1bd04ded 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -60,11 +60,11 @@ the minimum from setuptools import setup setup( - name="mypackage", - version="0.0.1", - packages=["mypackage"], + name='mypackage', + version='0.0.1', + packages=['mypackage'], install_requires=[ - "requests", + 'requests', 'importlib; python_version == "2.6"', ], ) -- cgit v1.2.1 From df1602aed550c0b312aedebce1b80313b26f32bf Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Fri, 30 Jul 2021 09:18:39 +0100 Subject: add python_requires example --- docs/userguide/dependency_management.rst | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/dependency_management.rst b/docs/userguide/dependency_management.rst index b97896ba..23578a57 100644 --- a/docs/userguide/dependency_management.rst +++ b/docs/userguide/dependency_management.rst @@ -341,4 +341,25 @@ In some cases, you might need to specify the minimum required python version. This is handled with the ``python_requires`` keyword supplied to ``setup.cfg`` or ``setup.py``. -Example WIP + +.. tab:: setup.cfg + + .. code-block:: ini + + [metadata] + name = Project-B + #... + + [options] + #... + python_requires = >=3.6 + +.. tab:: setup.py + + .. code-block:: python + + setup( + name="Project-B", + python_requires=[">=3.6"], + ..., + ) -- cgit v1.2.1 From ca296ca8663a376f3c36c9f8fd86b10ba81366c2 Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Sun, 18 Jul 2021 09:27:21 +0100 Subject: remove lib2to3 usage --- docs/userguide/declarative_config.rst | 4 ---- docs/userguide/development_mode.rst | 8 -------- docs/userguide/keywords.rst | 12 ------------ 3 files changed, 24 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/declarative_config.rst b/docs/userguide/declarative_config.rst index 3b72611c..c50fcf6d 100644 --- a/docs/userguide/declarative_config.rst +++ b/docs/userguide/declarative_config.rst @@ -211,10 +211,6 @@ install_requires list-semi extras_require section [#opt-2]_ python_requires str entry_points file:, section 51.0.0 -use_2to3 bool -use_2to3_fixers list-comma -use_2to3_exclude_fixers list-comma -convert_2to3_doctests list-comma scripts list-comma eager_resources list-comma dependency_links list-comma diff --git a/docs/userguide/development_mode.rst b/docs/userguide/development_mode.rst index 3c477ec1..90bc5676 100644 --- a/docs/userguide/development_mode.rst +++ b/docs/userguide/development_mode.rst @@ -28,14 +28,6 @@ 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. -If you have enabled the ``use_2to3`` flag, then of course the ``.egg-link`` -will not link directly to your source code when run under Python 3, since -that source code would be made for Python 2 and not work under Python 3. -Instead the ``setup.py develop`` will build Python 3 code under the ``build`` -directory, and link there. This means that after doing code changes you will -have to run ``setup.py build`` before these changes are picked up by your -Python 3 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``. diff --git a/docs/userguide/keywords.rst b/docs/userguide/keywords.rst index 268e4f42..5388ffea 100644 --- a/docs/userguide/keywords.rst +++ b/docs/userguide/keywords.rst @@ -157,18 +157,6 @@ unless you need the associated ``setuptools`` feature. mess with it. For more details on how this argument works, see the section below on :ref:`Automatic Resource Extraction`. -``use_2to3`` - Convert the source code from Python 2 to Python 3 with 2to3 during the - build process. See :doc:`../deprecated/python3` for more details. - -``convert_2to3_doctests`` - List of doctest source files that need to be converted with 2to3. - See :doc:`../deprecated/python3` for more details. - -``use_2to3_fixers`` - A list of modules to search for additional fixers to be used during - the 2to3 conversion. See :doc:`../deprecated/python3` for more details. - ``project_urls`` An arbitrary map of URL names to hyperlinks, allowing more extensible documentation of where various resources can be found than the simple -- cgit v1.2.1 From 292614ea0dee7f5ae478ecc1c2fd10e31bdae38c Mon Sep 17 00:00:00 2001 From: Rupert Nash Date: Thu, 9 Sep 2021 13:18:32 +0100 Subject: Correct typo (s/brakets/brackets/) --- docs/userguide/entry_point.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/entry_point.rst b/docs/userguide/entry_point.rst index c92ccf76..21edc697 100644 --- a/docs/userguide/entry_point.rst +++ b/docs/userguide/entry_point.rst @@ -141,7 +141,7 @@ Dependency Management ===================== Some entry points may require additional dependencies to properly function. -For such an entry point, declare in square brakets any number of dependency +For such an entry point, declare in square brackets any number of dependency ``extras`` following the entry point definition. Such entry points will only be viable if their extras were declared and installed. See the :doc:`guide on dependencies management ` for -- cgit v1.2.1 From 95cacfa6c55fc1c8944b7e9b4086c09088ea4b88 Mon Sep 17 00:00:00 2001 From: Mozi <29089388+pzhlkj6612@users.noreply.github.com> Date: Sun, 12 Sep 2021 15:03:16 +0800 Subject: docs(quickstart): add link to "Development Mode" --- docs/userguide/quickstart.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 1bd04ded..bcb282ed 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -201,7 +201,7 @@ Then:: pip install --editable . This creates a link file in your interpreter site package directory which -associate with your source code. For more information, see: (WIP) +associate with your source code. For more information, see :doc:`development_mode`. Uploading your package to PyPI -- cgit v1.2.1 From fbfd7bc0f3b86352c748ab6fea0713391fcfa563 Mon Sep 17 00:00:00 2001 From: Diego Ramirez Date: Tue, 14 Sep 2021 08:22:34 -0500 Subject: Document the version coparisons Document how the legacy versions and non-legacy versions are compared. --- docs/userguide/distribution.rst | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/distribution.rst b/docs/userguide/distribution.rst index 377f7bb4..5888a819 100644 --- a/docs/userguide/distribution.rst +++ b/docs/userguide/distribution.rst @@ -161,7 +161,10 @@ without Cython. Specifying Your Project's Version --------------------------------- -Setuptools can work well with most versioning schemes; there are, however, a +Setuptools can work well with most versioning schemes. Over the years, +setuptools has tried to closely follow the +`PEP 440 `_ scheme, but it +also supports legacy versions. There are, however, a few special things to watch out for, in order to ensure that setuptools and other tools can always tell what version of your package is newer than another version. Knowing these things will also help you correctly specify what @@ -181,9 +184,13 @@ tag. Pre-release tags make a version be considered *older* than the version they are appended to. So, revision ``2.4`` is *newer* than revision ``2.4c1``, which in turn is newer than ``2.4b1`` or ``2.4a1``. Postrelease tags make a version be considered *newer* than the version they are appended to. So, -revisions like ``2.4-1`` and ``2.4pl3`` are newer than ``2.4``, but are *older* +revisions like ``2.4-1`` is newer than ``2.4``, but *older* than ``2.4.1`` (which has a higher release number). +In the case of legacy versions (for example, ``2.4pl1``) are always considered +older than non-legacy versions. Taking that in count, a version ``2.4pl1`` +is *older* than ``2.4`` + A pre-release tag is a series of letters that are alphabetically before "final". Some examples of prerelease tags would include ``alpha``, ``beta``, ``a``, ``c``, ``dev``, and so on. You do not have to place a dot or dash -- cgit v1.2.1 From 59ff034a066105826dc677ad27e617e8b56f2ef6 Mon Sep 17 00:00:00 2001 From: Diego Ramirez Date: Tue, 14 Sep 2021 10:25:25 -0500 Subject: Update distribution.rst Fix some typos. --- docs/userguide/distribution.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/distribution.rst b/docs/userguide/distribution.rst index 5888a819..19bed1f9 100644 --- a/docs/userguide/distribution.rst +++ b/docs/userguide/distribution.rst @@ -184,11 +184,11 @@ tag. Pre-release tags make a version be considered *older* than the version they are appended to. So, revision ``2.4`` is *newer* than revision ``2.4c1``, which in turn is newer than ``2.4b1`` or ``2.4a1``. Postrelease tags make a version be considered *newer* than the version they are appended to. So, -revisions like ``2.4-1`` is newer than ``2.4``, but *older* +revisions like ``2.4-1`` are newer than ``2.4``, but *older* than ``2.4.1`` (which has a higher release number). -In the case of legacy versions (for example, ``2.4pl1``) are always considered -older than non-legacy versions. Taking that in count, a version ``2.4pl1`` +In the case of legacy versions (for example, ``2.4pl1``), they are considered +older than non-legacy versions. Taking that in count, a revision ``2.4pl1`` is *older* than ``2.4`` A pre-release tag is a series of letters that are alphabetically before -- cgit v1.2.1 From f44a3cb8d12f820c0c3131f0f6ed973bb88a7fe3 Mon Sep 17 00:00:00 2001 From: stanton119 Date: Fri, 17 Sep 2021 14:31:12 +0100 Subject: Update package_discovery.rst Small typo --- docs/userguide/package_discovery.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/package_discovery.rst b/docs/userguide/package_discovery.rst index 551e02e6..61da2d66 100644 --- a/docs/userguide/package_discovery.rst +++ b/docs/userguide/package_discovery.rst @@ -38,7 +38,7 @@ included manually in the following manner: packages=['mypkg1', 'mypkg2'] ) -This can get tiresome reallly quickly. To speed things up, we introduce two +This can get tiresome really quickly. To speed things up, we introduce two functions provided by setuptools: .. tab:: setup.cfg -- cgit v1.2.1 From a1c82058a3a792101cf9cb8b9fe30622931cbae3 Mon Sep 17 00:00:00 2001 From: "Jens C. Jensen" <1847332+jensecj@users.noreply.github.com> Date: Sun, 3 Oct 2021 15:17:48 +0000 Subject: fix typo: above -> below I guess the sections may have been moved around at some point? or someone wrote it upside down, anyway this fixes the direction for most right-side-up readers :) --- docs/userguide/distribution.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/distribution.rst b/docs/userguide/distribution.rst index 19bed1f9..02eab66f 100644 --- a/docs/userguide/distribution.rst +++ b/docs/userguide/distribution.rst @@ -25,7 +25,7 @@ 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 :ref:`egg_info ` command for more details. -(Also, before you release your project, be sure to see the section above on +(Also, before you release your project, be sure to see the section below on :ref:`Specifying Your Project's Version` for more information about how pre- and post-release tags affect how version numbers are interpreted. This is important in order to make sure that dependency processing tools will know -- cgit v1.2.1 From 68b12429d977f6e0c10fe97f7ba45df1be6c3f69 Mon Sep 17 00:00:00 2001 From: "Jens C. Jensen" <1847332+jensecj@users.noreply.github.com> Date: Sun, 3 Oct 2021 16:27:12 +0000 Subject: Update docs/userguide/distribution.rst Co-authored-by: Jason R. Coombs --- docs/userguide/distribution.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/userguide') diff --git a/docs/userguide/distribution.rst b/docs/userguide/distribution.rst index 02eab66f..2872dacd 100644 --- a/docs/userguide/distribution.rst +++ b/docs/userguide/distribution.rst @@ -25,7 +25,7 @@ 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 :ref:`egg_info ` command for more details. -(Also, before you release your project, be sure to see the section below on +(Also, before you release your project, be sure to see the section on :ref:`Specifying Your Project's Version` for more information about how pre- and post-release tags affect how version numbers are interpreted. This is important in order to make sure that dependency processing tools will know -- cgit v1.2.1 From eba81f6d33e425b121d1fcb215f02bb1dede2a11 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Fri, 22 Oct 2021 15:06:19 -0400 Subject: Add minimum versions for setup_requires, python_requires, py_modules. Closes #1535. --- docs/userguide/declarative_config.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/declarative_config.rst b/docs/userguide/declarative_config.rst index c50fcf6d..abafe376 100644 --- a/docs/userguide/declarative_config.rst +++ b/docs/userguide/declarative_config.rst @@ -206,10 +206,10 @@ Options Key Type Minimum Version Notes ======================= =================================== =============== ========= zip_safe bool -setup_requires list-semi +setup_requires list-semi 36.7.0 install_requires list-semi extras_require section [#opt-2]_ -python_requires str +python_requires str 34.4.0 entry_points file:, section 51.0.0 scripts list-comma eager_resources list-comma @@ -221,7 +221,7 @@ package_dir dict package_data section [#opt-1]_ exclude_package_data section namespace_packages list-comma -py_modules list-comma +py_modules list-comma 34.4.0 data_files dict 40.6.0 ======================= =================================== =============== ========= -- cgit v1.2.1 From 2c169ff531635bccab1f8bd0451a762bd286903c Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Tue, 26 Oct 2021 13:35:02 +0100 Subject: Remove data_files from declarative config example According to the following references: - https://setuptools.pypa.io/en/latest/references/keywords.html - https://packaging.python.org/guides/distributing-packages-using-setuptools/#package-data the usage of ``data_files`` is deprecated. Therefore we should avoid having it in the main configuration example for declarative config. --- docs/userguide/declarative_config.rst | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/declarative_config.rst b/docs/userguide/declarative_config.rst index abafe376..d1c25df1 100644 --- a/docs/userguide/declarative_config.rst +++ b/docs/userguide/declarative_config.rst @@ -63,13 +63,6 @@ boilerplate code in some cases. src.subpackage1 src.subpackage2 - [options.data_files] - /etc/my_package = - site.d/00_default.conf - host.d/00_default.conf - data = data/img/logo.png, data/svg/icon.svg - fonts = data/fonts/*.ttf, data/fonts/*.otf - Metadata and options are set in the config sections of the same name. * Keys are the same as the keyword arguments one provides to the ``setup()`` @@ -222,7 +215,7 @@ package_data section [# exclude_package_data section namespace_packages list-comma py_modules list-comma 34.4.0 -data_files dict 40.6.0 +data_files section 40.6.0 [#opt-4]_ ======================= =================================== =============== ========= **Notes**: @@ -250,6 +243,9 @@ data_files dict 40.6.0 The ``find_namespace:`` directive is supported since Python >=3.3. +.. [#opt-4] ``data_files`` is deprecated and should be avoided. + Please check :doc:`/userguide/datafiles` for more information. + Compatibility with other tools ============================== -- cgit v1.2.1 From eca0111c29721056e8af7ac0d08d5f678fe7473e Mon Sep 17 00:00:00 2001 From: Anderson Bravalheri Date: Fri, 5 Nov 2021 19:03:05 +0000 Subject: Document setuptools replacements --- docs/userguide/extension.rst | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'docs/userguide') diff --git a/docs/userguide/extension.rst b/docs/userguide/extension.rst index 93b59501..966c6fde 100644 --- a/docs/userguide/extension.rst +++ b/docs/userguide/extension.rst @@ -45,6 +45,14 @@ entry points in the active distributions on ``sys.path``. In fact, this is how setuptools' own commands are installed: the setuptools project's setup script defines entry points for them! +.. note:: + When creating commands, and specially when defining custom ways of building + compiled extensions (for example via ``build_ext``), you might want to + handle exceptions such as ``CompileError``, ``LinkError``, ``LibError``, + among others. These exceptions are available in the ``setuptools.errors`` + module. + + Adding ``setup()`` Arguments ---------------------------- -- cgit v1.2.1 From 172ea3681ce1f2b7da1044c5215cb8058b866324 Mon Sep 17 00:00:00 2001 From: "Jason R. Coombs" Date: Sun, 7 Nov 2021 04:51:19 -0500 Subject: Prefer imperative voice. --- docs/userguide/extension.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/extension.rst b/docs/userguide/extension.rst index 966c6fde..d74ca3fe 100644 --- a/docs/userguide/extension.rst +++ b/docs/userguide/extension.rst @@ -47,8 +47,8 @@ script defines entry points for them! .. note:: When creating commands, and specially when defining custom ways of building - compiled extensions (for example via ``build_ext``), you might want to - handle exceptions such as ``CompileError``, ``LinkError``, ``LibError``, + compiled extensions (for example via ``build_ext``), consider + handling exceptions such as ``CompileError``, ``LinkError``, ``LibError``, among others. These exceptions are available in the ``setuptools.errors`` module. -- cgit v1.2.1 From 4f475e9035ff40906024249e81b2f7e5b9bebf14 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 11 Nov 2021 15:57:01 +0100 Subject: Document that pip works with editable setup.cfg --- docs/userguide/quickstart.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index bcb282ed..9c1d84f9 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -186,17 +186,17 @@ For more details, see :doc:`datafiles` Development mode ================ -``setuptools`` allows you to install a package without copying any files -to your interpreter directory (e.g. the ``site-packages`` directory). This -allows you to modify your source code and have the changes take effect without -you having to rebuild and reinstall. This is currently incompatible with -PEP 517 and therefore it requires a ``setup.py`` script with the following -content:: - import setuptools - setuptools.setup() +.. tip:: + + When there is no ``setup.py`` script present, this is only + compatible with :pep:`517` since :ref:`pip v21.1 `. -Then:: +``setuptools`` allows you to install a package without copying any files +to your interpreter directory (e.g. the ``site-packages`` directory). +This allows you to modify your source code and have the changes take +effect without you having to rebuild and reinstall. +Here's how to do it:: pip install --editable . -- cgit v1.2.1 From ba39e1851f02fa27b425f616d13c2b07298c63d5 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Fri, 12 Nov 2021 23:56:44 +0100 Subject: Improve the mention of pip version that doesn't need `setup.py` Co-authored-by: Jason R. Coombs --- docs/userguide/quickstart.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'docs/userguide') diff --git a/docs/userguide/quickstart.rst b/docs/userguide/quickstart.rst index 9c1d84f9..6bf353a0 100644 --- a/docs/userguide/quickstart.rst +++ b/docs/userguide/quickstart.rst @@ -189,8 +189,9 @@ Development mode .. tip:: - When there is no ``setup.py`` script present, this is only - compatible with :pep:`517` since :ref:`pip v21.1 `. + Prior to :ref:`pip v21.1 `, a ``setup.py`` script was + required to be compatible with development mode. With late + versions of pip, any project may be installed in this mode. ``setuptools`` allows you to install a package without copying any files to your interpreter directory (e.g. the ``site-packages`` directory). -- cgit v1.2.1