Skip to content

Commit 90016f4

Browse files
debakarrRoy, Debakarfaif
authored
Add type hint to remaining pattern modules (#410)
* Adding typehint * Update __exit__ type * fix black formatting --------- Co-authored-by: Roy, Debakar <[email protected]> Co-authored-by: Sakis Kasampalis <[email protected]>
1 parent 11132fc commit 90016f4

File tree

12 files changed

+90
-59
lines changed

12 files changed

+90
-59
lines changed

patterns/behavioral/catalog.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ class Catalog:
1212
"""
1313

1414
def __init__(self, param: str) -> None:
15-
1615
# dictionary that will be used to determine which static method is
1716
# to be executed but that will be also used to store possible param
1817
# value

patterns/behavioral/memento.py

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99
from typing import Callable, List
1010

1111

12-
def memento(obj, deep=False):
12+
def memento(obj: Any, deep: bool = False) -> Callable:
1313
state = deepcopy(obj.__dict__) if deep else copy(obj.__dict__)
1414

15-
def restore():
15+
def restore() -> None:
1616
obj.__dict__.clear()
1717
obj.__dict__.update(state)
1818

@@ -28,15 +28,15 @@ class Transaction:
2828
deep = False
2929
states: List[Callable[[], None]] = []
3030

31-
def __init__(self, deep, *targets):
31+
def __init__(self, deep: bool, *targets: Any) -> None:
3232
self.deep = deep
3333
self.targets = targets
3434
self.commit()
3535

36-
def commit(self):
36+
def commit(self) -> None:
3737
self.states = [memento(target, self.deep) for target in self.targets]
3838

39-
def rollback(self):
39+
def rollback(self) -> None:
4040
for a_state in self.states:
4141
a_state()
4242

@@ -48,29 +48,39 @@ def Transactional(method):
4848
:param method: The function to be decorated.
4949
"""
5050

51-
def transaction(obj, *args, **kwargs):
52-
state = memento(obj)
53-
try:
54-
return method(obj, *args, **kwargs)
55-
except Exception as e:
56-
state()
57-
raise e
51+
def __init__(self, method: Callable) -> None:
52+
self.method = method
53+
54+
def __get__(self, obj: Any, T: Type) -> Callable:
55+
"""
56+
A decorator that makes a function transactional.
57+
58+
:param method: The function to be decorated.
59+
"""
60+
61+
def transaction(*args, **kwargs):
62+
state = memento(obj)
63+
try:
64+
return self.method(obj, *args, **kwargs)
65+
except Exception as e:
66+
state()
67+
raise e
5868

5969
return transaction
6070

6171

6272
class NumObj:
63-
def __init__(self, value):
73+
def __init__(self, value: int) -> None:
6474
self.value = value
6575

66-
def __repr__(self):
76+
def __repr__(self) -> str:
6777
return f"<{self.__class__.__name__}: {self.value!r}>"
6878

69-
def increment(self):
79+
def increment(self) -> None:
7080
self.value += 1
7181

7282
@Transactional
73-
def do_stuff(self):
83+
def do_stuff(self) -> None:
7484
self.value = "1111" # <- invalid value
7585
self.increment() # <- will fail and rollback
7686

patterns/behavioral/registry.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33

44
class RegistryHolder(type):
5-
65
REGISTRY: Dict[str, "RegistryHolder"] = {}
76

87
def __new__(cls, name, bases, attrs):

patterns/behavioral/specification.py

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"""
77

88
from abc import abstractmethod
9+
from typing import Union
910

1011

1112
class Specification:
@@ -28,60 +29,60 @@ class CompositeSpecification(Specification):
2829
def is_satisfied_by(self, candidate):
2930
pass
3031

31-
def and_specification(self, candidate):
32+
def and_specification(self, candidate: "Specification") -> "AndSpecification":
3233
return AndSpecification(self, candidate)
3334

34-
def or_specification(self, candidate):
35+
def or_specification(self, candidate: "Specification") -> "OrSpecification":
3536
return OrSpecification(self, candidate)
3637

37-
def not_specification(self):
38+
def not_specification(self) -> "NotSpecification":
3839
return NotSpecification(self)
3940

4041

4142
class AndSpecification(CompositeSpecification):
42-
def __init__(self, one, other):
43+
def __init__(self, one: "Specification", other: "Specification") -> None:
4344
self._one: Specification = one
4445
self._other: Specification = other
4546

46-
def is_satisfied_by(self, candidate):
47+
def is_satisfied_by(self, candidate: Union["User", str]) -> bool:
4748
return bool(
4849
self._one.is_satisfied_by(candidate)
4950
and self._other.is_satisfied_by(candidate)
5051
)
5152

5253

5354
class OrSpecification(CompositeSpecification):
54-
def __init__(self, one, other):
55+
def __init__(self, one: "Specification", other: "Specification") -> None:
5556
self._one: Specification = one
5657
self._other: Specification = other
5758

58-
def is_satisfied_by(self, candidate):
59+
def is_satisfied_by(self, candidate: Union["User", str]):
5960
return bool(
6061
self._one.is_satisfied_by(candidate)
6162
or self._other.is_satisfied_by(candidate)
6263
)
6364

6465

6566
class NotSpecification(CompositeSpecification):
66-
def __init__(self, wrapped):
67+
def __init__(self, wrapped: "Specification"):
6768
self._wrapped: Specification = wrapped
6869

69-
def is_satisfied_by(self, candidate):
70+
def is_satisfied_by(self, candidate: Union["User", str]):
7071
return bool(not self._wrapped.is_satisfied_by(candidate))
7172

7273

7374
class User:
74-
def __init__(self, super_user=False):
75+
def __init__(self, super_user: bool = False) -> None:
7576
self.super_user = super_user
7677

7778

7879
class UserSpecification(CompositeSpecification):
79-
def is_satisfied_by(self, candidate):
80+
def is_satisfied_by(self, candidate: Union["User", str]) -> bool:
8081
return isinstance(candidate, User)
8182

8283

8384
class SuperUserSpecification(CompositeSpecification):
84-
def is_satisfied_by(self, candidate):
85+
def is_satisfied_by(self, candidate: "User") -> bool:
8586
return getattr(candidate, "super_user", False)
8687

8788

patterns/behavioral/visitor.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
which is then being used e.g. in tools like `pyflakes`.
1515
- `Black` formatter tool implements it's own: https://github.com/ambv/black/blob/master/black.py#L718
1616
"""
17+
from typing import Union
1718

1819

1920
class Node:
@@ -33,7 +34,7 @@ class C(A, B):
3334

3435

3536
class Visitor:
36-
def visit(self, node, *args, **kwargs):
37+
def visit(self, node: Union[A, C, B], *args, **kwargs) -> None:
3738
meth = None
3839
for cls in node.__class__.__mro__:
3940
meth_name = "visit_" + cls.__name__
@@ -45,11 +46,11 @@ def visit(self, node, *args, **kwargs):
4546
meth = self.generic_visit
4647
return meth(node, *args, **kwargs)
4748

48-
def generic_visit(self, node, *args, **kwargs):
49-
return "generic_visit " + node.__class__.__name__
49+
def generic_visit(self, node: A, *args, **kwargs) -> None:
50+
print("generic_visit " + node.__class__.__name__)
5051

51-
def visit_B(self, node, *args, **kwargs):
52-
return "visit_B " + node.__class__.__name__
52+
def visit_B(self, node: Union[C, B], *args, **kwargs) -> None:
53+
print("visit_B " + node.__class__.__name__)
5354

5455

5556
def main():

patterns/creational/lazy_evaluation.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,23 @@
2020
"""
2121

2222
import functools
23+
from typing import Callable, Type
2324

2425

2526
class lazy_property:
26-
def __init__(self, function):
27+
def __init__(self, function: Callable) -> None:
2728
self.function = function
2829
functools.update_wrapper(self, function)
2930

30-
def __get__(self, obj, type_):
31+
def __get__(self, obj: "Person", type_: Type["Person"]) -> str:
3132
if obj is None:
3233
return self
3334
val = self.function(obj)
3435
obj.__dict__[self.function.__name__] = val
3536
return val
3637

3738

38-
def lazy_property2(fn):
39+
def lazy_property2(fn: Callable) -> property:
3940
"""
4041
A lazy property decorator.
4142
@@ -54,19 +55,19 @@ def _lazy_property(self):
5455

5556

5657
class Person:
57-
def __init__(self, name, occupation):
58+
def __init__(self, name: str, occupation: str) -> None:
5859
self.name = name
5960
self.occupation = occupation
6061
self.call_count2 = 0
6162

6263
@lazy_property
63-
def relatives(self):
64+
def relatives(self) -> str:
6465
# Get all relatives, let's assume that it costs much time.
6566
relatives = "Many relatives."
6667
return relatives
6768

6869
@lazy_property2
69-
def parents(self):
70+
def parents(self) -> str:
7071
self.call_count2 += 1
7172
return "Father and mother"
7273

patterns/creational/pool.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,24 +27,32 @@
2727
*TL;DR
2828
Stores a set of initialized objects kept ready to use.
2929
"""
30+
from queue import Queue
31+
from types import TracebackType
32+
from typing import Union
3033

3134

3235
class ObjectPool:
33-
def __init__(self, queue, auto_get=False):
36+
def __init__(self, queue: Queue, auto_get: bool = False) -> None:
3437
self._queue = queue
3538
self.item = self._queue.get() if auto_get else None
3639

37-
def __enter__(self):
40+
def __enter__(self) -> str:
3841
if self.item is None:
3942
self.item = self._queue.get()
4043
return self.item
4144

42-
def __exit__(self, Type, value, traceback):
45+
def __exit__(
46+
self,
47+
Type: Union[type[BaseException], None],
48+
value: Union[BaseException, None],
49+
traceback: Union[TracebackType, None],
50+
) -> None:
4351
if self.item is not None:
4452
self._queue.put(self.item)
4553
self.item = None
4654

47-
def __del__(self):
55+
def __del__(self) -> None:
4856
if self.item is not None:
4957
self._queue.put(self.item)
5058
self.item = None

patterns/other/graph_search.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1+
from typing import Any, Dict, List, Optional, Union
2+
3+
14
class GraphSearch:
25
"""Graph search emulation in python, from source
36
http://www.python.org/doc/essays/graphs/
47
58
dfs stands for Depth First Search
69
bfs stands for Breadth First Search"""
710

8-
def __init__(self, graph):
11+
def __init__(self, graph: Dict[str, List[str]]) -> None:
912
self.graph = graph
1013

11-
def find_path_dfs(self, start, end, path=None):
14+
def find_path_dfs(
15+
self, start: str, end: str, path: Optional[List[str]] = None
16+
) -> Optional[List[str]]:
1217
path = path or []
1318

1419
path.append(start)
@@ -20,7 +25,9 @@ def find_path_dfs(self, start, end, path=None):
2025
if newpath:
2126
return newpath
2227

23-
def find_all_paths_dfs(self, start, end, path=None):
28+
def find_all_paths_dfs(
29+
self, start: str, end: str, path: Optional[List[str]] = None
30+
) -> List[Union[List[str], Any]]:
2431
path = path or []
2532
path.append(start)
2633
if start == end:
@@ -32,7 +39,9 @@ def find_all_paths_dfs(self, start, end, path=None):
3239
paths.extend(newpaths)
3340
return paths
3441

35-
def find_shortest_path_dfs(self, start, end, path=None):
42+
def find_shortest_path_dfs(
43+
self, start: str, end: str, path: Optional[List[str]] = None
44+
) -> Optional[List[str]]:
3645
path = path or []
3746
path.append(start)
3847

@@ -47,7 +56,7 @@ def find_shortest_path_dfs(self, start, end, path=None):
4756
shortest = newpath
4857
return shortest
4958

50-
def find_shortest_path_bfs(self, start, end):
59+
def find_shortest_path_bfs(self, start: str, end: str) -> Optional[List[str]]:
5160
"""
5261
Finds the shortest path between two nodes in a graph using breadth-first search.
5362

patterns/structural/3-tier.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ class Data:
1616
}
1717

1818
def __get__(self, obj, klas):
19-
2019
print("(Fetching from Data Store)")
2120
return {"products": self.products}
2221

0 commit comments

Comments
 (0)