~ubuntu-branches/ubuntu/trusty/cinder/trusty

« back to all changes in this revision

Viewing changes to .pc/fix-ubuntu-tests.patch/cinder/openstack/common/setup.py

  • Committer: Package Import Robot
  • Author(s): James Page, Chuck Short, James Page
  • Date: 2013-03-16 09:30:20 UTC
  • mfrom: (1.1.12)
  • Revision ID: package-import@ubuntu.com-20130316093020-xnaqjbr18uhkti6l
Tags: 1:2013.1~rc1-0ubuntu1
[ Chuck Short ]
* debian/patches/fix-ubuntu-tests.patch: Dropped.
* debian/rules: Fix version number when building the testsuite. 
* debian/cinder-backup{.install, upstart, logroate}: Add cinder-backup
  service.
* debian/rules: Run the testsuite against PYTHONPATH.
* debian/control: Update build-depends and run-time depends.
  - Dropped python-glance not needed.
  - Dropped python-cheetah not needed.
  - Droped python-daemon not needed.
  - Dropped python-netaddr not needed.
  - Renamed python-oslo-config to python-oslo.config.
  - Added python-keystoneclient to depends.
  - Added python-swiftclient to depends.
 * debian/pydist-overrides: No longer needed.

[ James Page ]
* New upstream release candidate.
* d/watch: Update uversionmangle to deal with upstream versioning
  changes, remove tarballs.openstack.org.
* d/cinder.conf: Set lock_path to /var/lock/cinder (default is not
  sensible).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# vim: tabstop=4 shiftwidth=4 softtabstop=4
2
 
 
3
 
# Copyright 2011 OpenStack LLC.
4
 
# Copyright 2012-2013 Hewlett-Packard Development Company, L.P.
5
 
# All Rights Reserved.
6
 
#
7
 
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
8
 
#    not use this file except in compliance with the License. You may obtain
9
 
#    a copy of the License at
10
 
#
11
 
#         http://www.apache.org/licenses/LICENSE-2.0
12
 
#
13
 
#    Unless required by applicable law or agreed to in writing, software
14
 
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
 
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
 
#    License for the specific language governing permissions and limitations
17
 
#    under the License.
18
 
 
19
 
"""
20
 
Utilities with minimum-depends for use in setup.py
21
 
"""
22
 
 
23
 
import email
24
 
import os
25
 
import re
26
 
import subprocess
27
 
import sys
28
 
 
29
 
from setuptools.command import sdist
30
 
 
31
 
 
32
 
def parse_mailmap(mailmap='.mailmap'):
33
 
    mapping = {}
34
 
    if os.path.exists(mailmap):
35
 
        with open(mailmap, 'r') as fp:
36
 
            for l in fp:
37
 
                try:
38
 
                    canonical_email, alias = re.match(
39
 
                        r'[^#]*?(<.+>).*(<.+>).*', l).groups()
40
 
                except AttributeError:
41
 
                    continue
42
 
                mapping[alias] = canonical_email
43
 
    return mapping
44
 
 
45
 
 
46
 
def canonicalize_emails(changelog, mapping):
47
 
    """Takes in a string and an email alias mapping and replaces all
48
 
       instances of the aliases in the string with their real email.
49
 
    """
50
 
    for alias, email_address in mapping.iteritems():
51
 
        changelog = changelog.replace(alias, email_address)
52
 
    return changelog
53
 
 
54
 
 
55
 
# Get requirements from the first file that exists
56
 
def get_reqs_from_files(requirements_files):
57
 
    for requirements_file in requirements_files:
58
 
        if os.path.exists(requirements_file):
59
 
            with open(requirements_file, 'r') as fil:
60
 
                return fil.read().split('\n')
61
 
    return []
62
 
 
63
 
 
64
 
def parse_requirements(requirements_files=['requirements.txt',
65
 
                                           'tools/pip-requires']):
66
 
    requirements = []
67
 
    for line in get_reqs_from_files(requirements_files):
