Commit 97d43ce5 authored by PJ Eby's avatar PJ Eby

Added ``setuptools.file_finders`` entry point group to allow implementing

revision control plugins.

--HG--
branch : setuptools
extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/trunk/setuptools%4043428
parent 529b06d3
......@@ -77,9 +77,9 @@ setup(
"easy_install-%s = setuptools.command.easy_install:main"
% sys.version[:3]
],
},
"setuptools.file_finders":
["svn_cvs = setuptools.command.sdist:_default_revctrl"]
},
classifiers = [f.strip() for f in """
Development Status :: 3 - Alpha
Intended Audience :: Developers
......
......@@ -12,6 +12,9 @@ eager_resources = setuptools.dist:assert_string_list
zip_safe = setuptools.dist:assert_bool
tests_require = setuptools.dist:check_requirements
[setuptools.file_finders]
svn_cvs = setuptools.command.sdist:_default_revctrl
[egg_info.writers]
dependency_links.txt = setuptools.command.egg_info:overwrite_arg
requires.txt = setuptools.command.egg_info:write_requirements
......
......@@ -635,7 +635,10 @@ e.g.::
This tells setuptools to install any data files it finds in your packages. The
data files must be under CVS or Subversion control, or else they must be
specified via the distutils' ``MANIFEST.in`` file.
specified via the distutils' ``MANIFEST.in`` file. (They can also be tracked
by another revision control system, using an appropriate plugin. See the
section below on `Adding Support for Other 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
......@@ -1346,6 +1349,10 @@ revision control, don't create a a ``MANIFEST.in`` file for your project.
(And, if you already have one, you might consider deleting it the next time
you would otherwise have to change it.)
(NOTE: other revision control systems besides CVS and Subversion can be
supported using plugins; see the section below on `Adding Support for Other
Revision Control Systems`_ for information on how to write such 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
......@@ -2328,6 +2335,60 @@ the ``cmd`` object's ``write_file()``, ``delete_file()``, and
those methods' docstrings for more details.
Adding Support for Other Revision Control Systems
-------------------------------------------------
If you would like to create a plugin for ``setuptools`` to find files in other
source control systems besides CVS and Subversion, 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::
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).
Subclassing ``Command``
-----------------------
......@@ -2371,6 +2432,9 @@ Release Notes/Change History
----------------------------
0.6a11
* Added ``setuptools.file_finders`` entry point group to allow implementing
revision control plugins.
* Added ``--identity`` option to ``upload`` command.
* Added ``dependency_links`` to allow specifying URLs for ``--find-links``.
......
from distutils.command.sdist import sdist as _sdist
from distutils.util import convert_path
import os, re, sys
import os, re, sys, pkg_resources
entities = [
("&lt;","<"), ("&gt;", ">"), ("&quot;", '"'), ("&apos;", "'"),
......@@ -39,13 +39,13 @@ def joinpath(prefix,suffix):
def walk_revctrl(dirname='', memo=None):
def walk_revctrl(dirname=''):
"""Find all files under revision control"""
if memo is None:
memo = {}
if dirname in memo:
# Don't rescan a scanned directory
return
for ep in pkg_resources.iter_entry_points('setuptools.file_finders'):
for item in ep.load()(dirname):
yield item
def _default_revctrl(dirname=''):
for path, finder in finders:
path = joinpath(dirname,path)
if os.path.isfile(path):
......@@ -53,7 +53,7 @@ def walk_revctrl(dirname='', memo=None):
if os.path.isfile(path):
yield path
elif os.path.isdir(path):
for item in walk_revctrl(path, memo):
for item in _default_revctrl(path):
yield item
def externals_finder(dirname, filename):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment