I am trying to make a MVC framework with routing. The model itself is iterable. If I don't use a router class then it will give all the first keys from the model.
But when using the router class, I get the following error: TypeError: 'ABCMeta' object is not iterable
I have a simplified version of the source code:
Model
from abc import ABC, abstractmethod
class Model(ABC):
@abstractmethod
def __iter__(self):
...
@abstractmethod
def get(self, item):
...
@property
@abstractmethod
def item_type(self, name):
...
class TestModel(Model):
test_items = {
"one": { "name": "1" },
"two": { "name": "2" },
}
item_type = "test"
def __iter__(self):
yield from self.test_items
def get(self, item):
try:
return self.test_items[item]
except KeyError as key_err:
print("Key cannot be found", key_err)
Controller
from abc import ABC, abstractmethod
class Controller(ABC):
@abstractmethod
def __iter__(self):
...
@abstractmethod
def show_items(self):
...
@abstractmethod
def show_item_information(self, item_name):
...
class TestController:
def __init__(self, model, view):
self.view = view
self.model = model
def show_items(self):
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):
try:
item_info = self.model.get(item_name)
except Exception:
item_type = self.model.item_type
self.view.item_not_found(item_type, item_name)
else:
item_type = self.model.item_type
self.view.show_item_information(item_type, item_name, item_info)
Router
class Router:
def __init__(self):
self.routes = {}
def register_controller(self, path, controller, model, view):
self.routes[path] = controller(model, view)
def resolve(self, path):
callback = self.routes.get(path)
if callback:
return callback
return self.default_controller
def default_controller(self, *args, **kwargs):
status = 'Controller not found'
return status
Main
#!/usr/bin/env python3
from sys import argv
from lib.router import Router
from lib.model import TestModel
from lib.view import TestView
from lib.controller import TestController
def main():
router = Router()
router.register_controller('test', TestController, TestModel, TestView)
path = argv[1]
controller = router.resolve(path)
controller.show_items()
if __name__ == '__main__':
main()
What I expect is that with the routering that the model stays iterable.
I have tried to build in a check if the class is Iterable. But this isn't really a solution.