Issues (2)

tests/test_proxy.py (2 issues)

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
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
    def remote_call(x):
92
        return x + 1
93
94
    # Code that the developer writes
95
    VALUE = 10
96
97
    class ClientProxy(Proxy[RemoteCall]):
98
        def __call__(self, x: int):
99
            return self._proxy_subject(x + VALUE)
100
101
    proxy: ClientProxy = ClientProxy(remote_call)
102
103
    assert remote_call(2) == 2 + 1
104
    assert proxy(2) == 2 + VALUE + 1
105
106
107 View Code Duplication
def test_proxy_as_instance():
0 ignored issues
show
This code seems to be duplicated in your project.
Loading history...
108
    from typing import Callable
109
110
    from software_patterns import Proxy
111
112
    RemoteCall = Callable[[int], int]
113
114
    def remote_call(x):
115
        return x + 1
116
117
    # Code that the developer writes
118
    VALUE = 10
119
120
    class ClientProxy(Proxy[RemoteCall]):
121
        def __call__(self, x: int):
122
            return self._proxy_subject(x + VALUE)
123
124
    proxy: ClientProxy = ClientProxy(remote_call)
125
126
    assert remote_call(2) == 2 + 1
127
    assert proxy(2) == 2 + VALUE + 1
128
129
    assert hash(proxy) == hash(remote_call)
130
131
132
def test_mapping_proxy():
133
    from typing import Mapping
134
135
    from software_patterns import Proxy
136
137
    # test data
138
    RemoteMapping = Mapping[str, str]
139
140
    remote_mapping: RemoteMapping = {
141
        'id_1': 'a',
142
        'id_2': 'b',
143
    }
144
145
    ## Code that the developer writes
146
147
    class ClientProxy(Proxy[Mapping]):
148
        CACHE = {
149
            'id_1': 'a-cached',
150
        }
151
152
        def __getitem__(self, str_id: str):
153
            return self.CACHE.get(str_id, self._proxy_subject[str_id])
154
155
        def __contains__(self, element):
156
            return element in self._proxy_subject
157
158
        def wipe_cache(self):
159
            self.CACHE = {}
160
161
    proxy: ClientProxy = ClientProxy(remote_mapping)
162
163
    # Test code
164
    assert remote_mapping['id_1'] == 'a'
165
    assert remote_mapping['id_2'] == 'b'
166
    assert 'id_1' in remote_mapping
167
168
    assert proxy['id_1'] == 'a-cached'
169
    assert proxy['id_2'] == 'b'
170
    assert 'id_1' in proxy
171
172
    # Proxy delegates attribute requests (ie 'keys' as below) to subject
173
    assert sorted(remote_mapping.keys()) == sorted(proxy.keys())
174
    assert str(proxy) == str(remote_mapping)
175
176
    proxy.wipe_cache()
177
178
    assert proxy['id_1'] == 'a'
179
    assert proxy['id_2'] == 'b'
180
    assert sorted(remote_mapping.keys()) == sorted(proxy.keys())
181
    assert str(proxy) == str(remote_mapping)
182