Completed
Pull Request — master (#125)
by Michael
06:04 queued 05:30
created

stage()   F

Complexity

Conditions 12

Size

Total Lines 86

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 27
CRAP Score 13.7202

Importance

Changes 10
Bugs 1 Features 0
Metric Value
cc 12
c 10
b 1
f 0
dl 0
loc 86
ccs 27
cts 35
cp 0.7714
crap 13.7202
rs 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like stage() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1 3
import difflib
0 ignored issues
show
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 -> changes.config).

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...
Bug introduced by
There seems to be a cyclic import (changes -> changes.cli -> changes.commands.init).

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 3
from datetime import date
3 3
from pathlib import Path
4
5 3
import bumpversion
0 ignored issues
show
Configuration introduced by
The import bumpversion could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
6 3
import click
0 ignored issues
show
Configuration introduced by
The import click could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
7 3
from plumbum.cmd import git
0 ignored issues
show
Configuration introduced by
The import plumbum.cmd could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
8 3
import pkg_resources
9 3
from jinja2 import Template
0 ignored issues
show
Configuration introduced by
The import jinja2 could not be resolved.

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
10
11 3
import changes
12 3
from changes.config import BumpVersion
13 3
from changes.models import Release, changes_to_release_type
14 3
from . import info, error, debug, STYLES
15
16
17 3
def discard(release_name='', release_description=''):
18 3
    bumpversion_part, release_type, proposed_version = changes_to_release_type(
19
        changes.project_settings.repository
20
    )
21 3
    release = Release(
22
        name=release_name,
23
        release_date=date.today().isoformat(),
24
        version=str(proposed_version),
25
        description=release_description,
26
    )
27
28 3
    if release.version == str(changes.project_settings.repository.latest_version):
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (82/79).

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

Loading history...
29 3
        info('No staged release to discard')
30 3
        return
31
32 3
    info('Discarding currently staged release {}'.format(release.version))
33
34 3
    settings = changes.project_settings
35
36 3
    release_notes_path = Path(settings.releases_directory).joinpath(
37
        '{}.md'.format(release.version)
38
    )
39
40 3
    modified_bumpversion_files = BumpVersion.read_from_file(Path('.bumpversion.cfg')).version_files_to_replace
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (110/79).

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

Loading history...
41 3
    git_discard_files = (
42
        modified_bumpversion_files +
43
        [
44
            '.bumpversion.cfg',
45
        ]
46
    )
47
48 3
    info('Running: git {}'.format(' '.join(
49
        ['checkout', '--'] + git_discard_files
50
    )))
51 3
    git(['checkout', '--'] + git_discard_files)
52
53 3
    if release_notes_path.exists():
0 ignored issues
show
Bug introduced by
The Instance of PurePath does not seem to have a member named exists.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
54 3
        info('Running: rm {}'.format(
55
            release_notes_path,
56
        ))
57 3
        release_notes_path.unlink()
0 ignored issues
show
Bug introduced by
The Instance of PurePath does not seem to have a member named unlink.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
58
59
60 3
def stage(draft, release_name='', release_description=''):
61
62 3
    repository = changes.project_settings.repository
63 3
    bumpversion_part, release_type, proposed_version = changes_to_release_type(repository)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (90/79).

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

Loading history...
64
65 3
    if not repository.changes_since_last_version:
66
        error("There aren't any changes to release since {}".format(proposed_version))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (86/79).

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

Loading history...
67
        return
68
69 3
    info('Staging [{}] release for version {}'.format(
70
        release_type,
71
        proposed_version
72
    ))
73
74 3
    if BumpVersion.read_from_file(Path('.bumpversion.cfg')).current_version == str(proposed_version):
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (101/79).

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

Loading history...
75
        info('Version already bumped to {}'.format(proposed_version))
76
    else:
77 3
        bumpversion_arguments = (
78
            BumpVersion.DRAFT_OPTIONS if draft
79
            else BumpVersion.STAGE_OPTIONS
80
        ) + [bumpversion_part]
81
82 3
        info('Running: bumpversion {}'.format(
83
            ' '.join(bumpversion_arguments)
84
        ))
85 3
        bumpversion.main(bumpversion_arguments)
86
87 3
    info('Generating Release')
88
    # prepare context for changelog documentation
89 3
    project_labels = changes.project_settings.labels
90 3
    for label, properties in project_labels.items():
91 3
        pull_requests_with_label = [
92
            pull_request
93
            for pull_request in repository.changes_since_last_version
94
            if label in pull_request.labels
95
        ]
96
97 3
        project_labels[label]['pull_requests'] = pull_requests_with_label
98
99 3
    release = Release(
100
        name=release_name,
101
        release_date=date.today().isoformat(),
102
        version=str(proposed_version),
103
        description=release_description,
104
        changes=project_labels,
105
    )
106
107
    # TODO: if project_settings.release_notes_template is None
108 3
    release_notes_template = pkg_resources.resource_string(
109
        changes.__name__,
110
        'templates/release_notes_template.md'
111
    ).decode('utf8')
112
113 3
    release_notes = Template(release_notes_template).render(release=release)
114
115 3
    releases_directory = Path(changes.project_settings.releases_directory)
116 3
    if not releases_directory.exists():
117 3
        releases_directory.mkdir(parents=True)
118
119 3
    release_notes_path = releases_directory.joinpath(
120
        '{}.md'.format(release.version)
121
    )
122
123 3
    if draft:
124 3
        info('Would have created {}:'.format(release_notes_path))
125 3
        debug(release_notes)
126
    else:
127 3
        info('Writing release notes to {}'.format(release_notes_path))
128 3
        if release_notes_path.exists():
0 ignored issues
show
Bug introduced by
The Instance of PurePath does not seem to have a member named exists.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
129
            release_notes_content = release_notes_path.read_text(encoding='utf-8')
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (82/79).

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

Loading history...
Bug introduced by
The Instance of PurePath does not seem to have a member named read_text.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
130
            if release_notes_content != release_notes:
131
                info('\n'.join(difflib.unified_diff(
132
                    release_notes_content.splitlines(),
133
                    release_notes.splitlines(),
134
                    fromfile=str(release_notes_path),
135
                    tofile=str(release_notes_path)
136
                )))
137
                if click.confirm(
138
                    click.style(
139
                        '{} has modified content, overwrite?'.format(release_notes_path),
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (89/79).

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

Loading history...
140
                        **STYLES['error']
141
                    )
142
                ):
143
                    release_notes_path.write_text(release_notes, encoding='utf-8')
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (82/79).

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

Loading history...
Bug introduced by
The Instance of PurePath does not seem to have a member named write_text.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
144
        else:
145
            release_notes_path.write_text(release_notes, encoding='utf-8')
0 ignored issues
show
Bug introduced by
The Instance of PurePath does not seem to have a member named write_text.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
146