Passed
Pull Request — master (#7)
by Matt
01:37
created

version.py (14 issues)

1
# -*- coding: utf-8 -*-
0 ignored issues
show
This module should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
2
# Author: Douglas Creager <[email protected]>
3
# This file is placed into the public domain.
4
5
# Calculates the current version number.  If possible, this is the
6
# output of “git describe”, modified to conform to the versioning
7
# scheme that setuptools uses.  If “git describe” returns an error
8
# (most likely because we're in an unpacked copy of a release tarball,
9
# rather than in a git working copy), then we fall back on reading the
10
# contents of the RELEASE-VERSION file.
11
#
12
# To use this script, simply import it your setup.py file, and use the
13
# results of get_git_version() as your package version:
14
#
15
# from version import *
16
#
17
# setup(
18
#     version=get_git_version(),
19
#     .
20
#     .
21
#     .
22
# )
23
#
24
# This will automatically update the RELEASE-VERSION file, if
25
# necessary.  Note that the RELEASE-VERSION file should *not* be
26
# checked into git; please add it to your top-level .gitignore file.
27
#
28
# You'll probably want to distribute the RELEASE-VERSION file in your
29
# sdist tarballs; to do this, just create a MANIFEST.in file that
30
# contains the following line:
31
#
32
#   include RELEASE-VERSION
33
34
from __future__ import print_function
35
36
import os
37
import subprocess
38
39
__all__ = ("get_git_version")
40
41
42
def call_git_describe(abbrev=4):
0 ignored issues
show
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
43
    runner = GitRunner()
44
    output = runner.run_git(['rev-parse', '--abbrev-ref', 'HEAD'])
45
    branch = output[0].strip()
46
47
    output = runner.run_git(['describe', '--long', '--abbrev=%d' % abbrev])
48
    tag = output[0].strip()
49
    release, commits_ahead, _ = tag.split('-')
50
    commits_ahead = int(commits_ahead)
51
    if commits_ahead:
52
        if 'master' == branch:
0 ignored issues
show
Comparison should be branch == 'master'
Loading history...
53
            return "{t}.post{c}".format(t=release, c=commits_ahead)
54
        else:
55
            return "{t}.dev{c}".format(t=release, c=commits_ahead)
56
    else:
57
        return release
58
59
60
def read_release_version():
0 ignored issues
show
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
61
    try:
62
        with open(get_release_version_path(), "r") as f:
0 ignored issues
show
Coding Style Naming introduced by
The name f does not conform to the variable naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
63
            version = f.readlines()[0]
64
            return version.strip()
65
    except (IOError, OSError):
66
        return None
67
68
69
def get_release_version_path():
0 ignored issues
show
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
70
    top_level_dir = os.path.dirname(os.path.abspath(__file__))
71
    assert os.path.isdir(top_level_dir)
72
    rv_path = os.path.join(top_level_dir, 'RELEASE-VERSION')
73
    return rv_path
74
75
76
def write_release_version(version):
0 ignored issues
show
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
77
    f = open(get_release_version_path(), "w")
0 ignored issues
show
Coding Style Naming introduced by
The name f does not conform to the variable naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
78
    f.write("%s\n" % version)
79
    f.close()
80
81
82
def get_git_version(abbrev=4):
0 ignored issues
show
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
83
    # Read in the version that's currently in RELEASE-VERSION.
84
    release_version = read_release_version()
85
86
    # First try to get the current version using “git describe”.
87
    try:
88
        version = call_git_describe(abbrev)
89
    except GitError:
90
        # We're probably operating from a source dist
91
        version = None
92
93
    # If that doesn't work, fall back on the value that's in
94
    # RELEASE-VERSION.
95
    if version is None:
96
        version = release_version
97
98
    # If we still don't have anything, that's an error.
99
    if version is None:
100
        raise ValueError("Cannot find the version number!")
101
102
    # If the current version is different from what's in the
103
    # RELEASE-VERSION file, update the file to be current.
104
    if version != release_version:
105
        write_release_version(version)
106
107
    # Finally, return the current version.
108
    return version
109
110
111
class GitError(Exception):
0 ignored issues
show
This class should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
112
    pass
113
114
115
class GitRunner(object):
0 ignored issues
show
This class should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
116
    _toplevel_args = ['rev-parse', '--show-toplevel']
117
    _version_args = ['--version']
118
    _git_executable = 'git'
119
    _min_binary_ver = (1, 7, 2)
120
121
    def __init__(self):
122
        self._git_toplevel = None
123
        self._get_git_root()
124
125
    def _get_git_root(self):
0 ignored issues
show
This method should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
126
        # We should probably go beyond just finding the root dir for the Git
127
        # repo and do some sanity-checking on git itself
128
        top_level_dir = self.run_git(GitRunner._toplevel_args)
129
        self._git_toplevel = top_level_dir[0]
130
131
    def run_git(self, args, git_env=None):
132
        '''
133
        Runs the git executable with the arguments given and returns a list of
134
        lines produced on its standard output.
135
        '''
136
137
        popen_kwargs = {
138
            'stdout': subprocess.PIPE,
139
            'stderr': subprocess.PIPE,
140
        }
141
142
        if git_env:
143
            popen_kwargs['env'] = git_env
144
145
        if self._git_toplevel:
146
            popen_kwargs['cwd'] = self._git_toplevel
147
148
        git_process = subprocess.Popen(
149
            [GitRunner._git_executable] + args,
150
            **popen_kwargs
151
        )
152
153
        try:
154
            out, err = git_process.communicate()
155
            git_process.wait()
156
        except Exception as e:
0 ignored issues
show
Coding Style Naming introduced by
The name e does not conform to the variable naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
157
            raise GitError("Couldn't run 'git {args}':{newline}{ex}".format(
158
                args=' '.join(args),
159
                newline=os.linesep,
160
                ex=str(e)
161
            ))
162
163
        if (0 != git_process.returncode) or err:
0 ignored issues
show
Comparison should be git_process.returncode != 0
Loading history...
164
            if err:
165
                err = err.decode('utf_8')
166
            raise GitError("'git {args}' failed with:{newline}{err}".format(
167
                args=' '.join(args),
168
                newline=os.linesep,
169
                err=err
170
            ))
171
172
        if not out:
173
            raise ValueError("No output")
174
175
        return out.decode('utf_8').splitlines()
176
177
178
if __name__ == "__main__":
179
    print(get_git_version())
180