From 96c8e248b8cb306e9a76836f63fc06915411e01f Mon Sep 17 00:00:00 2001 From: Marcus Pereira Date: Sun, 12 Sep 2021 13:17:12 -0300 Subject: [PATCH] Refactoring the methods of the FlaskMVC class --- example/app.py | 12 ---- example/controllers/home_controller.py | 12 ---- example/views/index.html | 1 - example/views/post/new.html | 12 ---- mvc_flask/__init__.py | 68 ++++++++++++------- sample_app/app.py | 14 ++++ .../controllers/contact_controller.py | 0 sample_app/controllers/home_controller.py | 6 ++ {example => sample_app}/routes.json | 12 ---- sample_app/views/index.html | 1 + tests/__init__.py | 0 tests/fixtures.py | 21 +++--- tests/test_routes.py | 27 +++++--- tests/test_visitors_visit_routes.py | 36 ---------- 14 files changed, 92 insertions(+), 130 deletions(-) delete mode 100644 example/app.py delete mode 100644 example/controllers/home_controller.py delete mode 100644 example/views/index.html delete mode 100644 example/views/post/new.html create mode 100644 sample_app/app.py rename {example => sample_app}/controllers/contact_controller.py (100%) create mode 100644 sample_app/controllers/home_controller.py rename {example => sample_app}/routes.json (50%) create mode 100644 sample_app/views/index.html create mode 100644 tests/__init__.py delete mode 100644 tests/test_visitors_visit_routes.py diff --git a/example/app.py b/example/app.py deleted file mode 100644 index 9f53718..0000000 --- a/example/app.py +++ /dev/null @@ -1,12 +0,0 @@ -from flask import Flask -from mvc_flask import FlaskMVC - -mvc = FlaskMVC() - - -def create_app(): - app = Flask(__name__) - app.config["FLASK_MVC_DIR"] = "example" - mvc.init_app(app) - - return app diff --git a/example/controllers/home_controller.py b/example/controllers/home_controller.py deleted file mode 100644 index 09e186f..0000000 --- a/example/controllers/home_controller.py +++ /dev/null @@ -1,12 +0,0 @@ -from flask import render_template, redirect, url_for, request - - -class HomeController: - def index(self): - return render_template("index.html") - - def new(self): - return render_template("post/new.html") - - def create(self): - return redirect(url_for(".index")) diff --git a/example/views/index.html b/example/views/index.html deleted file mode 100644 index 2d6a743..0000000 --- a/example/views/index.html +++ /dev/null @@ -1 +0,0 @@ -

Hello, World!