68
 
        # For the requirements list, we need to inject only the portion
69
 
        # after egg= so that distutils knows the package it's looking for
70
 
        # such as:
71
 
        # -e git://github.com/openstack/nova/master#egg=nova
72
 
        if re.match(r'\s*-e\s+', line):
73
 
            requirements.append(re.sub(r'\s*-e\s+.*#egg=(.*)$', r'\1',
74
 
                                line))
75
 
        # such as:
76
 
        # http://github.com/openstack/nova/zipball/master#egg=nova
77
 
        elif re.match(r'\s*https?:', line):
78
 
            requirements.append(re.sub(r'\s*https?:.*#egg=(.*)$', r'\1',
79
 
                                line))
80
 
        # -f lines are for index locations, and don't get used here
81
 
        elif re.match(r'\s*-f\s+', line):
82
 
            pass
83
 
        # argparse is part of the standard library starting with 2.7
84
 
        # adding it to the requirements list screws distro installs
85
 
        elif line == 'argparse' and sys.version_info >= (2, 7):
86
 
            pass
87
 
        else:
88
 
            requirements.append(line)
89
 
 
90
 
    return requirements
91
 
 
92
 
 
93
 
def parse_dependency_links(requirements_files=['requirements.txt',
94
 
                                               'tools/pip-requires']):
95
 
    dependency_links = []
96
 
    # dependency_links inject alternate locations to find packages listed
97
 
    # in requirements
98
 
    for line in get_reqs_from_files(requirements_files):
99
 
        # skip comments and blank lines
100
 
        if re.match(r'(\s*#)|(\s*$)', line):
101
 
            continue
102
 
        # lines with -e or -f need the whole line, minus the flag
103
 
        if re.match(r'\s*-[ef]\s+', line):
104
 
            dependency_links.append(re.sub(r'\s*-[ef]\s+', '', line))
105
 
        # lines that are only urls can go in unmolested
106
 
        elif re.match(r'\s*https?:', line):
107
 
            dependency_links.append(line)
108
 
    return dependency_links
109
 
 
110
 
 
111
 
def _run_shell_command(cmd, throw_on_error=False):
112
 
    if os.name == 'nt':
113
 
        output = subprocess.Popen(["cmd.exe", "/C", cmd],
114
 
                                  stdout=subprocess.PIPE,
115
 
                                  stderr=subprocess.PIPE)
116
 
    else:
117
 
        output = subprocess.Popen(["/bin/sh", "-c", cmd],
118
 
                                  stdout=subprocess.PIPE,
119
 
                                  stderr=subprocess.PIPE)
120
 
    if output.returncode and throw_on_error:
121
 
        raise Exception("%s returned %d" % cmd, output.returncode)
122
 
    out = output.communicate()
123
 
    if len(out) == 0:
124
 
        return None
125
 
    if len(out[0].strip()) == 0:
126
 
        return None
127
 
    return out[0].strip()
128
 
 
129
 
 
130
 
def write_git_changelog():
131
 
    """Write a changelog based on the git changelog."""
132
 
    new_changelog = 'ChangeLog'
133
 
    if not os.getenv('SKIP_WRITE_GIT_CHANGELOG'):
134
 
        if os.path.isdir('.git'):
135
 
            git_log_cmd = 'git log --stat'
136
 
            changelog = _run_shell_command(git_log_cmd)
137
 
            mailmap = parse_mailmap()
138
 
            with open(new_changelog, "w") as changelog_file:
139
 
                changelog_file.write(canonicalize_emails(changelog, mailmap))
140
 
    else:
141
 
        open(new_changelog, 'w').close()
142
 
 
143
 
 
144
 
def generate_authors():
145
 
    """Create AUTHORS file using git commits."""
146
 
    jenkins_email = 'jenkins@review.(openstack|stackforge).org'
147
 
    old_authors = 'AUTHORS.in'
148
 
    new_authors = 'AUTHORS'
149
 
    if not os.getenv('SKIP_GENERATE_AUTHORS'):
