Passed
Push — master ( bff183...bdc66f )
by dgw
02:14 queued 12s
created

test_fileattribute_given_relative_when_absolute()   A

Complexity

Conditions 2

Size

Total Lines 3
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 2
nop 1
1
# coding=utf-8
2
from __future__ import unicode_literals, division, print_function, absolute_import
3
4
import os
5
6
import pytest
7
8
from sopel import config
9
from sopel.config import types
10
11
12
FAKE_CONFIG = """
13
[core]
14
owner=dgw
15
homedir={homedir}
16
"""
17
18
19
MULTILINE_CONFIG = FAKE_CONFIG + """
20
[spam]
21
eggs = one, two, three, four, and a half
22
bacons = grilled
23
    burn out, 
24
    , greasy, fat, and tasty
25
cheeses =   
26
    cheddar
27
      reblochon   
28
  camembert
29
"""  # noqa (trailing whitespaces are intended)
30
31
32
class FakeConfigSection(types.StaticSection):
33
    valattr = types.ValidatedAttribute('valattr')
34
    listattr = types.ListAttribute('listattr')
35
    choiceattr = types.ChoiceAttribute('choiceattr', ['spam', 'egg', 'bacon'])
36
    af_fileattr = types.FilenameAttribute('af_fileattr', relative=False, directory=False)
37
    ad_fileattr = types.FilenameAttribute('ad_fileattr', relative=False, directory=True)
38
    rf_fileattr = types.FilenameAttribute('rf_fileattr', relative=True, directory=False)
39
    rd_fileattr = types.FilenameAttribute('rd_fileattr', relative=True, directory=True)
40
41
42
class SpamSection(types.StaticSection):
43
    eggs = types.ListAttribute('eggs')
44
    bacons = types.ListAttribute('bacons', strip=False)
45
    cheeses = types.ListAttribute('cheeses')
46
47
48
@pytest.fixture
49
def tmphomedir(tmpdir):
50
    sopel_homedir = tmpdir.join('.sopel')
51
    sopel_homedir.mkdir()
52
    sopel_homedir.join('test.tmp').write('')
53
    sopel_homedir.join('test.d').mkdir()
54
    return sopel_homedir
55
56
57
@pytest.fixture
58
def fakeconfig(tmphomedir):
59
    conf_file = tmphomedir.join('conf.cfg')
60
    conf_file.write(FAKE_CONFIG.format(homedir=tmphomedir.strpath))
61
62
    test_settings = config.Config(conf_file.strpath)
63
    test_settings.define_section('fake', FakeConfigSection)
64
    return test_settings
65
66
67
@pytest.fixture
68
def multi_fakeconfig(tmphomedir):
69
    conf_file = tmphomedir.join('conf.cfg')
70
    conf_file.write(MULTILINE_CONFIG.format(homedir=tmphomedir.strpath))
71
72
    test_settings = config.Config(conf_file.strpath)
73
    test_settings.define_section('fake', FakeConfigSection)
74
    test_settings.define_section('spam', SpamSection)
75
    return test_settings
76
77
78
def test_validated_string_when_none(fakeconfig):
79
    fakeconfig.fake.valattr = None
80
    assert fakeconfig.fake.valattr is None
81
82
83
def test_listattribute_when_empty(fakeconfig):
84
    fakeconfig.fake.listattr = []
85
    assert fakeconfig.fake.listattr == []
86
87
88
def test_listattribute_with_one_value(fakeconfig):
89
    fakeconfig.fake.listattr = ['foo']
90
    assert fakeconfig.fake.listattr == ['foo']
91
92
93
def test_listattribute_with_multiple_values(fakeconfig):
94
    fakeconfig.fake.listattr = ['egg', 'sausage', 'bacon']
95
    assert fakeconfig.fake.listattr == ['egg', 'sausage', 'bacon']
96
97
98
def test_listattribute_with_value_containing_comma(fakeconfig):
99
    fakeconfig.fake.listattr = ['spam, egg, sausage', 'bacon']
100
    assert fakeconfig.fake.listattr == ['spam, egg, sausage', 'bacon']
101
102
103
def test_listattribute_with_value_containing_nonescape_backslash(fakeconfig):
104
    fakeconfig.fake.listattr = ['spam', r'egg\sausage', 'bacon']