\ No newline at end of file diff --git a/example/views/post/new.html b/example/views/post/new.html deleted file mode 100644 index b17b641..0000000 --- a/example/views/post/new.html +++ /dev/null @@ -1,12 +0,0 @@ -
-
- Formulate - -
- - -
- -
- -
\ No newline at end of file diff --git a/mvc_flask/__init__.py b/mvc_flask/__init__.py index 64f6ad8..ce88221 100644 --- a/mvc_flask/__init__.py +++ b/mvc_flask/__init__.py @@ -1,39 +1,55 @@ -import json -from pathlib import Path from importlib import import_module +import json +from pathlib import Path from flask import Flask +from flask.blueprints import Blueprint +from collections import namedtuple + + +Route = namedtuple("Route", ["method", "path", "controller", "action"]) class FlaskMVC: - def __init__(self, app: Flask = None): + def __init__(self, app: Flask = None, directory: str = "app"): + self.directory = Path(directory) + if app is not None: self.init_app(app) def init_app(self, app): - app.template_folder = "views" - app.config.setdefault("FLASK_MVC_DIR", "app") - - self.root_path = Path(app.config["FLASK_MVC_DIR"]) - - self._register_router(app) - - def _routes(self): - with open(self.root_path / "routes.json", mode="r") as f: - return json.load(f) - - def _register_router(self, app): - for route in self._routes(): - controller = route["controller"] - - mod = import_module( - f"{self.root_path}.controllers.{controller}_controller" + self.create_blueprint(app) + + def routes(self): + routes = [] + with open(self.directory / "routes.json", mode="r") as f: + routes = [ + Route( + route["method"], + route["path"], + route["controller"], + route["action"], + ) + for route in json.load(f) + ] + return routes + + def create_blueprint(self, app: Flask): + for route in self.routes(): + dd = ( + self.directory + / "controllers" + / f"{route.controller}_controller" ) - clazz = getattr(mod, f"{controller.title()}Controller") - app.add_url_rule( - route["path"], - endpoint=f"{controller}.{route['action']}", - view_func=getattr(clazz(), route["action"]), - methods=[route["method"]], + obj = import_module(dd.as_posix().replace("/", ".")) + controller = getattr(obj, f"{route.controller.title()}Controller") + + blueprint = Blueprint(route.controller, route.controller) + blueprint.add_url_rule( + rule=route.path, + endpoint=route.action, + view_func=getattr(controller(), route.action), + methods=[route.method], ) + app.register_blueprint(blueprint) diff --git a/sample_app/app.py b/sample_app/app.py new file mode 100644 index 0000000..d8963ec --- /dev/null +++ b/sample_app/app.py @@ -0,0 +1,14 @@ +from flask import Flask +from mvc_flask import FlaskMVC + + +def create_app(): + app = Flask(__name__) + return app + + +if __name__ == "__main__": + app = create_app() + app.template_folder = "views" + FlaskMVC(app, ".") + app.run() diff --git a/example/controllers/contact_controller.py b/sample_app/controllers/contact_controller.py similarity index 100% rename from example/controllers/contact_controller.py rename to sample_app/controllers/contact_controller.py diff --git a/sample_app/controllers/home_controller.py b/sample_app/controllers/home_controller.py new file mode 100644 index 0000000..31c1a3f --- /dev/null +++ b/sample_app/controllers/home_controller.py @@ -0,0 +1,6 @@ +from flask import render_template + + +class HomeController: + def index(self): + return render_template("index.html") diff --git a/example/routes.json b/sample_app/routes.json similarity index 50% rename from example/routes.json rename to sample_app/routes.json index 23e0718..ab30968 100644 --- a/example/routes.json +++ b/sample_app/routes.json @@ -5,18 +5,6 @@ "controller": "home", "action": "index" }, - { - "method": "get", - "path": "/new", - "controller": "home", - "action": "new" - }, - { - "method": "post", - "path": "/create", - "controller": "home", - "action": "create" - }, { "method": "GET", "path": "/contact", diff --git a/sample_app/views/index.html b/sample_app/views/index.html new file mode 100644 index 0000000..f76d8e9 --- /dev/null +++ b/sample_app/views/index.html @@ -0,0 +1 @@ +

Hello, World!

diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/fixtures.py b/tests/fixtures.py index cca0e1c..9333d80 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -1,21 +1,20 @@ -from example.app import create_app -from mvc_flask import FlaskMVC +from sample_app.app import create_app from ward import fixture +from mvc_flask import FlaskMVC @fixture -def test_client(): +def test_app(): app = create_app() app.testing = True - app_contenxt = app.test_request_context() - app_contenxt.push() - - return app.test_client() + app.template_folder = "views" + FlaskMVC(app, directory="sample_app") + return app @fixture -def test_app(): - app = create_app() - app.testing = True +def test_client(app=test_app): + app_contenxt = app.test_request_context() + app_contenxt.push() - return app + return app.test_client() diff --git a/tests/test_routes.py b/tests/test_routes.py index 7967097..4b5f3de 100644 --- a/tests/test_routes.py +++ b/tests/test_routes.py @@ -1,5 +1,5 @@ -from ward import test, expect, skip -from fixtures import test_app +from ward import test, expect +from tests.fixtures import test_app, test_client @test("contains routes") @@ -8,8 +8,6 @@ def _(app=test_app): expect.assert_in("/contact", routes, None) expect.assert_in("/", routes, None) - expect.assert_in("/new", routes, None) - expect.assert_in("/create", routes, None) @test("contains endpoints") @@ -17,8 +15,6 @@ def _(app=test_app): endpoints = [route.endpoint for route in app.url_map.iter_rules()] expect.assert_in("home.index", endpoints, None) - expect.assert_in("home.new", endpoints, None) - expect.assert_in("home.create", endpoints, None) expect.assert_in("contact.index", endpoints, None) @@ -30,5 +26,20 @@ def _(app=test_app): for route in routes.methods ] - expect.assert_equal(methods.count("GET"), 4, None) - expect.assert_equal(methods.count("POST"), 1, None) + expect.assert_equal(methods.count("GET"), 3, None) + + +@test("must contains text") +def _(client=test_client): + res = client.get("/") + + expect.assert_equal(res.status_code, 200, None) + expect.assert_in("Hello, World!", res.get_data(as_text=True), None) + + +@test("must contains text") +def _(client=test_client): + res = client.get("/contact") + + expect.assert_equal(res.status_code, 200, None) + expect.assert_in("Contact page", res.get_data(as_text=True), None) diff --git a/tests/test_visitors_visit_routes.py b/tests/test_visitors_visit_routes.py deleted file mode 100644 index f1dae3c..0000000 --- a/tests/test_visitors_visit_routes.py +++ /dev/null @@ -1,36 +0,0 @@ -from ward import test, expect -from fixtures import test_client - - -@test("must contains text") -def _(client=test_client): - res = client.get("/") - - expect.assert_equal(res.status_code, 200, None) - expect.assert_in("Hello, World!", res.get_data(as_text=True), None) - - -@test("must contains text") -def _(client=test_client): - res = client.get("/contact") - - expect.assert_equal(res.status_code, 200, None) - expect.assert_in("Contact page", res.get_data(as_text=True), None) - - -@test("must contains form") -def _(client=test_client): - res = client.get("/new") - - expect.assert_equal(res.status_code, 200, None) - expect.assert_in("form", res.get_data(as_text=True), None) - expect.assert_in("Send", res.get_data(as_text=True), None) - - -@test("must redirect to index") -def _(client=test_client): - res = client.post("/create", follow_redirects=True) - - expect.assert_equal(res.status_code, 200, None) - expect.assert_equal(res.request.path, "/", None) - expect.assert_in("Hello, World!", res.get_data(as_text=True), None)