-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathvalidate_properties_test.py
181 lines (138 loc) · 5.15 KB
/
validate_properties_test.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# Copyright (c) 2012 Lars Hupfeldt Nielsen, Hupfeldt IT
# All rights reserved. This work is under a BSD license, see LICENSE.TXT.
from pytest import raises
from multiconf import mc_config, ConfigItem, RepeatableConfigItem, InvalidUsageException, ConfigException
from multiconf.decorators import nested_repeatables, named_as
from multiconf.envs import EnvFactory
from .utils.utils import next_line_num, replace_multiconf_file_line_msg, config_error, file_line, lines_in
from .utils.utils import local_func, minor_version
from .utils.tstclasses import ItemWithAA
ef = EnvFactory()
pp = ef.Env('pp')
prod = ef.Env('prod')
g_p = ef.EnvGroup('g_p', pp, prod)
ef2_prod = EnvFactory()
prod2 = ef2_prod.Env('prod')
def ce(line_num, *lines):
return config_error(__file__, line_num, *lines)
def test_validate_properties_property_method():
@named_as('someitem')
class Nested(ConfigItem):
@property
def m(self):
return 1
@mc_config(ef, load_now=True)
def config(rt):
with ItemWithAA(aa=0):
Nested()
cr = config(prod)
assert cr.num_invalid_property_usage == 0
def test_validate_properties_property_attribute_method_override():
@named_as('someitem')
class Nested(ConfigItem):
@property
def m(self):
return 1
@mc_config(ef, load_now=True)
def config(rt):
with ItemWithAA(aa=0):
with Nested() as nn:
nn.setattr("m", mc_overwrite_property=True, default=7)
cr = config(prod).ItemWithAA
assert cr.someitem.m == 7
assert cr.num_invalid_property_usage == 0
def test_validate_properties_property_method_raises_InvalidUsageException():
@named_as('someitem')
class Nested(ConfigItem):
@property
def m(self):
raise InvalidUsageException("No m now")
@mc_config(ef, load_now=True)
def config(rt):
with ItemWithAA(aa=0):
Nested()
cr = config(prod)
assert cr.num_invalid_property_usage == 2
_validate_properties_property_method_raises_exception_expected_stderr = """
ConfigError: Exception validating @property 'm' on item <class 'test.validate_properties_test.%(local_func)sNested'> in Env('pp').
Traceback (most recent call last):
File "fake_multiconf_dir/multiconf.py", line 999, in _mc_validate_properties
val = getattr(self, key)%(carets)s
%(file_line)s, in m
raise Exception("Something is wrong")
Exception: Something is wrong
""".lstrip()
def test_validate_properties_property_method_raises_exception(capsys):
errorline = [None]
@named_as('someitem')
class Nested(ConfigItem):
@property
def m(self):
errorline[0] = next_line_num()
raise Exception("Something is wrong")
with raises(ConfigException) as exinfo:
@mc_config(ef, load_now=True)
def config(rt):
with ItemWithAA() as it:
it.setattr('aa', default=1, prod=0)
Nested()
_sout, serr = capsys.readouterr()
assert replace_multiconf_file_line_msg(serr) == _validate_properties_property_method_raises_exception_expected_stderr % {
"local_func": local_func(),
"carets": "\n ^^^^^^^^^^^^^^^^^^" if minor_version > 10 else "",
"file_line": file_line(__file__, errorline[0])
}
assert str(exinfo.value) == "Error validating @property methods for Env('pp')"
def test_validate_properties_property_method_on_repeatable_raises_exception(capsys):
errorline = [None]
@named_as('someitems')
class RNested(RepeatableConfigItem):
@property
def m(self):
errorline[0] = next_line_num()
raise Exception("Something is wrong")
@nested_repeatables('someitems')
class ItemWithAAAndSomeItems(ItemWithAA):
pass
with raises(ConfigException) as exinfo:
@mc_config(ef, load_now=True)
def config(rt):
with ItemWithAAAndSomeItems() as it:
it.setattr('aa', default=1, prod=0)
RNested('a')
RNested('b')
_sout, serr = capsys.readouterr()
assert lines_in(
serr,
# Once for each repeated item
'Exception: Something is wrong',
'Exception: Something is wrong',
)
assert str(exinfo.value) == "Error validating @property methods for Env('pp')"
def test_validate_properties_dir_error(capsys):
"""multiconf does not depend on dir(obj), but only on dir(cls)"""
errorline = [None]
@named_as('someitem')
class Nested(ItemWithAA):
def __dir__(self):
errorline[0] = next_line_num()
raise Exception('Error in dir()')
@property
def c(self):
return "show-me"
@mc_config(ef, load_now=True)
def config(rt):
with ItemWithAA(aa=0):
with Nested() as nn:
nn.aa = 2
nn = config(pp).ItemWithAA.someitem
assert nn.c == "show-me"
def test_mc_validate_has_method():
class item(ConfigItem):
def hello(self):
raise Exception("Error in hello")
def hi(self, there):
raise Exception("Error in hello " + there)
@mc_config(ef, load_now=True)
def config(_):
item()