Completed
Push — pyup-update-pytest-3.2.3-to-3.... ( 5144af )
by Michael
07:18 queued 07:12
created

BumpVersion.load()   B

Complexity

Conditions 4

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 4
c 2
b 0
f 0
dl 0
loc 33
rs 8.5806
1
import re
0 ignored issues
show
Bug introduced by
There seems to be a cyclic import (changes -> changes.cli -> changes.commands.publish).

Cyclic imports may cause partly loaded modules to be returned. This might lead to unexpected runtime behavior which is hard to debug.

Loading history...
Bug introduced by
There seems to be a cyclic import (changes -> changes.cli -> changes.commands.status).

Cyclic imports may cause partly loaded modules to be returned. This might lead to unexpected runtime behavior which is hard to debug.

Loading history...
Bug introduced by
There seems to be a cyclic import (changes -> changes.cli -> changes.commands.stage).

Cyclic imports may cause partly loaded modules to be returned. This might lead to unexpected runtime behavior which is hard to debug.

Loading history...
2
import textwrap
3
from configparser import RawConfigParser
4
from enum import Enum
5
from pathlib import Path
6
7
import attr
8
import click
9
10
11
class ReleaseType(str, Enum):
12
    NO_CHANGE = 'no-changes'
13
    BREAKING_CHANGE = 'breaking'
14
    FEATURE = 'feature'
15
    FIX = 'fix'
16
17
18
@attr.s
19
class Release(object):
20
    release_date = attr.ib()
21
    version = attr.ib()
22
    description = attr.ib(default=attr.Factory(str))
23
    name = attr.ib(default=attr.Factory(str))
24
    notes = attr.ib(default=attr.Factory(dict))
25
    release_file_path = attr.ib(default='')
26
27
    bumpversion_part = attr.ib(default=None)
28
    release_type = attr.ib(default=None)
29
30
    @property
31
    def title(self):
32
        return '{version} ({release_date})'.format(
33
            version=self.version,
34
            release_date=self.release_date
35
        ) + ((' ' + self.name) if self.name else '')
36
37
    @property
38
    def release_note_filename(self):
39
        return '{version}-{release_date}'.format(
40
            version=self.version,
41
            release_date=self.release_date
42
        ) + (('-' + self.name) if self.name else '')
43
44
    @classmethod
45
    def generate_notes(cls, project_labels, pull_requests_since_latest_version):
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (80/79).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
46
        for label, properties in project_labels.items():
47
            pull_requests_with_label = [
48
                pull_request
49
                for pull_request in pull_requests_since_latest_version
50
                if label in pull_request.label_names
51
            ]
52
53
            project_labels[label]['pull_requests'] = pull_requests_with_label
54
55
        return project_labels
56
57
58
@attr.s
59
class BumpVersion(object):
60
    DRAFT_OPTIONS = [
61
        '--dry-run', '--verbose',
62
        '--no-commit', '--no-tag',
63
        '--allow-dirty',
64
    ]
65
    STAGE_OPTIONS = [
66
        '--verbose', '--allow-dirty',
67
        '--no-commit', '--no-tag',
68
    ]
69
70
    current_version = attr.ib()
71
    version_files_to_replace = attr.ib(default=attr.Factory(list))
72
73
    @classmethod
74
    def load(cls, latest_version):
75
        # TODO: look in other supported bumpversion config locations
76
        bumpversion = None
77
        bumpversion_config_path = Path('.bumpversion.cfg')
78
        if not bumpversion_config_path.exists():
79
            user_supplied_versioned_file_paths = []
80
81
            version_file_path_answer = None
82
            input_terminator = '.'
83
            while not version_file_path_answer == input_terminator:
84
                version_file_path_answer = click.prompt(
85
                    'Enter a path to a file that contains a version number '
86
                    "(enter a path of '.' when you're done selecting files)",
87
                    type=click.Path(
88
                        exists=True,
89
                        dir_okay=True,
90
                        file_okay=True,
91
                        readable=True
92
                    )
93
                )
94
95
                if version_file_path_answer != input_terminator:
96
                    user_supplied_versioned_file_paths.append(
97
                        version_file_path_answer)
98
99
            bumpversion = cls(
100
                current_version=latest_version,
101
                version_files_to_replace=user_supplied_versioned_file_paths,
102
            )
103
            bumpversion.write_to_file(bumpversion_config_path)
104
105
        return bumpversion
106
107
    @classmethod
108
    def read_from_file(cls, config_path: Path):
109
        config = RawConfigParser('')
110
        config.readfp(config_path.open('rt', encoding='utf-8'))
111
112
        current_version = config.get("bumpversion", 'current_version')
113
114
        filenames = []
115
        for section_name in config.sections():
116
117
            section_name_match = re.compile(
118
                "^bumpversion:(file|part):(.+)").match(section_name)
119
120
            if not section_name_match:
121
                continue
122
123
            section_prefix, section_value = section_name_match.groups()
124
125
            if section_prefix == "file":
126
                filenames.append(section_value)
127
128
        return cls(
129
            current_version=current_version,
130
            version_files_to_replace=filenames,
131
        )
132
133
    def write_to_file(self, config_path: Path):
134
        bumpversion_cfg = textwrap.dedent(
135
            """\
136
            [bumpversion]
137
            current_version = {current_version}
138
139
            """
140
        ).format(**attr.asdict(self))
141
142
        bumpversion_files = '\n\n'.join([
143
            '[bumpversion:file:{}]'.format(file_name)
144
            for file_name in self.version_files_to_replace
145
        ])
146
147
        config_path.write_text(
148
            bumpversion_cfg + bumpversion_files
149
        )
150