Skip to content

Mvc add typing #439

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

Closed
wants to merge 7 commits 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: 3 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
os: linux
dist: focal
dist: noble
language: python

jobs:
include:
- python: "3.8"
env: TOXENV=py38
- python: "3.9"
env: TOXENV=py39
- python: "3.12"
env: TOXENV=py312

cache:
- pip
Expand Down
2 changes: 1 addition & 1 deletion lint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@ tox
mypy --ignore-missing-imports "${source_dir}" || true
pytest "${source_dir}"
pytest --doctest-modules "${source_dir}" || true
shopt -s globstar && pyupgrade --py37-plus ${source_dir}/*.py
shopt -s globstar && pyupgrade --py312-plus ${source_dir}/*.py
58 changes: 29 additions & 29 deletions patterns/structural/mvc.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ def __iter__(self):
pass

@abstractmethod
def get(self, item):
def get(self, item: str) -> dict:
"""Returns an object with a .items() call method
that iterates over key,value pairs of its information."""
pass

@property
@abstractmethod
def item_type(self):
def item_type(self) -> str:
pass


Expand All @@ -30,7 +30,7 @@ class Price(float):
"""A polymorphic way to pass a float with a particular
__str__ functionality."""

def __str__(self):
def __str__(self) -> str:
return f"{self:.2f}"

products = {
Expand All @@ -44,7 +44,7 @@ def __str__(self):
def __iter__(self):
yield from self.products

def get(self, product):
def get(self, product: str) -> dict:
try:
return self.products[product]
except KeyError as e:
Expand All @@ -53,54 +53,54 @@ def get(self, product):

class View(ABC):
@abstractmethod
def show_item_list(self, item_type, item_list):
def show_item_list(self, item_type: str, item_list: dict) -> None:
pass

@abstractmethod
def show_item_information(self, item_type, item_name, item_info):
def show_item_information(self, item_type: str, item_name: str, item_info: str) -> None:
"""Will look for item information by iterating over key,value pairs
yielded by item_info.items()"""
pass

@abstractmethod
def item_not_found(self, item_type, item_name):
def item_not_found(self, item_type: str, item_name: str) -> None:
pass


class ConsoleView(View):
def show_item_list(self, item_type, item_list):
def show_item_list(self, item_type: str, item_list: dict) -> None:
print(item_type.upper() + " LIST:")
for item in item_list:
print(item)
print("")

@staticmethod
def capitalizer(string):
def capitalizer(string) -> str:
return string[0].upper() + string[1:].lower()

def show_item_information(self, item_type, item_name, item_info):
def show_item_information(self, item_type, item_name, item_info) -> None:
print(item_type.upper() + " INFORMATION:")
printout = "Name: %s" % item_name
for key, value in item_info.items():
printout += ", " + self.capitalizer(str(key)) + ": " + str(value)
printout += "\n"
print(printout)

def item_not_found(self, item_type, item_name):
def item_not_found(self, item_type: str, item_name: str) -> None:
print(f'That {item_type} "{item_name}" does not exist in the records')


class Controller:
def __init__(self, model, view):
self.model = model
self.view = view
def __init__(self, model_class, view_class) -> None:
self.model = model_class
self.view = view_class

def show_items(self):
def show_items(self) -> None:
items = list(self.model)
item_type = self.model.item_type
self.view.show_item_list(item_type, items)

def show_item_information(self, item_name):
def show_item_information(self, item_name: str) -> None:
"""
Show information about a {item_type} item.
:param str item_name: the name of the {item_type} item to show information about
Expand All @@ -119,17 +119,17 @@ class Router:
def __init__(self):
self.routes = {}

def register(self, path, controller, model, view):
model = model()
view = view()
self.routes[path] = controller(model, view)
def register(self, path: str, controller_class, model_class, view_class) -> None:
model_instance = model_class()
view_instance = view_class()
self.routes[path] = controller_class(model_instance, view_instance)

def resolve(self, path):
def resolve(self, path: str) -> Controller:
if self.routes.get(path):
controller = self.routes[path]
controller: Controller = self.routes[path]
return controller
else:
return None
raise KeyError(f"No controller registered for path '{path}'")


def main():
Expand Down Expand Up @@ -168,13 +168,13 @@ def main():
if __name__ == "__main__":
router = Router()
router.register("products", Controller, ProductModel, ConsoleView)
controller = router.resolve(argv[1])
controller: Controller = router.resolve(argv[1])

command = str(argv[2]) if len(argv) > 2 else None
args = ' '.join(map(str, argv[3:])) if len(argv) > 3 else None
action: str = str(argv[2]) if len(argv) > 2 else ""
args: str = ' '.join(map(str, argv[3:])) if len(argv) > 3 else ""

if hasattr(controller, command):
command = getattr(controller, command)
if hasattr(controller, action):
command = getattr(controller, action)
sig = signature(command)

if len(sig.parameters) > 0:
Expand All @@ -185,7 +185,7 @@ def main():
else:
command()
else:
print(f"Command {command} not found in the controller.")
print(f"Command {action} not found in the controller.")

import doctest
doctest.testmod()
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ filterwarnings =
ignore:.*test class 'TestRunner'.*:Warning

[mypy]
python_version = 3.8
python_version = 3.12
ignore_missing_imports = True
9 changes: 3 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,10 @@
packages=find_packages(),
description="A collection of design patterns and idioms in Python.",
classifiers=[
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
],
)
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[tox]
envlist = py38,py39,py310,cov-report
envlist = py310,py312,cov-report
skip_missing_interpreters = true


Expand Down
Loading