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

Adding typehints to all files #400

Closed
wants to merge 1 commit into from
Closed
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
8 changes: 5 additions & 3 deletions patterns/behavioral/iterator.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@
Traverses a container and accesses the container's elements.
"""

from typing import Any, Generator

def count_to(count: int):

def count_to(count: int) -> Generator[str, Any, None]:
"""Counts by word numbers, up to a maximum of five"""
numbers = ["one", "two", "three", "four", "five"]
yield from numbers[:count]


# Test the generator
def count_to_two() -> None:
def count_to_two() -> Generator[str, Any, None]:
return count_to(2)


def count_to_five() -> None:
def count_to_five() -> Generator[str, Any, None]:
return count_to(5)


Expand Down
30 changes: 16 additions & 14 deletions patterns/behavioral/publish_subscribe.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,48 +4,50 @@
Author: https://github.com/HanWenfang
"""

from __future__ import annotations


class Provider:
def __init__(self):
def __init__(self) -> None:
self.msg_queue = []
self.subscribers = {}
self.subscribers: dict[str, list[Subscriber]] = {}

def notify(self, msg):
def notify(self, msg: str) -> None:
self.msg_queue.append(msg)

def subscribe(self, msg, subscriber):
def subscribe(self, msg: str, subscriber: Subscriber) -> None:
self.subscribers.setdefault(msg, []).append(subscriber)

def unsubscribe(self, msg, subscriber):
def unsubscribe(self, msg: str, subscriber: Subscriber) -> None:
self.subscribers[msg].remove(subscriber)

def update(self):
def update(self) -> None:
for msg in self.msg_queue:
for sub in self.subscribers.get(msg, []):
sub.run(msg)
self.msg_queue = []


class Publisher:
def __init__(self, msg_center):
def __init__(self, msg_center: Provider) -> None:
self.provider = msg_center

def publish(self, msg):
def publish(self, msg: str) -> None:
self.provider.notify(msg)


class Subscriber:
def __init__(self, name, msg_center):
self.name = name
self.provider = msg_center
def __init__(self, name: str, msg_center: Provider) -> None:
self.name: str = name
self.provider: Provider = msg_center

def subscribe(self, msg):
def subscribe(self, msg: str) -> None:
self.provider.subscribe(msg, self)

def unsubscribe(self, msg):
def unsubscribe(self, msg: str) -> None:
self.provider.unsubscribe(msg, self)

def run(self, msg):
def run(self, msg: str) -> None:
print(f"{self.name} got {msg}")


Expand Down
5 changes: 3 additions & 2 deletions patterns/behavioral/registry.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from __future__ import annotations
from typing import Dict


class RegistryHolder(type):

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

def __new__(cls, name, bases, attrs):
def __new__(cls, name: str, bases: tuple, attrs: dict) -> type:
new_cls = type.__new__(cls, name, bases, attrs)
"""
Here the name of the class is used as key but it could be any class
Expand All @@ -15,7 +16,7 @@ def __new__(cls, name, bases, attrs):
return new_cls

@classmethod
def get_registry(cls):
def get_registry(cls) -> dict:
return dict(cls.REGISTRY)


Expand Down
35 changes: 18 additions & 17 deletions patterns/behavioral/specification.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,83 +5,84 @@
Provides recombination business logic by chaining together using boolean logic.
"""

from __future__ import annotations
from abc import abstractmethod


class Specification:
def and_specification(self, candidate):
def and_specification(self, candidate) -> None:
raise NotImplementedError()

def or_specification(self, candidate):
def or_specification(self, candidate) -> None:
raise NotImplementedError()

def not_specification(self):
def not_specification(self, candidate) -> None:
raise NotImplementedError()

@abstractmethod
def is_satisfied_by(self, candidate):
def is_satisfied_by(self, candidate) -> None:
pass


class CompositeSpecification(Specification):
@abstractmethod
def is_satisfied_by(self, candidate):
def is_satisfied_by(self, candidate) -> None:
pass

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

def or_specification(self, candidate):
def or_specification(self, candidate) -> 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, other) -> None:
self._one: Specification = one
self._other: Specification = other

