5 from darcsver import darcsvermodule
7 from distutils.errors import DistutilsSetupError
9 def validate_string_or_iter_of_strings(dist, attr, value):
10 # value is required to be a string or else a list of strings
11 if isinstance(value, basestring):
15 if not isinstance(thing, basestring):
16 raise DistutilsSetupError("%r is required to be a string or an iterable of strings (got %r)" % (attr, value))
18 raise DistutilsSetupError("%r is required to be a string or an iterable of strings (got %r)" % (attr, value))
20 def validate_versionfiles(dist, attr, value):
21 return validate_string_or_iter_of_strings(dist, attr, value)
23 def validate_versionbodies(dist, attr, value):
24 return validate_string_or_iter_of_strings(dist, attr, value)
27 for thing in iterator:
32 PYTHON_VERSION_BODY='''
33 # This is the version of this tree, as created by %(versiontool)s from the darcs patch
34 # information: the main version number is taken from the most recent release
35 # tag. If some patches have been added since the last release, this will have a
36 # -NN "build number" suffix, or else a -rNN "revision number" suffix. Please see
37 # pyutil.version_class for a description of what the different fields mean.
39 __pkgname__ = "%(pkgname)s"
40 verstr = "%(pkgversion)s"
42 from pyutil.version_class import Version as pyutil_Version
43 __version__ = pyutil_Version(verstr)
44 except (ImportError, ValueError):
45 # Maybe there is no pyutil installed, or this may be an older version of
46 # pyutil.version_class which does not support SVN-alike revision numbers.
47 from distutils.version import LooseVersion as distutils_Version
48 __version__ = distutils_Version(verstr)
51 class DarcsVer(setuptools.Command):
52 description = "generate a version number from darcs history"
54 ('project-name', None, "name of the project as it appears in the project's release tags (default's the to the distribution name)"),
55 ('filename', None, "path to file into which the version number should be written (defaults to the package directory's _version.py)"),
56 ('count-all-patches', None, "If true, count the total number of patches in all history. If false, count the total number of patches since the most recent release tag."),
57 ('abort-if-snapshot', None, "If true, the if the current version is a snapshot (not a release tag), then immediately exit the process with exit code 0."),
60 def initialize_options(self):
61 self.project_name = None
63 self.count_all_patches = None
64 self.abort_if_snapshot = None
66 def finalize_options(self):
67 if self.project_name is None:
68 self.project_name = self.distribution.get_name()
70 # If the user passed --filename on the cmdline, override
71 # the setup.py's versionfiles argument.
72 if self.filename is not None:
73 if not isinstance(self.filename, basestring):
74 raise TypeError("filename is required to be a string, not %s, filename: %s" % (type(self.filename), self.filename))
75 self.distribution.versionfiles = [self.filename]
77 if self.abort_if_snapshot is None:
78 self.abort_if_snapshot=False
81 if self.distribution.versionfiles is None:
83 # If there is a package with the same name as the project name and
84 # there is a directory by that name then use that.
86 if self.distribution.packages and self.project_name in self.distribution.packages:
87 toppackage = self.project_name
89 if self.distribution.package_dir:
90 srcdir = self.distribution.package_dir.get(toppackage)
91 if not srcdir is None:
92 srcdir = self.distribution.package_dir.get('', '')
93 packagedir = os.path.join(srcdir, toppackage)
95 if packagedir is None or not os.path.isdir(packagedir):
96 # Else, if there is a singly-rooted tree of packages, use the
98 if self.distribution.packages:
99 for package in self.distribution.packages:
103 if toppackage.startswith(package+"."):
106 if not package.startswith(toppackage+"."):
112 if self.distribution.package_dir:
113 srcdir = self.distribution.package_dir.get(toppackage)
115 srcdir = self.distribution.package_dir.get('', '')
116 packagedir = os.path.join(srcdir, toppackage)
118 self.distribution.versionfiles = [os.path.join(packagedir, '_version.py')]
120 if self.distribution.versionbodies is None:
121 self.distribution.versionbodies = [PYTHON_VERSION_BODY]
123 assert all([isinstance(vfn, basestring) for vfn in self.distribution.versionfiles]), self.distribution.versionfiles
124 (rc, verstr) = darcsvermodule.update(self.project_name, self.distribution.versionfiles, self.count_all_patches, abort_if_snapshot=self.abort_if_snapshot, EXE_NAME="setup.py darcsver", version_body=self.distribution.versionbodies)
126 self.distribution.metadata.version = verstr