150
 
        if os.path.isdir('.git'):
151
 
            # don't include jenkins email address in AUTHORS file
152
 
            git_log_cmd = ("git log --format='%aN <%aE>' | sort -u | "
153
 
                           "egrep -v '" + jenkins_email + "'")
154
 
            changelog = _run_shell_command(git_log_cmd)
155
 
            mailmap = parse_mailmap()
156
 
            with open(new_authors, 'w') as new_authors_fh:
157
 
                new_authors_fh.write(canonicalize_emails(changelog, mailmap))
158
 
                if os.path.exists(old_authors):
159
 
                    with open(old_authors, "r") as old_authors_fh:
160
 
                        new_authors_fh.write('\n' + old_authors_fh.read())
161
 
    else:
162
 
        open(new_authors, 'w').close()
163
 
 
164
 
 
165
 
_rst_template = """%(heading)s
166
 
%(underline)s
167
 
 
168
 
.. automodule:: %(module)s
169
 
  :members:
170
 
  :undoc-members:
171
 
  :show-inheritance:
172
 
"""
173
 
 
174
 
 
175
 
def get_cmdclass():
176
 
    """Return dict of commands to run from setup.py."""
177
 
 
178
 
    cmdclass = dict()
179
 
 
180
 
    def _find_modules(arg, dirname, files):
181
 
        for filename in files:
182
 
            if filename.endswith('.py') and filename != '__init__.py':
183
 
                arg["%s.%s" % (dirname.replace('/', '.'),
184
 
                               filename[:-3])] = True
185
 
 
186
 
    class LocalSDist(sdist.sdist):
187
 
        """Builds the ChangeLog and Authors files from VC first."""
188
 
 
189
 
        def run(self):
190
 
            write_git_changelog()
191
 
            generate_authors()
192
 
            # sdist.sdist is an old style class, can't use super()
193
 
            sdist.sdist.run(self)
194
 
 
195
 
    cmdclass['sdist'] = LocalSDist
196
 
 
197
 
    # If Sphinx is installed on the box running setup.py,
198
 
    # enable setup.py to build the documentation, otherwise,
199
 
    # just ignore it
200
 
    try:
201
 
        from sphinx.setup_command import BuildDoc
202
 
 
203
 
        class LocalBuildDoc(BuildDoc):
204
 
 
205
 
            builders = ['html', 'man']
206
 
 
207
 
            def generate_autoindex(self):
208
 
                print "**Autodocumenting from %s" % os.path.abspath(os.curdir)
209
 
                modules = {}
210
 
                option_dict = self.distribution.get_option_dict('build_sphinx')
211
 
                source_dir = os.path.join(option_dict['source_dir'][1], 'api')
212
 
                if not os.path.exists(source_dir):
213
 
                    os.makedirs(source_dir)
214
 
                for pkg in self.distribution.packages:
215
 
                    if '.' not in pkg:
216
 
                        os.path.walk(pkg, _find_modules, modules)
217
 
                module_list = modules.keys()
218
 
                module_list.sort()
219
 
                autoindex_filename = os.path.join(source_dir, 'autoindex.rst')
220
 
                with open(autoindex_filename, 'w') as autoindex:
221
 
                    autoindex.write(""".. toctree::
222
 
   :maxdepth: 1
223
 
 
224
 
""")
225
 
                    for module in module_list:
226
 
                        output_filename = os.path.join(source_dir,
227
 
                                                       "%s.rst" % module)
228
 
                        heading = "The :mod:`%s` Module" % module
229
 
                        underline = "=" * len(heading)
230
 
                        values = dict(module=module, heading=heading,
231
 
                                      underline=underline)
232
 
 
233
 
                        print "Generating %s" % output_filename
234
 
                        with open(output_filename, 'w') as output_file:
235
 
                            output_file.write(_rst_template % values)
236
 
                        autoindex.write("   %s.rst\n" % module)
237
 
 
238
 
            def run(self):
239
 
                if not os.getenv('SPHINX_DEBUG'):
