9
9
10
10
11
11
class Model (ABC ):
12
+ """The Model is the data layer of the application."""
12
13
@abstractmethod
13
14
def __iter__ (self ):
14
15
pass
15
16
16
17
@abstractmethod
17
- def get (self , item ) :
18
+ def get (self , item : str ) -> dict :
18
19
"""Returns an object with a .items() call method
19
20
that iterates over key,value pairs of its information."""
20
21
pass
21
22
22
23
@property
23
24
@abstractmethod
24
- def item_type (self ):
25
+ def item_type (self ) -> str :
25
26
pass
26
27
27
28
28
29
class ProductModel (Model ):
30
+ """The Model is the data layer of the application."""
29
31
class Price (float ):
30
32
"""A polymorphic way to pass a float with a particular
31
33
__str__ functionality."""
32
34
33
- def __str__ (self ):
35
+ def __str__ (self ) -> str :
34
36
return f"{ self :.2f} "
35
37
36
38
products = {
@@ -44,92 +46,98 @@ def __str__(self):
44
46
def __iter__ (self ):
45
47
yield from self .products
46
48
47
- def get (self , product ) :
49
+ def get (self , product : str ) -> dict :
48
50
try :
49
51
return self .products [product ]
50
52
except KeyError as e :
51
53
raise KeyError (str (e ) + " not in the model's item list." )
52
54
53
55
54
56
class View (ABC ):
57
+ """The View is the presentation layer of the application."""
55
58
@abstractmethod
56
- def show_item_list (self , item_type , item_list ) :
59
+ def show_item_list (self , item_type : str , item_list : dict ) -> None :
57
60
pass
58
61
59
62
@abstractmethod
60
- def show_item_information (self , item_type , item_name , item_info ) :
63
+ def show_item_information (self , item_type : str , item_name : str , item_info : dict ) -> None :
61
64
"""Will look for item information by iterating over key,value pairs
62
65
yielded by item_info.items()"""
63
66
pass
64
67
65
68
@abstractmethod
66
- def item_not_found (self , item_type , item_name ) :
69
+ def item_not_found (self , item_type : str , item_name : str ) -> None :
67
70
pass
68
71
69
72
70
73
class ConsoleView (View ):
71
- def show_item_list (self , item_type , item_list ):
74
+ """The View is the presentation layer of the application."""
75
+ def show_item_list (self , item_type : str , item_list : dict ) -> None :
72
76
print (item_type .upper () + " LIST:" )
73
77
for item in item_list :
74
78
print (item )
75
79
print ("" )
76
80
77
81
@staticmethod
78
- def capitalizer (string ):
82
+ def capitalizer (string : str ) -> str :
83
+ """Capitalizes the first letter of a string and lowercases the rest."""
79
84
return string [0 ].upper () + string [1 :].lower ()
80
85
81
- def show_item_information (self , item_type , item_name , item_info ):
86
+ def show_item_information (self , item_type : str , item_name : str , item_info : dict ) -> None :
87
+ """Will look for item information by iterating over key,value pairs"""
82
88
print (item_type .upper () + " INFORMATION:" )
83
89
printout = "Name: %s" % item_name
84
90
for key , value in item_info .items ():
85
91
printout += ", " + self .capitalizer (str (key )) + ": " + str (value )
86
92
printout += "\n "
87
93
print (printout )
88
94
89
- def item_not_found (self , item_type , item_name ) :
95
+ def item_not_found (self , item_type : str , item_name : str ) -> None :
90
96
print (f'That { item_type } "{ item_name } " does not exist in the records' )
91
97
92
98
93
99
class Controller :
94
- def __init__ (self , model , view ):
95
- self .model = model
96
- self .view = view
100
+ """The Controller is the intermediary between the Model and the View."""
101
+ def __init__ (self , model_class : Model , view_class : View ) -> None :
102
+ self .model : Model = model_class
103
+ self .view : View = view_class
97
104
98
- def show_items (self ):
105
+ def show_items (self ) -> None :
99
106
items = list (self .model )
100
107
item_type = self .model .item_type
101
108
self .view .show_item_list (item_type , items )
102
109
103
- def show_item_information (self , item_name ) :
110
+ def show_item_information (self , item_name : str ) -> None :
104
111
"""
105
112
Show information about a {item_type} item.
106
113
:param str item_name: the name of the {item_type} item to show information about
107
114
"""
108
115
try :
109
- item_info = self .model .get (item_name )
116
+ item_info : str = self .model .get (item_name )
110
117
except Exception :
111
- item_type = self .model .item_type
118
+ item_type : str = self .model .item_type
112
119
self .view .item_not_found (item_type , item_name )
113
120
else :
114
- item_type = self .model .item_type
121
+ item_type : str = self .model .item_type
115
122
self .view .show_item_information (item_type , item_name , item_info )
116
123
117
124
118
125
class Router :
126
+ """The Router is the entry point of the application."""
119
127
def __init__ (self ):
120
128
self .routes = {}
121
129
122
- def register (self , path , controller , model , view ) :
123
- model = model ()
124
- view = view ()
125
- self .routes [path ] = controller ( model , view )
130
+ def register (self , path : str , controller_class : Controller , model_class : Model , view_class : View ) -> None :
131
+ model_instance : Model = model_class ()
132
+ view_instance : View = view_class ()
133
+ self .routes [path ] = controller_class ( model_instance , view_instance )
126
134
127
- def resolve (self , path ) :
135
+ def resolve (self , path : str ) -> Controller :
128
136
if self .routes .get (path ):
129
- controller = self .routes [path ]
137
+ controller : Controller = self .routes [path ]
130
138
return controller
131
139
else :
132
- return None
140
+ raise KeyError ( f"No controller registered for path ' { path } '" )
133
141
134
142
135
143
def main ():
@@ -168,13 +176,13 @@ def main():
168
176
if __name__ == "__main__" :
169
177
router = Router ()
170
178
router .register ("products" , Controller , ProductModel , ConsoleView )
171
- controller = router .resolve (argv [1 ])
179
+ controller : Controller = router .resolve (argv [1 ])
172
180
173
- command = str (argv [2 ]) if len (argv ) > 2 else None
174
- args = ' ' .join (map (str , argv [3 :])) if len (argv ) > 3 else None
181
+ action : str = str (argv [2 ]) if len (argv ) > 2 else ""
182
+ args : str = ' ' .join (map (str , argv [3 :])) if len (argv ) > 3 else ""
175
183
176
- if hasattr (controller , command ):
177
- command = getattr (controller , command )
184
+ if hasattr (controller , action ):
185
+ command = getattr (controller , action )
178
186
sig = signature (command )
179
187
180
188
if len (sig .parameters ) > 0 :
@@ -185,7 +193,7 @@ def main():
185
193
else :
186
194
command ()
187
195
else :
188
- print (f"Command { command } not found in the controller." )
196
+ print (f"Command { action } not found in the controller." )
189
197
190
198
import doctest
191
199
doctest .testmod ()
0 commit comments