Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
15 changes: 7 additions & 8 deletions patterns/behavioral/chain_of_responsibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,10 @@
"""

from abc import ABC, abstractmethod
from typing import Optional, Tuple


class Handler(ABC):
def __init__(self, successor: Optional["Handler"] = None):
def __init__(self, successor: "Handler | None" = None):
self.successor = successor

def handle(self, request: int) -> None:
Expand All @@ -39,7 +38,7 @@ def handle(self, request: int) -> None:
self.successor.handle(request)

@abstractmethod
def check_range(self, request: int) -> Optional[bool]:
def check_range(self, request: int) -> bool | None:
"""Compare passed value to predefined interval"""


Expand All @@ -49,7 +48,7 @@ class ConcreteHandler0(Handler):
"""

@staticmethod
def check_range(request: int) -> Optional[bool]:
def check_range(request: int) -> bool | None:
if 0 <= request < 10:
print(f"request {request} handled in handler 0")
return True
Expand All @@ -61,7 +60,7 @@ class ConcreteHandler1(Handler):

start, end = 10, 20

def check_range(self, request: int) -> Optional[bool]:
def check_range(self, request: int) -> bool | None:
if self.start <= request < self.end:
print(f"request {request} handled in handler 1")
return True
Expand All @@ -71,21 +70,21 @@ def check_range(self, request: int) -> Optional[bool]:
class ConcreteHandler2(Handler):
"""... With helper methods."""

def check_range(self, request: int) -> Optional[bool]:
def check_range(self, request: int) -> bool | None:
start, end = self.get_interval_from_db()
if start <= request < end:
print(f"request {request} handled in handler 2")
return True
return None

@staticmethod
def get_interval_from_db() -> Tuple[int, int]:
def get_interval_from_db() -> tuple[int, int]:
return (20, 30)


class FallbackHandler(Handler):
@staticmethod
def check_range(request: int) -> Optional[bool]:
def check_range(request: int) -> bool | None:
print(f"end of chain, no handler for {request}")
return False

Expand Down
7 changes: 3 additions & 4 deletions patterns/behavioral/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
https://docs.djangoproject.com/en/2.1/ref/request-response/#httprequest-objects
"""

from typing import List, Union


class HideFileCommand:
Expand All @@ -30,7 +29,7 @@ class HideFileCommand:

def __init__(self) -> None:
# an array of files hidden, to undo them as needed
self._hidden_files: List[str] = []
self._hidden_files: list[str] = []

def execute(self, filename: str) -> None:
print(f"hiding {filename}")
Expand All @@ -48,7 +47,7 @@ class DeleteFileCommand:

def __init__(self) -> None:
# an array of deleted files, to undo them as needed
self._deleted_files: List[str] = []
self._deleted_files: list[str] = []

def execute(self, filename: str) -> None:
print(f"deleting {filename}")
Expand All @@ -64,7 +63,7 @@ class MenuItem:
The invoker class. Here it is items in a menu.
"""

def __init__(self, command: Union[HideFileCommand, DeleteFileCommand]) -> None:
def __init__(self, command: HideFileCommand | DeleteFileCommand) -> None:
self._command = command

def on_do_press(self, filename: str) -> None:
Expand Down
4 changes: 2 additions & 2 deletions patterns/behavioral/memento.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"""

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


def memento(obj: Any, deep: bool = False) -> Callable:
Expand All @@ -26,7 +26,7 @@ class Transaction:
"""

deep = False
states: List[Callable[[], None]] = []
states: list[Callable[[], None]] = []

def __init__(self, deep: bool, *targets: Any) -> None:
self.deep = deep
Expand Down
3 changes: 1 addition & 2 deletions patterns/behavioral/observer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
# observer.py

from __future__ import annotations
from typing import List

class Observer:
def update(self, subject: Subject) -> None:
Expand All @@ -26,7 +25,7 @@ def update(self, subject: Subject) -> None:


class Subject:
_observers: List[Observer]
_observers: list[Observer]

def __init__(self) -> None:
"""
Expand Down
5 changes: 1 addition & 4 deletions patterns/behavioral/registry.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
from typing import Dict


class RegistryHolder(type):
REGISTRY: Dict[str, "RegistryHolder"] = {}
REGISTRY: dict[str, "RegistryHolder"] = {}

def __new__(cls, name, bases, attrs):
new_cls = type.__new__(cls, name, bases, attrs)
Expand Down
9 changes: 4 additions & 5 deletions patterns/behavioral/specification.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"""

from abc import abstractmethod
from typing import Union


class Specification:
Expand Down Expand Up @@ -44,7 +43,7 @@ def __init__(self, one: "Specification", other: "Specification") -> None:
self._one: Specification = one
self._other: Specification = other

