1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
3
# Copyright 2012 OpenStack LLC
5
# Licensed under the Apache License, Version 2.0 (the "License"); you may
6
# not use this file except in compliance with the License. You may obtain
7
# a copy of the License at
9
# http://www.apache.org/licenses/LICENSE-2.0
11
# Unless required by applicable law or agreed to in writing, software
12
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
# License for the specific language governing permissions and limitations
18
Utilities for consuming the auto-generated versioninfo files.
28
class _deferred_version_string(object):
29
"""Internal helper class which provides delayed version calculation."""
30
def __init__(self, version_info, prefix):
31
self.version_info = version_info
35
return "%s%s" % (self.prefix, self.version_info.version_string())
38
return "%s%s" % (self.prefix, self.version_info.version_string())
41
class VersionInfo(object):
43
def __init__(self, package, python_package=None, pre_version=None):
44
"""Object that understands versioning for a package
45
:param package: name of the top level python namespace. For glance,
46
this would be "glance" for python-glanceclient, it
47
would be "glanceclient"
48
:param python_package: optional name of the project name. For
49
glance this can be left unset. For
50
python-glanceclient, this would be
52
:param pre_version: optional version that the project is working to
54
self.package = package
55
if python_package is None:
56
self.python_package = package
58
self.python_package = python_package
59
self.pre_version = pre_version
62
def _generate_version(self):
63
"""Defer to the openstack.common.setup routines for making a
65
if self.pre_version is None:
66
return setup.get_post_version(self.python_package)
68
return setup.get_pre_version(self.python_package, self.pre_version)
70
def _newer_version(self, pending_version):
71
"""Check to see if we're working with a stale version or not.
72
We expect a version string that either looks like:
73
2012.2~f3~20120708.10.4426392
74
which is an unreleased version of a pre-version, or:
76
which is an unreleased version of a post-version, or:
78
Which is a release and which should match tag.
79
For now, if we have a date-embedded version, check to see if it's
80
old, and if so re-generate. Otherwise, just deal with it.
83
version_date = int(self.version.split("~")[-1].split('.')[0])
84
if version_date < int(datetime.date.today().strftime('%Y%m%d')):
85
return self._generate_version()
87
return pending_version
89
return pending_version
91
def version_string_with_vcs(self, always=False):
92
"""Return the full version of the package including suffixes indicating
95
For instance, if we are working towards the 2012.2 release,
96
canonical_version_string should return 2012.2 if this is a final
97
release, or else something like 2012.2~f1~20120705.20 if it's not.
99
:param always: if true, skip all version caching
102
self.version = self._generate_version()
104
if self.version is None:
106
requirement = pkg_resources.Requirement.parse(self.python_package)
107
versioninfo = "%s/versioninfo" % self.package
109
raw_version = pkg_resources.resource_string(requirement,
111
self.version = self._newer_version(raw_version.strip())
112
except (IOError, pkg_resources.DistributionNotFound):
113
self.version = self._generate_version()
117
def canonical_version_string(self, always=False):
118
"""Return the simple version of the package excluding any suffixes.
120
For instance, if we are working towards the 2012.2 release,
121
canonical_version_string should return 2012.2 in all cases.
123
:param always: if true, skip all version caching
125
return self.version_string_with_vcs(always).split('~')[0]
127
def version_string(self, always=False):
128
"""Return the base version of the package.
130
For instance, if we are working towards the 2012.2 release,
131
version_string should return 2012.2 if this is a final release, or
132
2012.2-dev if it is not.
134
:param always: if true, skip all version caching
136
version_parts = self.version_string_with_vcs(always).split('~')
137
if len(version_parts) == 1:
138
return version_parts[0]
140
return '%s-dev' % (version_parts[0],)
142
def deferred_version_string(self, prefix=""):
143
"""Generate an object which will expand in a string context to
144
the results of version_string(). We do this so that don't
145
call into pkg_resources every time we start up a program when
146
passing version information into the CONF constructor, but
147
rather only do the calculation when and if a version is requested
149
return _deferred_version_string(self, prefix)