Completed
Push — master ( 178087...13f71d )
by Konstantinos
25s queued 12s
created

software_patterns.proxy.ProxySubject.__init__()   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
cc 1
nop 2
1
"""Proxy structural software pattern.
2
3
This module contains boiler-plate code to supply the Proxy structural software
4
design pattern, to the client code."""
5
6
from abc import ABC, abstractmethod
7
from typing import TypeVar, Generic, Callable
8
9
T = TypeVar('T')
10
11
12
__all__ = ['ProxySubject', 'Proxy']
13
14
15
class ProxySubjectInterface(ABC, Generic[T]):
16
    """Proxy Subject interface holding the important 'request' operation.
17
18
    Declares common operations for both ProxySubject and
19
    the Proxy. As long as the client uses ProxySubject's interface, a proxy can
20
    be passed pass to it, instead of a real subject.
21
    """
22
    @abstractmethod
23
    def request(self, *args, **kwargs) -> T:
24
        raise NotImplementedError
25
26
27
class ProxySubject(ProxySubjectInterface, Generic[T]):
28
    """
29
    The ProxySubject contains some core business logic. Usually, ProxySubject are
30
    capable of doing some useful work which may also be very slow or sensitive -
31
    e.g. correcting input data. A Proxy can solve these issues without any
32
    changes to the ProxySubject's code.
33
34
    Example:
35
36
        >>> from software_patterns import ProxySubject
37
        >>> proxied_operation = lambda x: x + 1
38
        >>> proxied_operation(1)
39
        2
40
41
        >>> proxied_object = ProxySubject(proxied_operation)
42
        >>> proxied_object.request(1)
43
        2
44
    """
45
    def __init__(self, callback: Callable[..., T]):
46
        self._callback = callback
47
48
    def request(self, *args, **kwargs) -> T:
49
        return self._callback(*args, **kwargs)
50
51
52
class Proxy(ProxySubjectInterface, Generic[T]):
53
    """
54
    The Proxy has an interface identical to the ProxySubject.
55
56
    Example:
57
58
        >>> from software_patterns import Proxy
59
        >>> from software_patterns import ProxySubject
60
61
        >>> class ClientProxy(Proxy):
62
        ...  def request(self, *args, **kwargs):
63
        ...   args = [args[0] + 1]
64
        ...   result = super().request(*args, **kwargs)
65
        ...   result += 1
66
        ...   return result
67
68
        >>> proxied_operation = lambda x: x * 2
69
        >>> proxy_subject = ProxySubject(proxied_operation)
70
        >>> proxy_subject.request(3)
71
        6
72
73
        >>> proxy = ClientProxy(proxy_subject)
74
        >>> proxy.request(3)
75
        9
76
    """
77
    def __init__(self, proxy_subject: ProxySubject):
78
        self._proxy_subject = proxy_subject
79
80
    def request(self, *args, **kwargs) -> T:
81
        """
82
        The most common applications of the Proxy pattern are lazy loading,
83
        caching, controlling the access, logging, etc. A Proxy can perform one
84
        of these things and then, depending on the result, pass the execution to
85
        the same method in a linked ProxySubject object.
86
        """
87
        return self._proxy_subject.request(*args, **kwargs)
88