105
    assert fakeconfig.fake.listattr == ['spam', r'egg\sausage', 'bacon']
106
107
    fakeconfig.fake.listattr = ['spam', r'egg\tacos', 'bacon']
108
    assert fakeconfig.fake.listattr == ['spam', r'egg\tacos', 'bacon']
109
110
111
def test_listattribute_with_value_containing_standard_escape_sequence(fakeconfig):
112
    fakeconfig.fake.listattr = ['spam', 'egg\tsausage', 'bacon']
113
    assert fakeconfig.fake.listattr == ['spam', 'egg\tsausage', 'bacon']
114
115
    fakeconfig.fake.listattr = ['spam', 'egg\nsausage', 'bacon']
116
    assert fakeconfig.fake.listattr == [
117
        'spam', 'egg', 'sausage', 'bacon'
118
    ], 'Line break are always converted to new item'
119
120
    fakeconfig.fake.listattr = ['spam', 'egg\\sausage', 'bacon']
121
    assert fakeconfig.fake.listattr == ['spam', 'egg\\sausage', 'bacon']
122
123
124
def test_listattribute_with_value_ending_in_special_chars(fakeconfig):
125
    fakeconfig.fake.listattr = ['spam', 'egg', 'sausage\\', 'bacon']
126
    assert fakeconfig.fake.listattr == ['spam', 'egg', 'sausage\\', 'bacon']
127
128
    fakeconfig.fake.listattr = ['spam', 'egg', 'sausage,', 'bacon']
129
    assert fakeconfig.fake.listattr == ['spam', 'egg', 'sausage', 'bacon']
130
131
    fakeconfig.fake.listattr = ['spam', 'egg', 'sausage,,', 'bacon']
132
    assert fakeconfig.fake.listattr == ['spam', 'egg', 'sausage', 'bacon']
133
134
135
def test_listattribute_with_value_containing_adjacent_special_chars(fakeconfig):
136
    fakeconfig.fake.listattr = ['spam', r'egg\,sausage', 'bacon']
137
    assert fakeconfig.fake.listattr == ['spam', r'egg\,sausage', 'bacon']
138
139
    fakeconfig.fake.listattr = ['spam', r'egg\,\sausage', 'bacon']
140
    assert fakeconfig.fake.listattr == ['spam', r'egg\,\sausage', 'bacon']
141
142
    fakeconfig.fake.listattr = ['spam', r'egg,\,sausage', 'bacon']
143
    assert fakeconfig.fake.listattr == ['spam', r'egg,\,sausage', 'bacon']
144
145
    fakeconfig.fake.listattr = ['spam', 'egg,,sausage', 'bacon']
146
    assert fakeconfig.fake.listattr == ['spam', 'egg,,sausage', 'bacon']
147
148
    fakeconfig.fake.listattr = ['spam', r'egg\\sausage', 'bacon']
149
    assert fakeconfig.fake.listattr == ['spam', r'egg\\sausage', 'bacon']
150
151
152
def test_choiceattribute_when_none(fakeconfig):
153
    fakeconfig.fake.choiceattr = None
154
    assert fakeconfig.fake.choiceattr is None
155
156
157
def test_choiceattribute_when_not_in_set(fakeconfig):
158
    with pytest.raises(ValueError):
159
        fakeconfig.fake.choiceattr = 'sausage'
160
161
162
def test_choiceattribute_when_valid(fakeconfig):
163
    fakeconfig.fake.choiceattr = 'bacon'
164
    assert fakeconfig.fake.choiceattr == 'bacon'
165
166
167
def test_fileattribute_valid_absolute_file_path(fakeconfig):
168
    testfile = os.path.join(fakeconfig.core.homedir, 'test.tmp')
169
    fakeconfig.fake.af_fileattr = testfile
170
    assert fakeconfig.fake.af_fileattr == testfile
171
172
173
def test_fileattribute_valid_absolute_dir_path(fakeconfig):
174
    testdir = os.path.join(fakeconfig.core.homedir, 'test.d')
175
    fakeconfig.fake.ad_fileattr = testdir
176
    assert fakeconfig.fake.ad_fileattr == testdir
