Completed
Pull Request — master (#290)
by Jace
03:06
created

describe_template()   F

Complexity

Conditions 53

Size

Total Lines 193

Duplication

Lines 33
Ratio 17.1 %

Importance

Changes 5
Bugs 0 Features 0
Metric Value
cc 53
dl 33
loc 193
rs 2
c 5
b 0
f 0

43 Methods

Rating   Name   Duplication   Size   Complexity  
A it_returns_alternate_when_style_provided() 0 3 1
A is_placeholder_when_no_lines() 0 4 1
A describe_sample_path() 0 9 3
A it_considers_urls_valid_styles() 0 5 1
A it_caches_file_downloads() 0 5 1
A describe_styles() 0 9 3
A it_handles_invalid_paths() 0 2 1
A it_supports_comparison() 0 8 4
A it_returns_default_when_no_style() 0 3 1
A is_underscore_when_no_lines() 0 4 1
A it_returns_default_when_style_is_none() 0 3 1
A is_based_on_lines() 0 2 1
A describe_default_path() 0 9 3
D describe_get_path() 0 31 8
A is_empty_when_no_alternate_images() 0 3 1
A is_filesnames_of_alternate_images() 0 3 1
A it_handles_bad_urls() 0 2 1
A with_missing_split() 0 4 1
A is_none_when_no_file() 7 7 2
A with_no_default_image() 0 2 1
A it_returns_none_when_no_match() 0 2 1
B describe_path() 17 17 5
A describe_search() 0 13 3
A it_returns_the_best_matching_result() 0 4 1
A describe_validate_size() 0 15 2
A describe_keywords() 0 6 2
A is_the_set_of_all_relevant_terms() 0 4 1
A with_no_name() 0 4 1
A with_cached_valid_link() 5 5 1
A describe_validate_meta() 0 14 4
A with_nonalphanumberic_name() 0 4 1
A with_bad_link() 8 8 2
A with_various_dimenions() 0 13 1
B describe_validate() 0 16 6
A it_counts_contained_terms() 0 8 1
A it_treats_none_specially() 0 2 1
A describe_validate_link() 16 16 4
A with_one_failing_validator() 0 5 2
A is_returned_when_file_exists() 7 7 2
A describe_match() 0 9 3
A with_no_validators() 0 2 1
A describe_validate_regexes() 0 6 2
A with_all_passing_validators() 0 5 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 describe_template() 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
# pylint: disable=unused-variable,expression-not-assigned,misplaced-comparison-constant,singleton-comparison
0 ignored issues
show
introduced by
Bad option value 'misplaced-comparison-constant'
Loading history...
introduced by
Bad option value 'singleton-comparison'
Loading history...
2
3
import tempfile
4
from pathlib import Path
5
from unittest.mock import patch, Mock
6
7
import pytest
8
from expecter import expect
0 ignored issues
show
Configuration introduced by
The import expecter 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...
9
10
from memegen.domain import Template
11
12
13
def temp(path):
14
    return Path(tempfile.gettempdir(), path)
15
16
17
def describe_template():
18
19
    def it_supports_comparison():
20
        t1 = Template('abc', "A Thing")
21
        t2 = Template('def')
22
        t3 = Template('def', "Do This")
23
24
        assert t1 != t2
25
        assert t2 == t3
26
        assert t1 < t3
27
28
    def describe_get_path():
29
30
        @patch('pathlib.Path.is_file', Mock(return_value=True))
31
        def it_returns_default_when_no_style(template):
32
            expect(template.get_path()) == Path("abc/default.png")
33
34
        @patch('pathlib.Path.is_file', Mock(return_value=True))
35
        def it_returns_alternate_when_style_provided(template):
36
            expect(template.get_path('Custom')) == Path("abc/custom.png")
37
38
        @patch('pathlib.Path.is_file', Mock(return_value=True))
39
        def it_returns_default_when_style_is_none(template):
40
            expect(template.get_path(None)) == Path("abc/default.png")
41
42
        @patch('pathlib.Path.is_file', Mock(return_value=False))
43
        def it_considers_urls_valid_styles(template):
44
            url = "http://example.com"
45
            path = temp("a9b9f04336ce0181a08e774e01113b31")
46
            expect(template.get_path(url)) == path
47
48
        @patch('pathlib.Path.is_file', Mock(return_value=True))
49
        def it_caches_file_downloads(template):
50
            url = "http://this/will/be/ignored"
51
            path = temp("d888710f0697650eb68fc9dcbb976d4c")
52
            expect(template.get_path(url)) == path
53
54
        def it_handles_bad_urls(template):
55
            expect(template.get_path("http://invalid")) == None
56
57
        def it_handles_invalid_paths(template):
58
            expect(template.get_path("@#$%^")) == None
59
60 View Code Duplication
    def describe_path():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
61
62
        def is_returned_when_file_exists(template):
63
            template.root = "my_root"
64
65
            with patch('pathlib.Path.is_file', Mock(return_value=True)):
66
                path = template.path
67
68
            expect(path) == Path("my_root/abc/default.png")
69
70
        def is_none_when_no_file(template):
71
            template.root = "my_root"
72
73
            with patch('pathlib.Path.is_file', Mock(return_value=False)):
74
                path = template.path
75
76
            expect(path) == None
77
78
    def describe_default_path():
79
80
        def is_based_on_lines(template):
81
            expect(template.default_path) == "foo/bar"
82
83
        def is_underscore_when_no_lines(template):
84
            template.lines = []
85
86
            expect(template.default_path) == "_"
87
88
    def describe_styles():
89
90
        @patch('os.listdir', Mock(return_value=[]))
91
        def is_empty_when_no_alternate_images(template):
92
            expect(template.styles) == []
93
94
        @patch('os.listdir', Mock(return_value=['foo.jpg', 'bar.png']))
95
        def is_filesnames_of_alternate_images(template):
96
            expect(template.styles) == ['bar', 'foo']
97
98
    def describe_sample_path():
99
100
        def is_based_on_lines(template):
101
            expect(template.sample_path) == "foo/bar"
102
103
        def is_placeholder_when_no_lines(template):
104
            template.lines = []
105
106
            expect(template.sample_path) == "your-text/goes-here"
107
108
    def describe_keywords():
109
110
        def is_the_set_of_all_relevant_terms(template):
111
            template.lines[0] = "A day in the life"
112
113
            expect(template.keywords) == {'abc', 'day', 'the', 'bar', 'life'}
114
115
    def describe_match():
116
117
        def it_returns_none_when_no_match(template):
118
            expect(template.match("")) == (0, None)
119
120
        def it_returns_the_best_matching_result(template):
121
            template.compile_regexes([r"(\w*)/?(abc)", r"(\w*)/?(def)"])
122
123
            expect(template.match("_/def")) == (0.42, "_/def")
124
125
    def describe_search():
126
127
        def it_counts_contained_terms(template):
128
            template.key = 'Foo'
129
            template.name = "The Foobar Meme"
130
            template.aliases.append('Foo')
131
            template.aliases.append('Foobar')
132
            template.lines[0] = "This on time foobar happened"
133
134
            expect(template.search("Foo")) == 5
135
136
        def it_treats_none_specially(template):
137
            expect(template.search(None)) == -1
138
139
    def describe_validate_meta():
140
141
        def with_no_name(template):
142
            template.name = None
143
144
            expect(template.validate_meta()) == False
145
146
        def with_no_default_image(template):
147
            expect(template.validate_meta()) == False
148
149
        def with_nonalphanumberic_name(template):
150
            template.name = "'ABC' Meme"
151
152
            expect(template.validate_meta()) == False
153
154 View Code Duplication
    def describe_validate_link():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
155
156
        def with_bad_link(template):
157
            mock_response = Mock()
158
            mock_response.status_code = 404
159
160
            with patch('requests.head', Mock(return_value=mock_response)):
161
                template.link = "example.com/fake"
162
163
                expect(template.validate_link()) == False
164
165
        @patch('pathlib.Path.is_file', Mock(return_value=True))
166
        def with_cached_valid_link(template):
167
            template.link = "already_cached_site.com"
168
169
            expect(template.validate_link()) == True
170
171
    def describe_validate_size():
172
173
        @pytest.mark.parametrize('dimensions,valid', [
174
            ((Template.MIN_WIDTH, Template.MIN_HEIGHT), True),
175
            ((Template.MIN_WIDTH - 1, Template.MIN_HEIGHT), False),
176
            ((Template.MIN_WIDTH, Template.MIN_HEIGHT - 1), False),
177
            ((Template.MIN_WIDTH - 1, Template.MIN_HEIGHT - 1), False),
178
        ])
179
        @patch('PIL.Image.open')
180
        def with_various_dimenions(mock_open, template, dimensions, valid):
181
            mock_img = Mock()
182
            mock_img.size = dimensions
183
            mock_open.return_value = mock_img
184
185
            expect(template.validate_size()) == valid
186
187
    def describe_validate_regexes():
188
189
        def with_missing_split(template):
190
            template.compile_regexes([".*"])
191
192
            expect(template.validate_regexes()) == False
193
194
    def describe_validate():
195
196
        def with_no_validators(template):
197
            expect(template.validate([])) == True
198
199
        def with_all_passing_validators(template):
200
            """Verify a template is valid if all validators pass."""
201
            mock_validators = [lambda: True]
202
203
            expect(template.validate(validators=mock_validators)) == True
204
205
        def with_one_failing_validator(template):
206
            """Verify a template is invalid if any validators fail."""
207
            mock_validators = [lambda: False]
208
209
            expect(template.validate(validators=mock_validators)) == False
210