Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add type hint to remaining pattern modules #410

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion patterns/behavioral/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ class Catalog:
"""

def __init__(self, param: str) -> None:

# dictionary that will be used to determine which static method is
# to be executed but that will be also used to store possible param
# value
Expand Down
24 changes: 12 additions & 12 deletions patterns/behavioral/memento.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
Provides the ability to restore an object to its previous state.
"""

from typing import Callable, List
from typing import Any, Type, Callable, List
from copy import copy, deepcopy


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

def restore():
def restore() -> None:
obj.__dict__.clear()
obj.__dict__.update(state)

Expand All @@ -28,15 +28,15 @@ class Transaction:
deep = False
states: List[Callable[[], None]] = []

def __init__(self, deep, *targets):
def __init__(self, deep: bool, *targets: Any) -> None:
self.deep = deep
self.targets = targets
self.commit()

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

def rollback(self):
def rollback(self) -> None:
for a_state in self.states:
a_state()

Expand All @@ -47,10 +47,10 @@ class Transactional:
@Transactional will rollback to entry-state upon exceptions.
"""

def __init__(self, method):
def __init__(self, method: Callable) -> None:
self.method = method

def __get__(self, obj, T):
def __get__(self, obj: Any, T: Type) -> Callable:
"""
A decorator that makes a function transactional.

Expand All @@ -69,17 +69,17 @@ def transaction(*args, **kwargs):


class NumObj:
def __init__(self, value):
def __init__(self, value: int) -> None:
self.value = value

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

def increment(self):
def increment(self) -> None:
self.value += 1

@Transactional
def do_stuff(self):
def do_stuff(self) -> None:
self.value = "1111" # <- invalid value
self.increment() # <- will fail and rollback

Expand Down
1 change: 0 additions & 1 deletion patterns/behavioral/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@


class RegistryHolder(type):

REGISTRY: Dict[str, "RegistryHolder"] = {}

def __new__(cls, name, bases, attrs):
Expand Down
25 changes: 13 additions & 12 deletions patterns/behavioral/specification.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"""

from abc import abstractmethod
from typing import Union


class Specification:
Expand All @@ -28,60 +29,60 @@ class CompositeSpecification(Specification):
def is_satisfied_by(self, candidate):
pass

def and_specification(self, candidate):
def and_specification(self, candidate: "Specification") -> "AndSpecification":
return AndSpecification(self, candidate)

def or_specification(self, candidate):
def or_specification(self, candidate: "Specification") -> "OrSpecification":
return OrSpecification(self, candidate)

def not_specification(self):
def not_specification(self) -> "NotSpecification":
return NotSpecification(self)


class AndSpecification(CompositeSpecification):
def __init__(self, one, other):
def __init__(self, one: "Specification", other: "Specification") -> None:
self._one: Specification = one
self._other: Specification = other

def is_satisfied_by(self, candidate):
def is_satisfied_by(self, candidate: Union["User", str]) -> bool:
return bool(
self._one.is_satisfied_by(candidate)
and self._other.is_satisfied_by(candidate)
)


class OrSpecification(CompositeSpecification):
def __init__(self, one, other):
def __init__(self, one: "Specification", other: "Specification") -> None:
self._one: Specification = one
self._other: Specification = other

def is_satisfied_by(self, candidate):
def is_satisfied_by(self, candidate: Union["User", str]):
return bool(
self._one.is_satisfied_by(candidate)
or self._other.is_satisfied_by(candidate)
)


class NotSpecification(CompositeSpecification):
def __init__(self, wrapped):
def __init__(self, wrapped: "Specification"):
self._wrapped: Specification = wrapped

def is_satisfied_by(self, candidate):
def is_satisfied_by(self, candidate: Union["User", str]):
return bool(not self._wrapped.is_satisfied_by(candidate))


class User:
def __init__(self, super_user=False):
def __init__(self, super_user: bool = False) -> None:
self.super_user = super_user


class UserSpecification(CompositeSpecification):
def is_satisfied_by(self, candidate):
def is_satisfied_by(self, candidate: Union["User", str]) -> bool:
return isinstance(candidate, User)


class SuperUserSpecification(CompositeSpecification):
def is_satisfied_by(self, candidate):
def is_satisfied_by(self, candidate: "User") -> bool:
return getattr(candidate, "super_user", False)


Expand Down
7 changes: 4 additions & 3 deletions patterns/behavioral/visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
which is then being used e.g. in tools like `pyflakes`.
- `Black` formatter tool implements it's own: https://github.com/ambv/black/blob/master/black.py#L718
"""
from typing import Union


class Node:
Expand All @@ -33,7 +34,7 @@ class C(A, B):