177
178
179
def test_fileattribute_given_relative_when_absolute(fakeconfig):
180
    with pytest.raises(ValueError):
181
        fakeconfig.fake.af_fileattr = '../testconfig.tmp'
182
183
184
def test_fileattribute_given_absolute_when_relative(fakeconfig):
185
    testfile = os.path.join(fakeconfig.core.homedir, 'test.tmp')
186
    fakeconfig.fake.rf_fileattr = testfile
187
    assert fakeconfig.fake.rf_fileattr == testfile
188
189
190
def test_fileattribute_given_dir_when_file(fakeconfig):
191
    testdir = os.path.join(fakeconfig.core.homedir, 'test.d')
192
    with pytest.raises(ValueError):
193
        fakeconfig.fake.af_fileattr = testdir
194
195
196
def test_fileattribute_given_file_when_dir(fakeconfig):
197
    testfile = os.path.join(fakeconfig.core.homedir, 'test.tmp')
198
    with pytest.raises(ValueError):
199
        fakeconfig.fake.ad_fileattr = testfile
200
201
202
def test_configparser_multi_lines(multi_fakeconfig):
203
    # spam
204
    assert multi_fakeconfig.spam.eggs == [
205
        'one',
206
        'two',
207
        'three',
208
        'four',
209
        'and a half',  # no-newline + comma
210
    ], 'Comma separated line: "four" and "and a half" must be separated'
211
    assert multi_fakeconfig.spam.bacons == [
212
        'grilled',
213
        'burn out',
214
        'greasy, fat, and tasty',
215
    ]
216
    assert multi_fakeconfig.spam.cheeses == [
217
        'cheddar',
218
        'reblochon',
219
        'camembert',
220
    ]
221
222
223
def test_save_unmodified_config(multi_fakeconfig):
224
    """Assert type attributes are kept as they should be"""
225
    multi_fakeconfig.save()
226
    saved_config = config.Config(multi_fakeconfig.filename)
227
    saved_config.define_section('fake', FakeConfigSection)
228
    saved_config.define_section('spam', SpamSection)
229
230
    # core
231
    assert saved_config.core.owner == 'dgw'
232
233
    # fake
234
    assert saved_config.fake.valattr is None
235
    assert saved_config.fake.listattr == []
236
    assert saved_config.fake.choiceattr is None
237
    assert saved_config.fake.af_fileattr is None
238
    assert saved_config.fake.ad_fileattr is None
239
    assert saved_config.fake.rf_fileattr is None
240
    assert saved_config.fake.rd_fileattr is None
241
242
    # spam
243
    assert saved_config.spam.eggs == [
244
        'one',
245
        'two',
246
        'three',
247
        'four',
248
        'and a half',  # no-newline + comma
249
    ], 'Comma separated line: "four" and "and a half" must be separated'
250
    assert saved_config.spam.bacons == [
251
        'grilled',
252
        'burn out',
253
        'greasy, fat, and tasty',
254
    ]
255
    assert saved_config.spam.cheeses == [
256
        'cheddar',
257
        'reblochon',
258
        'camembert',
259
    ]
260
261
262
def test_save_modified_config(multi_fakeconfig):
263
    """Assert modified values are restored properly"""
264
    multi_fakeconfig.fake.choiceattr = 'spam'
265
    multi_fakeconfig.spam.eggs = [
266
        'one',
267
        'two',
268
    ]
269
    multi_fakeconfig.spam.cheeses = [
270
        'camembert, reblochon, and cheddar',
271
    ]
272
273
    multi_fakeconfig.save()
274
275
    with open(multi_fakeconfig.filename) as fd:
276
        print(fd.read())  # used for debug purpose if an assert fails
277
278
    saved_config = config.Config(multi_fakeconfig.filename)
279
    saved_config.define_section('fake', FakeConfigSection)
280
    saved_config.define_section('spam', SpamSection)
281
282
    assert saved_config.fake.choiceattr == 'spam'
283
    assert saved_config.spam.eggs == ['one', 'two']
284
    assert saved_config.spam.cheeses == [
285
        'camembert, reblochon, and cheddar',
286
    ], (
287
        'ListAttribute with one line only, with commas, must *not* be split '
288
        'differently from what was expected, i.e. into one (and only one) value'
289
    )
290