aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPJ Eby <distutils-sig@python.org>2005-07-08 04:48:20 +0000
committerPJ Eby <distutils-sig@python.org>2005-07-08 04:48:20 +0000
commit592269afeaa4f96bddbaa8b6fbe8dddcea2445a4 (patch)
tree5fe55dced4503fdbb70eb5ec692d86003c444fe3
parent56fcb8fdcc377acf0d74430a3d2d4dbffe306d44 (diff)
downloadexternal_python_setuptools-592269afeaa4f96bddbaa8b6fbe8dddcea2445a4.tar.gz
external_python_setuptools-592269afeaa4f96bddbaa8b6fbe8dddcea2445a4.tar.bz2
external_python_setuptools-592269afeaa4f96bddbaa8b6fbe8dddcea2445a4.zip
* Added "rotate" command to delete old distribution files, given a set of
patterns to match and the number of files to keep. (Keeps the most recently-modified distribution files matching each pattern.) * Added "saveopts" command that saves all command-line options for the current invocation to the local, global, or per-user configuration file. Useful for setting defaults without having to hand-edit a configuration file. * Added a "setopt" command that sets a single option in a specified distutils configuration file. --HG-- branch : setuptools extra : convert_revision : svn%3A6015fed2-1504-0410-9fe1-9d1591cc4771/sandbox/trunk/setuptools%4041093
-rwxr-xr-xEasyInstall.txt19
-rw-r--r--setuptools/command/__init__.py2
-rwxr-xr-xsetuptools/command/rotate.py82
-rwxr-xr-xsetuptools/command/saveopts.py27
-rwxr-xr-xsetuptools/command/setopt.py164
5 files changed, 293 insertions, 1 deletions
diff --git a/EasyInstall.txt b/EasyInstall.txt
index 31a2734a..dccdf957 100755
--- a/EasyInstall.txt
+++ b/EasyInstall.txt
@@ -488,6 +488,25 @@ Known Issues
in Exemaker. So, don't use Exemaker to wrap ``easy_install.py``, or at any
rate don't expect it to work with all packages.
+0.5a8
+ * The "egg_info" command now always sets the distribution metadata to "safe"
+ forms of the distribution name and version, so that distribution files will
+ be generated with parseable names (i.e., ones that don't include '-' in the
+ name or version). Also, this means that if you use the various ``--tag``
+ options of "egg_info", any distributions generated will use the tags in the
+ version, not just egg distributions.
+
+ * Added "rotate" command to delete old distribution files, given a set of
+ patterns to match and the number of files to keep. (Keeps the most
+ recently-modified distribution files matching each pattern.)
+
+ * Added "saveopts" command that saves all command-line options for the current
+ invocation to the local, global, or per-user configuration file. Useful for
+ setting defaults without having to hand-edit a configuration file.
+
+ * Added a "setopt" command that sets a single option in a specified distutils
+ configuration file.
+
0.5a7
* Added "upload" support for egg and source distributions, including a bug
fix for "upload" and a temporary workaround for lack of .egg support in
diff --git a/setuptools/command/__init__.py b/setuptools/command/__init__.py
index bc5bc878..0606ef9c 100644
--- a/setuptools/command/__init__.py
+++ b/setuptools/command/__init__.py
@@ -1,6 +1,6 @@
import distutils.command
-__all__ = ['test', 'develop', 'bdist_egg']
+__all__ = ['test', 'develop', 'bdist_egg', 'saveopts', 'setopt', 'rotate']
# Make our commands available as though they were part of the distutils
diff --git a/setuptools/command/rotate.py b/setuptools/command/rotate.py
new file mode 100755
index 00000000..f7330436
--- /dev/null
+++ b/setuptools/command/rotate.py
@@ -0,0 +1,82 @@
+import distutils, os
+from setuptools import Command
+from distutils.util import convert_path
+from distutils import log
+from distutils.errors import *
+
+class rotate(Command):
+ """Delete older distributions"""
+
+ description = "Delete older distributions, keeping N newest files"
+ user_options = [
+ ('match=', 'm', "patterns to match (required)"),
+ ('dist-dir=', 'd', "directory where the distributions are"),
+ ('keep=', 'k', "number of matching distributions to keep"),
+ ]
+
+ boolean_options = []
+
+ def initialize_options(self):
+ self.match = None
+ self.dist_dir = None
+ self.keep = None
+
+ def finalize_options(self):
+ if self.match is None:
+ raise DistutilsOptionError(
+ "Must specify one or more (comma-separated) match patterns "
+ "(e.g. '.zip' or '.egg')"
+ )
+ if self.keep is None:
+ raise DistutilsOptionError("Must specify number of files to keep")
+ try:
+ self.keep = int(self.keep)
+ except ValueError:
+ raise DistutilsOptionError("--keep must be an integer")
+ if isinstance(self.match, basestring):
+ self.match = [
+ convert_path(p.strip()) for p in self.match.split(',')
+ ]
+ self.set_undefined_options('bdist',('dist_dir', 'dist_dir'))
+
+ def run(self):
+ self.run_command("egg_info")
+ from glob import glob
+ for pattern in self.match:
+ pattern = self.distribution.get_name()+'*'+pattern
+ files = glob(os.path.join(self.dist_dir,pattern))
+ files = [(os.path.getmtime(f),f) for f in files]
+ files.sort()
+ files.reverse()
+
+ log.info("%d file(s) matching %s", len(files), pattern)
+ files = files[self.keep:]
+ for (t,f) in files:
+ log.info("Deleting %s", f)
+ if not self.dry_run:
+ os.unlink(f)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/setuptools/command/saveopts.py b/setuptools/command/saveopts.py
new file mode 100755
index 00000000..ad3cf193
--- /dev/null
+++ b/setuptools/command/saveopts.py
@@ -0,0 +1,27 @@
+import distutils, os
+from setuptools import Command
+from setuptools.command.setopt import edit_config, option_base
+
+class saveopts(option_base):
+ """Save command-line options to a file"""
+
+ description = "save supplied options to setup.cfg or other config file"
+
+ user_options = option_base.user_options + [
+ ]
+
+ boolean_options = option_base.boolean_options + [
+ ]
+
+ def run(self):
+ dist = self.distribution
+ commands = dist.command_options.keys()
+ settings = {}
+ for cmd in commands:
+ if cmd=='saveopts':
+ continue
+ for opt,(src,val) in dist.get_option_dict(cmd).items():
+ if src=="command line":
+ settings.setdefault(cmd,{})[opt] = val
+ edit_config(self.filename, settings, self.dry_run)
+
diff --git a/setuptools/command/setopt.py b/setuptools/command/setopt.py
new file mode 100755
index 00000000..b5d9d307
--- /dev/null
+++ b/setuptools/command/setopt.py
@@ -0,0 +1,164 @@
+import distutils, os
+from setuptools import Command
+from distutils.util import convert_path
+from distutils import log
+from distutils.errors import *
+
+__all__ = ['config_file', 'edit_config', 'option_base', 'setopt']
+
+
+def config_file(kind="local"):
+ """Get the filename of the distutils, local, global, or per-user config
+
+ `kind` must be one of "local", "global", or "user"
+ """
+ if kind=='local':
+ return 'setup.cfg'
+ if kind=='global':
+ return os.path.join(
+ os.path.dirname(distutils.__file__),'distutils.cfg'
+ )
+ if kind=='user':
+ dot = os.name=='posix' and '.' or ''
+ return os.path.expanduser(convert_path("~/%spydistutils.cfg" % dot))
+ raise ValueError(
+ "config_file() type must be 'local', 'global', or 'user'", kind
+ )
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+def edit_config(filename, settings, dry_run=False):
+ """Edit a configuration file to include `settings`
+
+ `settings` is a dictionary of dictionaries or ``None`` values, keyed by
+ command/section name. A ``None`` value means to delete the entire section,
+ while a dictionary lists settings to be changed or deleted in that section.
+ A setting of ``None`` means to delete that setting.
+ """
+ from ConfigParser import RawConfigParser
+ log.debug("Reading configuration from %s", filename)
+ opts = RawConfigParser()
+ opts.read([filename])
+
+ for section, options in settings.items():
+ if options is None:
+ log.debug("Deleting section [%s] from %s", section, filename)
+ opts.remove_section(section)
+ else:
+ if not opts.has_section(section):
+ log.debug("Adding new section [%s] to %s", section, filename)
+ opts.add_section(section)
+ for option,value in options.items():
+ if value is None:
+ log.debug("Deleting %s.%s from %s",
+ section, option, filename
+ )
+ opts.remove_option(section,option)
+ else:
+ log.debug(
+ "Setting %s.%s to %r in %s",
+ section, option, value, filename
+ )
+ opts.set(section,option,value)
+
+ log.info("Writing %s", filename)
+ if not dry_run:
+ f = open(filename,'w')
+ opts.write(f)
+ f.close()
+
+
+class option_base(Command):
+ """Abstract base class for commands that mess with config files"""
+
+ user_options = [
+ ('filename=', 'f',
+ "set the file to use (default=setup.cfg)"),
+ ('global-config', 'g',
+ "save options to the site-wide distutils.cfg file"),
+ ('user-config', 'u',
+ "save options to the current user's pydistutils.cfg file"),
+ ]
+
+ boolean_options = [
+ 'global-config', 'user-config',
+ ]
+
+ def initialize_options(self):
+ self.global_config = None
+ self.user_config = None
+ self.filename = None
+
+ def finalize_options(self):
+ filenames = []
+ if self.global_config:
+ filenames.append(config_file('global'))
+ if self.user_config:
+ filenames.append(config_file('user'))
+ if self.filename is not None:
+ filenames.append(self.filename)
+ if not filenames:
+ filenames.append(config_file('local'))
+ if len(filenames)>1:
+ raise DistutilsOptionError(
+ "Must specify only one configuration file option",
+ filenames
+ )
+ self.filename, = filenames
+
+
+
+
+class setopt(option_base):
+ """Save command-line options to a file"""
+
+ description = "set an option in setup.cfg or another config file"
+
+ user_options = option_base.user_options + [
+ ('command=', 'c', 'command to set an option for'),
+ ('option=', 'o', 'option to set'),
+ ('set-value=', 's', 'value of the option'),
+ ('remove', 'r', 'unset the value'),
+ ]
+
+ boolean_options = option_base.boolean_options + ['remove']
+
+ def initialize_options(self):
+ option_base.initialize_options(self)
+ self.command = None
+ self.option = None
+ self.set_value = None
+ self.remove = None
+
+ def finalize_options(self):
+ option_base.finalize_options(self)
+ if self.command is None or self.option is None:
+ raise DistutilsOptionError("Must specify --command *and* --option")
+ if self.set_value is None and not self.remove:
+ raise DistutilsOptionError("Must specify --set-value or --remove")
+
+ def run(self):
+ edit_config(
+ self.filename, {
+ self.command: {self.option.replace('-','_'):self.set_value}
+ },
+ self.dry_run
+ )
+
+
+
+
+
+