Completed
Push — develop ( 0ce159...3bb0e5 )
by Jace
02:41
created

FindMixin   A

Complexity

Total Complexity 3

Size/Duplication

Total Lines 7
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 3
c 2
b 0
f 0
dl 0
loc 7
rs 10

1 Method

Rating   Name   Duplication   Size   Complexity  
A find() 0 5 3
1
# pylint: disable=missing-docstring,no-self-use,no-member,misplaced-comparison-constant,expression-not-assigned
0 ignored issues
show
introduced by
Bad option value 'misplaced-comparison-constant'
Loading history...
2
3
import logging
4
from unittest.mock import patch, Mock
5
6
import pytest
7
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...
8
9
import yorm
10
from yorm import common
11
from yorm.decorators import attr
12
from yorm.types import Dictionary, List
13
from yorm.types import String, Integer
14
15
from . import strip
16
17
log = logging.getLogger(__name__)
18
19
20
# CLASSES ######################################################################
21
22
23
@attr(abc=Integer)
24
class SampleDictionary(Dictionary):
25
    """Sample dictionary container."""
26
27
28
@attr(var1=Integer)
29
@attr(var2=String)
30
class SampleDictionaryWithInitialization(Dictionary):
31
    """Sample dictionary container with initialization."""
32
33
    def __init__(self, var1, var2, var3):
34
        super().__init__()
35
        self.var1 = var1
36
        self.var2 = var2
37
        self.var3 = var3
38
39
40
@attr(all=String)
41
class StringList(List):
42
    """Sample list container."""
43
44
45
class UnknownList(List):
46
    """Sample list container."""
47
48
49
# TESTS ########################################################################
50
51
52
class TestDictionary:
53
    """Unit tests for the `Dictionary` container."""
54
55
    obj = {'abc': 123}
56
57
    class SampleClass:
58
59
        def __init__(self):
60
            self.abc = 42
61
62
    class SampleClass2:
63
64
        def __init__(self):
65
            self.unmapped = Mock()
66
67
    data_value = [
68
        (obj, obj),
69
        (None, {'abc': 0}),
70
        ("key=value", {'key': "value", 'abc': 0}),
71
        ("key=", {'key': "", 'abc': 0}),
72
        ("key", {'key': None, 'abc': 0}),
73
    ]
74
75
    value_data = [
76
        (obj, obj),
77
        (SampleClass(), {'abc': 42}),
78
        (SampleClass2(), {'abc': 0}),
79
        ([], {'abc': 0}),
80
    ]
81
82
    def setup_method(self, _):
83
        """Reset the class' mapped attributes before each test."""
84
        common.attrs[SampleDictionary] = {'abc': Integer}
85
86
    @pytest.mark.parametrize("data,value", data_value)
87
    def test_to_value(self, data, value):
88
        """Verify input data is converted to values."""
89
        assert value == SampleDictionary.to_value(data)
90
91
    @pytest.mark.parametrize("value,data", value_data)
92
    def test_to_data(self, value, data):
93
        """Verify values are converted to output data."""
94
        assert data == SampleDictionary.to_data(value)
95
96
    def test_not_implemented(self):
97
        """Verify `Dictionary` cannot be used directly."""
98
        with pytest.raises(NotImplementedError):
99
            Dictionary()
100
101
    def test_dict_as_object(self):
102
        """Verify a `Dictionary` can be used as an attribute."""
103
        dictionary = SampleDictionaryWithInitialization(1, 2, 3.0)
104
        value = {'var1': 1, 'var2': '2'}
105
        value2 = dictionary.to_value(dictionary)
106
        assert value == value2
107
        # keys are not accessible as attributes
108
        assert not hasattr(value2, 'var1')
109
        assert not hasattr(value2, 'var2')
110
        assert not hasattr(value2, 'var3')
111
112
    def test_unknown_attrributes_are_ignored(self):
113
        obj = SampleDictionary.create_default()
114
        obj.update_value({'key': "value", 'abc': 7}, auto_track=False)
115
        assert {'abc': 7} == obj
116
117
118
class TestList:
119
    """Unit tests for the `List` container."""
120
121
    obj = ["a", "b", "c"]
122
123
    data_value = [
124
        (obj, obj),
125
        (None, []),
126
        ("a b c", ["a", "b", "c"]),
127
        ("a,b,c", ["a", "b", "c"]),
128
        ("abc", ["abc"]),
129
        ("a\nb\nc", ["a", "b", "c"]),
130
        (4.2, ['4.2']),
131
    ]
132
133
    value_data = [
134
        (obj, obj),
135
    ]
136
137
    @pytest.mark.parametrize("data,value", data_value)
138
    def test_to_value(self, data, value):
139
        """Verify input data is converted to values."""
140
        assert value == StringList.to_value(data)
141
142
    @pytest.mark.parametrize("value,data", value_data)
143
    def test_to_data(self, value, data):
144
        """Verify values are converted to output data."""
145
        assert data == StringList.to_data(value)
146
147
    def test_item_type(self):
148
        """Verify list item type can be determined."""
149
        assert String == StringList.item_type
150
151
    def test_item_type_none(self):
152
        """Verify list item type defaults to None."""
153
        assert None is UnknownList.item_type
154
155
    def test_not_implemented(self):
156
        """Verify `List` cannot be used directly."""
157
        with pytest.raises(NotImplementedError):
158
            List()
159
        with pytest.raises(NotImplementedError):
160
            UnknownList()
161
162
    def test_shortened_syntax(self):
163
        cls = List.of_type(Integer)
164
        expect(cls.__name__) == "IntegerList"
165
        expect(common.attrs[cls]) == {'all': Integer}
166
167
168
class TestExtensions:
169
    """Unit tests for extensions to the container classes."""
170
171
    class FindMixin:
172
173
        def find(self, value):
174
            for value2 in self:
175
                if value.lower() == value2.lower():
176
                    return value2
177
            return None
178
179
    @yorm.attr(a=yorm.types.String)
180
    class MyDictionary(Dictionary, FindMixin):
181
        pass
182
183
    @yorm.attr(all=yorm.types.String)
184
    class MyList(List, FindMixin):
185
        pass
186
187
    def test_converted_dict_keeps_type(self):
188
        my_dict = self.MyDictionary()
189
        my_dict['a'] = 1
190
        my_dict2 = self.MyDictionary.to_value(my_dict)
191
        assert 'a' == my_dict2.find('A')
192
        assert None is my_dict2.find('B')
193
194
    def test_converted_list_keeps_type(self):
195
        my_list = self.MyList()
196
        my_list.append('a')
197
        my_list2 = self.MyList.to_value(my_list)
198
        assert 'a' == my_list2.find('A')
199
        assert None is my_list2.find('B')
200
201
202
@patch('yorm.settings.fake', True)
203
class TestReservedNames:
204
205
    class MyObject:
206
207
        def __init__(self, items=None):
208
            self.items = items or []
209
210
        def __repr__(self):
211
            return "<my_object>"
212
213
    def test_list_named_items(self):
214
        my_object = self.MyObject()
215
        yorm.sync_object(my_object, "fake/path", {'items': StringList})
216
217
        log.info("Appending value to list of items...")
218
        my_object.items.append('foo')
219
220
        log.info("Checking object contents...")
221
        assert strip("""
222
        items:
223
        - foo
224
        """) == my_object.__mapper__.text
225
226
        log.info("Writting new file contents...")
227
        my_object.__mapper__.text = strip("""
228
        items:
229
        - bar
230
        """)
231
232
        log.info("Checking file contents...")
233
        assert ['bar'] == my_object.items
234