1# coding: utf-8
2from __future__ import unicode_literals, division, absolute_import, print_function
3
4import codecs
5import os
6import re
7
8from . import package_root, package_name, has_tests_package
9
10
11run_args = [
12    {
13        'name': 'pep440_version',
14        'required': True
15    },
16]
17
18
19def run(new_version):
20    """
21    Updates the package version in the various locations
22
23    :param new_version:
24        A unicode string of the new library version as a PEP 440 version
25
26    :return:
27        A bool - if the version number was successfully bumped
28    """
29
30    # We use a restricted form of PEP 440 versions
31    version_match = re.match(
32        r'(\d+)\.(\d+)\.(\d)+(?:\.((?:dev|a|b|rc)\d+))?$',
33        new_version
34    )
35    if not version_match:
36        raise ValueError('Invalid PEP 440 version: %s' % new_version)
37
38    new_version_info = (
39        int(version_match.group(1)),
40        int(version_match.group(2)),
41        int(version_match.group(3)),
42    )
43    if version_match.group(4):
44        new_version_info += (version_match.group(4),)
45
46    version_path = os.path.join(package_root, package_name, 'version.py')
47    setup_path = os.path.join(package_root, 'setup.py')
48    setup_tests_path = os.path.join(package_root, 'tests', 'setup.py')
49    tests_path = os.path.join(package_root, 'tests', '__init__.py')
50
51    file_paths = [version_path, setup_path]
52    if has_tests_package:
53        file_paths.extend([setup_tests_path, tests_path])
54
55    for file_path in file_paths:
56        orig_source = ''
57        with codecs.open(file_path, 'r', encoding='utf-8') as f:
58            orig_source = f.read()
59
60        found = 0
61        new_source = ''
62        for line in orig_source.splitlines(True):
63            if line.startswith('__version__ = '):
64                found += 1
65                new_source += '__version__ = %r\n' % new_version
66            elif line.startswith('__version_info__ = '):
67                found += 1
68                new_source += '__version_info__ = %r\n' % (new_version_info,)
69            elif line.startswith('PACKAGE_VERSION = '):
70                found += 1
71                new_source += 'PACKAGE_VERSION = %r\n' % new_version
72            else:
73                new_source += line
74
75        if found == 0:
76            raise ValueError('Did not find any versions in %s' % file_path)
77
78        s = 's' if found > 1 else ''
79        rel_path = file_path[len(package_root) + 1:]
80        was_were = 'was' if found == 1 else 'were'
81        if new_source != orig_source:
82            print('Updated %d version%s in %s' % (found, s, rel_path))
83            with codecs.open(file_path, 'w', encoding='utf-8') as f:
84                f.write(new_source)
85        else:
86            print('%d version%s in %s %s up-to-date' % (found, s, rel_path, was_were))
87
88    return True
89