Passed
Pull Request — master (#21)
by Konstantinos
01:03
created

test_proxy.test_proxy_behaviour()   B

Complexity

Conditions 1

Size

Total Lines 71
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 45
dl 0
loc 71
rs 8.8
c 0
b 0
f 0
cc 1
nop 2

How to fix   Long Method   

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:

1
import pytest
2
3
4
@pytest.fixture
5
def dummy_handle():
6
    def handle(self, *args, **kwargs):
7
        return f'{type(self).__name__} handle request with args [{", ".join((str(_) for _ in args))}] and kwargs [{", ".join(f"{k}={v}" for k, v in kwargs.items())}]'
8
9
    return handle
10
11
12
def test_proxy_behaviour(dummy_handle, capsys):
13
    from typing import List
14
15
    from software_patterns import Proxy
16
17
    # replicate client code that wants to use the proxy pattern
18
    class ClientSubject(object):
19
        """ "A class with a request instance method."""
20
21
        def request(self, *args, **kwargs):
22
            print(dummy_handle(self, *args, **kwargs))
23
            return type(self).__name__
24
25
    # Derive from Proxy
26
    class ClientProxy(Proxy):
27
        def request(self, *args, **kwargs):
28
29
            # run proxy code before sending request to the "proxied" handler
30
            before_args = list(['before'] + list(args))
31
            print(dummy_handle(self, *before_args, **kwargs))
32
            # handle request with the proxied logic
33
            # _ = super().request(*args, **kwargs)
34
            _ = self._proxy_subject.request(*args, **kwargs)
35
            assert _ == 'ClientSubject'
36
37
            # run proxy code after request to the "proxied" handler
38
            after_args = list(['after'] + list(args))
39
            print(dummy_handle(self, *after_args, **kwargs))
40
            return _
41
42
    real_subject = ClientSubject()
43
    proxy = ClientProxy(real_subject)
44
45
    # use proxy in a scenario
46
47
    # First test what happens without using proxy
48
    args: List = [1, 2]
49
    kwargs = {'k1': 'v1'}
50
    result = real_subject.request(*args, **kwargs)
51
52
    captured = capsys.readouterr()
53
    assert captured.out == dummy_handle(real_subject, 1, 2, k1='v1') + '\n'
54
    assert (
55
        captured.out
56
        == f'ClientSubject handle request with args [{", ".join(str(_) for _ in args)}] and kwargs [{", ".join(f"{k}={v}" for k, v in kwargs.items())}]\n'
57
    )
58
    assert result == type(real_subject).__name__
59
    assert result == 'ClientSubject'
60
61
    # Now test what happens using proxy
62
    result = proxy.request(*args, **kwargs)
63
64
    captured = capsys.readouterr()
65
66
    assert (
67
        captured.out
68
        == dummy_handle(*list([proxy, 'before'] + args), **kwargs)
69
        + '\n'
70
        + dummy_handle(*list([real_subject] + args), **kwargs)
71
        + '\n'
72
        + dummy_handle(*list([proxy, 'after'] + args), **kwargs)
73
        + '\n'
74
    )
75
    assert (
76
        captured.out
77
        == f'ClientProxy handle request with args [{", ".join(str(_) for _ in ["before"] + args)}] and kwargs [{", ".join(f"{k}={v}" for k, v in kwargs.items())}]\n'
78
        + f'ClientSubject handle request with args [{", ".join(str(_) for _ in args)}] and kwargs [{", ".join(f"{k}={v}" for k, v in kwargs.items())}]\n'
79
        + f'ClientProxy handle request with args [{", ".join(str(_) for _ in ["after"] + args)}] and kwargs [{", ".join(f"{k}={v}" for k, v in kwargs.items())}]\n'
80
    )
81
    assert result == type(real_subject).__name__
82
    assert result == 'ClientSubject'
83
84
85 View Code Duplication
def test_simple_proxy():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
86
    from typing import Callable
87
88
    from software_patterns import Proxy
89
90
    RemoteCall = Callable[[int], int]
91
    remote_call: RemoteCall = lambda x: x + 1
92
93
    # Code that the developer writes
94
    VALUE = 10
95
96
    class ClientProxy(Proxy[RemoteCall]):
97
        def __call__(self, x: int):
98
            return self._proxy_subject(x + VALUE)
99
100
    proxy: ClientProxy = ClientProxy(remote_call)
101
102
    assert remote_call(2) == 2 + 1
103
    assert proxy(2) == 2 + VALUE + 1
104
105
106 View Code Duplication
def test_proxy_as_instance():
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
107
    from typing import Callable
108
109
    from software_patterns import Proxy
110
111
    RemoteCall = Callable[[int], int]
112
113
    remote_call: RemoteCall = lambda x: x + 1
114
115
    # Code that the developer writes
116
    VALUE = 10
117
118
    class ClientProxy(Proxy[RemoteCall]):
119
        def __call__(self, x: int):
120
            return self._proxy_subject(x + VALUE)
121
122
    proxy: ClientProxy = ClientProxy(remote_call)
123
124
    assert remote_call(2) == 2 + 1
125
    assert proxy(2) == 2 + VALUE + 1
126
127
    assert hash(proxy) == hash(remote_call)
128
129
130
def test_mapping_proxy():
131
    from typing import Mapping
132
133
    from software_patterns import Proxy
134
135
    # test data
136
    RemoteMapping = Mapping[str, str]
137
138
    remote_mapping: RemoteMapping = {
139
        'id_1': 'a',
140
        'id_2': 'b',
141
    }
142
143
    ## Code that the developer writes
144
145
    class ClientProxy(Proxy[Mapping]):
146
        CACHE = {
147
            'id_1': 'a-cached',
148
        }
149
150
        def __getitem__(self, str_id: str):
151
            return self.CACHE.get(str_id, self._proxy_subject[str_id])
152
153
        def __contains__(self, element):
154
            return element in self._proxy_subject
155
156
        def wipe_cache(self):
157
            self.CACHE = {}
158
159
    proxy: ClientProxy = ClientProxy(remote_mapping)
160
161
    # Test code
162
    assert remote_mapping['id_1'] == 'a'
163
    assert remote_mapping['id_2'] == 'b'
164
    assert 'id_1' in remote_mapping
165
166
    assert proxy['id_1'] == 'a-cached'
167
    assert proxy['id_2'] == 'b'
168
    assert 'id_1' in proxy
169
170
    # Proxy delegates attribute requests (ie 'keys' as below) to subject
171
    assert sorted(remote_mapping.keys()) == sorted(proxy.keys())
172
    assert str(proxy) == str(remote_mapping)
173
174
    proxy.wipe_cache()
175
176
    assert proxy['id_1'] == 'a'
177
    assert proxy['id_2'] == 'b'
178
    assert sorted(remote_mapping.keys()) == sorted(proxy.keys())
179
    assert str(proxy) == str(remote_mapping)
180