240
 
                    self.generate_autoindex()
241
 
 
242
 
                for builder in self.builders:
243
 
                    self.builder = builder
244
 
                    self.finalize_options()
245
 
                    self.project = self.distribution.get_name()
246
 
                    self.version = self.distribution.get_version()
247
 
                    self.release = self.distribution.get_version()
248
 
                    BuildDoc.run(self)
249
 
 
250
 
        class LocalBuildLatex(LocalBuildDoc):
251
 
            builders = ['latex']
252
 
 
253
 
        cmdclass['build_sphinx'] = LocalBuildDoc
254
 
        cmdclass['build_sphinx_latex'] = LocalBuildLatex
255
 
    except ImportError:
256
 
        pass
257
 
 
258
 
    return cmdclass
259
 
 
260
 
 
261
 
def _get_revno():
262
 
    """Return the number of commits since the most recent tag.
263
 
 
264
 
    We use git-describe to find this out, but if there are no
265
 
    tags then we fall back to counting commits since the beginning
266
 
    of time.
267
 
    """
268
 
    describe = _run_shell_command("git describe --always")
269
 
    if "-" in describe:
270
 
        return describe.rsplit("-", 2)[-2]
271
 
 
272
 
    # no tags found
273
 
    revlist = _run_shell_command("git rev-list --abbrev-commit HEAD")
274
 
    return len(revlist.splitlines())
275
 
 
276
 
 
277
 
def get_version_from_git(pre_version):
278
 
    """Return a version which is equal to the tag that's on the current
279
 
    revision if there is one, or tag plus number of additional revisions
280
 
    if the current revision has no tag."""
281
 
 
282
 
    if os.path.isdir('.git'):
283
 
        if pre_version:
284
 
            try:
285
 
                return _run_shell_command(
286
 
                    "git describe --exact-match",
287
 
                    throw_on_error=True).replace('-', '.')
288
 
            except Exception:
289
 
                sha = _run_shell_command("git log -n1 --pretty=format:%h")
290
 
                return "%s.a%s.g%s" % (pre_version, _get_revno(), sha)
291
 
        else:
292
 
            return _run_shell_command(
293
 
                "git describe --always").replace('-', '.')
294
 
    return None
295
 
 
296
 
 
297
 
def get_version_from_pkg_info(package_name):
298
 
    """Get the version from PKG-INFO file if we can."""
299
 
    try:
300
 
        pkg_info_file = open('PKG-INFO', 'r')
301
 
    except (IOError, OSError):
302
 
        return None
303
 
    try:
304
 
        pkg_info = email.message_from_file(pkg_info_file)
305
 
    except email.MessageError:
306
 
        return None
307
 
    # Check to make sure we're in our own dir
308
 
    if pkg_info.get('Name', None) != package_name:
309
 
        return None
310
 
    return pkg_info.get('Version', None)
311
 
 
312
 
 
313
 
def get_version(package_name, pre_version=None):
314
 
    """Get the version of the project. First, try getting it from PKG-INFO, if
315
 
    it exists. If it does, that means we're in a distribution tarball or that
316
 
    install has happened. Otherwise, if there is no PKG-INFO file, pull the
317
 
    version from git.
318
 
 
319
 
    We do not support setup.py version sanity in git archive tarballs, nor do
320
 
    we support packagers directly sucking our git repo into theirs. We expect
321
 
    that a source tarball be made from our git repo - or that if someone wants
322
 
    to make a source tarball from a fork of our repo with additional tags in it
323
 
    that they understand and desire the results of doing that.
324
 
    """
325
 
    version = os.environ.get("OSLO_PACKAGE_VERSION", None)
326
 
    if version:
327
 
        return version
328
 
    version = get_version_from_pkg_info(package_name)
329
 
    if version:
330
 
        return version
331
 
    version = get_version_from_git(pre_version)
332
 
    if version:
333
 
        return version
334
 
    raise Exception("Versioning for this project requires either an sdist"
335
 
                    " tarball, or access to an upstream git repository.")