def is_satisfied_by(self, candidate):
def is_satisfied_by(self, candidate) -> 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, other) -> None:
self._one: Specification = one
self._other: Specification = other

def is_satisfied_by(self, candidate):
def is_satisfied_by(self, candidate) -> bool:
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) -> None:
self._wrapped: Specification = wrapped

def is_satisfied_by(self, candidate):
def is_satisfied_by(self, candidate) -> bool:
return bool(not self._wrapped.is_satisfied_by(candidate))


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


class UserSpecification(CompositeSpecification):
def is_satisfied_by(self, candidate):
def is_satisfied_by(self, candidate) -> bool:
return isinstance(candidate, User)


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


Expand Down
40 changes: 21 additions & 19 deletions patterns/behavioral/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
Implements state transitions by invoking methods from the pattern's superclass.
"""

from __future__ import annotations


class State:

"""Base state. This is to share functionality"""

def scan(self):
def scan(self: AmState) -> None:
"""Scan the dial to the next station"""
self.pos += 1
if self.pos == len(self.stations):
Expand All @@ -22,25 +24,25 @@ def scan(self):


class AmState(State):
def __init__(self, radio):
self.radio = radio
self.stations = ["1250", "1380", "1510"]
self.pos = 0
self.name = "AM"
def __init__(self, radio) -> None:
self.radio: Radio = radio
self.stations: list[str] = ["1250", "1380", "1510"]
self.pos: int = 0
self.name: str = "AM"

def toggle_amfm(self):
def toggle_amfm(self) -> None:
print("Switching to FM")
self.radio.state = self.radio.fmstate


class FmState(State):
def __init__(self, radio):
self.radio = radio
self.stations = ["81.3", "89.1", "103.9"]
self.pos = 0
self.name = "FM"
def __init__(self, radio) -> None:
self.radio: Radio = radio
self.stations: list[str] = ["81.3", "89.1", "103.9"]
self.pos: int = 0
self.name: str = "FM"

def toggle_amfm(self):
def toggle_amfm(self) -> None:
print("Switching to AM")
self.radio.state = self.radio.amstate

Expand All @@ -49,16 +51,16 @@ class Radio:

"""A radio. It has a scan button, and an AM/FM toggle switch."""

def __init__(self):
def __init__(self) -> None:
"""We have an AM state and an FM state"""
self.amstate = AmState(self)
self.fmstate = FmState(self)
self.state = self.amstate
self.amstate: AmState = AmState(self)
self.fmstate: FmState = FmState(self)
self.state: AmState = self.amstate

def toggle_amfm(self):
def toggle_amfm(self) -> None:
self.state.toggle_amfm()

def scan(self):
def scan(self) -> None:
self.state.scan()


Expand Down
9 changes: 6 additions & 3 deletions patterns/behavioral/visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
- `Black` formatter tool implements it's own: https://github.com/ambv/black/blob/master/black.py#L718
"""

from __future__ import annotations
from typing import Union


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


class Visitor:
def visit(self, node, *args, **kwargs):
def visit(self, node: Node, *args, **kwargs) -> Union[generic_visit, visit_B]:
meth = None
for cls in node.__class__.__mro__:
meth_name = "visit_" + cls.__name__
Expand All @@ -45,10 +48,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, *args, **kwargs) -> None:
print("generic_visit " + node.__class__.__name__)

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


Expand Down
11 changes: 6 additions & 5 deletions patterns/creational/borg.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,28 @@
*TL;DR
Provides singleton-like behavior sharing state between instances.
"""
from typing import Dict

from typing import Dict, Union


class Borg:
_shared_state: Dict[str, str] = {}

def __init__(self):
def __init__(self) -> None:
self.__dict__ = self._shared_state


class YourBorg(Borg):
def __init__(self, state=None):
def __init__(self, state=None) -> None:
super().__init__()
if state:
self.state = state
self.state: Union[str, None] = state
else:
# initiate the first instance with default state
if not hasattr(self, "state"):
self.state = "Init"

def __str__(self):
def __str__(self) -> str:
return self.state


Expand Down
Loading