def is_satisfied_by(self, candidate: Union["User", str]) -> bool:
def is_satisfied_by(self, candidate: "User" | str) -> bool:
return bool(
self._one.is_satisfied_by(candidate)
and self._other.is_satisfied_by(candidate)
Expand All @@ -56,7 +55,7 @@ def __init__(self, one: "Specification", other: "Specification") -> None:
self._one: Specification = one
self._other: Specification = other

def is_satisfied_by(self, candidate: Union["User", str]):
def is_satisfied_by(self, candidate: "User" | str):
return bool(
self._one.is_satisfied_by(candidate)
or self._other.is_satisfied_by(candidate)
Expand All @@ -67,7 +66,7 @@ class NotSpecification(CompositeSpecification):
def __init__(self, wrapped: "Specification"):
self._wrapped: Specification = wrapped

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


Expand All @@ -77,7 +76,7 @@ def __init__(self, super_user: bool = False) -> None:


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


Expand Down
4 changes: 2 additions & 2 deletions patterns/behavioral/strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def validate(obj: Order, value: Callable) -> bool:
def __set_name__(self, owner, name: str) -> None:
self.private_name = f"_{name}"

def __set__(self, obj: Order, value: Callable = None) -> None:
def __set__(self, obj: Order, value: Callable | None = None) -> None:
if value and self.validate(obj, value):
setattr(obj, self.private_name, value)
else:
Expand All @@ -42,7 +42,7 @@ def __get__(self, obj: object, objtype: type = None):
class Order:
discount_strategy = DiscountStrategyValidator()

def __init__(self, price: float, discount_strategy: Callable = None) -> None:
def __init__(self, price: float, discount_strategy: Callable | None = None) -> None:
self.price: float = price
self.discount_strategy = discount_strategy

Expand Down
5 changes: 2 additions & 3 deletions patterns/behavioral/visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
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 @@ -34,7 +33,7 @@ class C(A, B):


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

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


Expand Down
5 changes: 2 additions & 3 deletions patterns/creational/abstract_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
"""

import random
from typing import Type


class Pet:
Expand Down Expand Up @@ -64,7 +63,7 @@ def __str__(self) -> str:
class PetShop:
"""A pet shop"""

def __init__(self, animal_factory: Type[Pet]) -> None:
def __init__(self, animal_factory: type[Pet]) -> None:
"""pet_factory is our abstract factory. We can set it at will."""

self.pet_factory = animal_factory
Expand All @@ -91,7 +90,7 @@ def main() -> None:

if __name__ == "__main__":
animals = [Dog, Cat]
random_animal: Type[Pet] = random.choice(animals)
random_animal: type[Pet] = random.choice(animals)

shop = PetShop(random_animal)
import doctest
Expand Down
5 changes: 1 addition & 4 deletions patterns/creational/borg.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,8 @@
Provides singleton-like behavior sharing state between instances.
"""

from typing import Dict


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

def __init__(self) -> None:
self.__dict__ = self._shared_state
Expand Down
4 changes: 2 additions & 2 deletions patterns/creational/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
Creates objects without having to specify the exact class.
"""

from typing import Dict, Protocol, Type
from typing import Protocol


class Localizer(Protocol):
Expand All @@ -49,7 +49,7 @@ def localize(self, msg: str) -> str:

def get_localizer(language: str = "English") -> Localizer:
"""Factory"""
localizers: Dict[str, Type[Localizer]] = {
localizers: dict[str, type[Localizer]] = {
"English": EnglishLocalizer,
"Greek": GreekLocalizer,
}
Expand Down
4 changes: 2 additions & 2 deletions patterns/creational/lazy_evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,15 @@
"""

import functools
from typing import Callable, Type
from typing import Callable


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

def __get__(self, obj: "Person", type_: Type["Person"]) -> str:
def __get__(self, obj: "Person", type_: type["Person"]) -> str:
if obj is None:
return self
val = self.function(obj)
Expand Down
7 changes: 3 additions & 4 deletions patterns/creational/pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
"""
from queue import Queue
from types import TracebackType
from typing import Union


class ObjectPool:
Expand All @@ -44,9 +43,9 @@ def __enter__(self) -> str:

def __exit__(
self,
Type: Union[type[BaseException], None],
value: Union[BaseException, None],
traceback: Union[TracebackType, None],
Type: type[BaseException] | None,
value: BaseException | None,
traceback: TracebackType | None,
) -> None:
if self.item is not None:
self._queue.put(self.item)
Expand Down
2 changes: 1 addition & 1 deletion patterns/fundamental/delegation_pattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Delegator:
def __init__(self, delegate: Delegate) -> None:
self.delegate = delegate

def __getattr__(self, name: str) -> Any | Callable:
def __getattr__(self, name: str) -> Any:
attr = getattr(self.delegate, name)

if not callable(attr):
Expand Down
18 changes: 9 additions & 9 deletions patterns/other/graph_search.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Dict, List, Optional, Union
from typing import Any


class GraphSearch:
Expand All @@ -8,12 +8,12 @@ class GraphSearch:
dfs stands for Depth First Search
bfs stands for Breadth First Search"""

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

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

path.append(start)
Expand All @@ -26,8 +26,8 @@ def find_path_dfs(
return newpath

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

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

Expand All @@ -56,7 +56,7 @@ def find_shortest_path_dfs(
shortest = newpath
return shortest

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

Expand Down
Loading