class Visitor:
def visit(self, node, *args, **kwargs):
def visit(self, node: Union[A, C, B], *args, **kwargs) -> None:
meth = None
for cls in node.__class__.__mro__:
meth_name = "visit_" + cls.__name__
Expand All @@ -45,10 +46,10 @@ def visit(self, node, *args, **kwargs):
meth = self.generic_visit
return meth(node, *args, **kwargs)

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

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


Expand Down
1 change: 1 addition & 0 deletions patterns/creational/abstract_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def buy_pet(self, name: str) -> Pet:

# Additional factories:


# Create a random animal
def random_animal(name: str) -> Pet:
"""Let's be dynamic!"""
Expand Down
1 change: 0 additions & 1 deletion patterns/creational/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ def localize(self, msg: str) -> str:


def get_localizer(language: str = "English") -> Localizer:

"""Factory"""
localizers: Dict[str, Type[Localizer]] = {
"English": EnglishLocalizer,
Expand Down
13 changes: 7 additions & 6 deletions patterns/creational/lazy_evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,23 @@
"""

import functools
from typing import Callable, Type


class lazy_property:
def __init__(self, function):
def __init__(self, function: Callable) -> None:
self.function = function
functools.update_wrapper(self, function)

def __get__(self, obj, type_):
def __get__(self, obj: "Person", type_: Type["Person"]) -> str:
if obj is None:
return self
val = self.function(obj)
obj.__dict__[self.function.__name__] = val
return val


def lazy_property2(fn):
def lazy_property2(fn: Callable) -> property:
"""
A lazy property decorator.

Expand All @@ -54,19 +55,19 @@ def _lazy_property(self):


class Person:
def __init__(self, name, occupation):
def __init__(self, name: str, occupation: str) -> None:
self.name = name
self.occupation = occupation
self.call_count2 = 0

@lazy_property
def relatives(self):
def relatives(self) -> str:
# Get all relatives, let's assume that it costs much time.
relatives = "Many relatives."
return relatives

@lazy_property2
def parents(self):
def parents(self) -> str:
self.call_count2 += 1
return "Father and mother"

Expand Down
16 changes: 12 additions & 4 deletions patterns/creational/pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,32 @@
*TL;DR
Stores a set of initialized objects kept ready to use.
"""
from queue import Queue
from types import TracebackType
from typing import Union


class ObjectPool:
def __init__(self, queue, auto_get=False):
def __init__(self, queue: Queue, auto_get: bool = False) -> None:
self._queue = queue
self.item = self._queue.get() if auto_get else None

def __enter__(self):
def __enter__(self) -> str:
if self.item is None:
self.item = self._queue.get()
return self.item

def __exit__(self, Type, value, traceback):
def __exit__(
self,
Type: Union[type[BaseException], None],
value: Union[BaseException, None],
traceback: Union[TracebackType, None],
) -> None:
if self.item is not None:
self._queue.put(self.item)
self.item = None

def __del__(self):
def __del__(self) -> None:
if self.item is not None:
self._queue.put(self.item)
self.item = None
Expand Down
19 changes: 14 additions & 5 deletions patterns/other/graph_search.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from typing import Any, Dict, List, Optional, Union


class GraphSearch:

"""Graph search emulation in python, from source
Expand All @@ -6,10 +9,12 @@ class GraphSearch:
dfs stands for Depth First Search
bfs stands for Breadth First Search"""

def __init__(self, graph):
def __init__(self, graph: Dict[str, List[str]]) -> None:
self.graph = graph

def find_path_dfs(self, start, end, path=None):
def find_path_dfs(
self, start: str, end: str, path: Optional[List[str]] = None
) -> Optional[List[str]]:
path = path or []

path.append(start)
Expand All @@ -21,7 +26,9 @@ def find_path_dfs(self, start, end, path=None):
if newpath:
return newpath

def find_all_paths_dfs(self, start, end, path=None):
def find_all_paths_dfs(
self, start: str, end: str, path: Optional[List[str]] = None
) -> List[Union[List[str], Any]]:
path = path or []
path.append(start)
if start == end:
Expand All @@ -33,7 +40,9 @@ def find_all_paths_dfs(self, start, end, path=None):
paths.extend(newpaths)
return paths

def find_shortest_path_dfs(self, start, end, path=None):
def find_shortest_path_dfs(
self, start: str, end: str, path: Optional[List[str]] = None
) -> Optional[List[str]]:
path = path or []
path.append(start)

Expand All @@ -48,7 +57,7 @@ def find_shortest_path_dfs(self, start, end, path=None):
shortest = newpath
return shortest

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

Expand Down
1 change: 0 additions & 1 deletion patterns/structural/3-tier.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ class Data:
}

def __get__(self, obj, klas):

print("(Fetching from Data Store)")
return {"products": self.products}

Expand Down
Loading
Loading