Skip to content

Commit 818ed36

Browse files
committed
refactor
1 parent 0f09377 commit 818ed36

File tree

3 files changed

+163
-115
lines changed

3 files changed

+163
-115
lines changed

core.py

Lines changed: 2 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import pkgutil
2-
import os
3-
import inspect
1+
from package_extractor import PackageExtractor
42

53
"""
64
Description:: Initialize the blueprints inside in the root folder
@@ -26,115 +24,4 @@ def __init__(self, app, root_path):
2624
self.root_path = root_path
2725

2826
""" register blueprint to the current path """
29-
self.add_blueprint(root_path)
30-
31-
def directory_path(self, path):
32-
33-
""" get all the list of files and directories """
34-
for file in os.listdir(path):
35-
36-
""" prevent __pycache__ directory or any directory that has __ """
37-
if "__" not in file:
38-
""" get the full path directory """
39-
dir_file = path + '/' + file
40-
41-
""" check is the path is a directory
42-
only directories are picked
43-
"""
44-
if os.path.isdir(dir_file):
45-
""" register blueprint on the directory """
46-
self.add_blueprint(dir_file)
47-
48-
""" find sub directories on each directory found """
49-
self.directory_path(path=dir_file)
50-
51-
@staticmethod
52-
def blueprint_name(name):
53-
""" set index automatically as home page """
54-
if "index" in name:
55-
name = str(name).replace("index", "")
56-
if "routes" in name:
57-
name = str(name).replace("routes", "")
58-
59-
""" remove the last . in the string it it ends with a .
60-
for the url structure must follow the flask routing format
61-
it should be /model/method instead of /model/method/
62-
"""
63-
if name[-1:] == ".":
64-
name = name[:-1]
65-
http_name = str(name).replace(".", "/")
66-
print(http_name)
67-
return http_name
68-
69-
@staticmethod
70-
def get_http_methods(names):
71-
if isinstance(names, list):
72-
methods = []
73-
74-
for name in names:
75-
if "__" not in name:
76-
if name == "index":
77-
methods.append('GET')
78-
elif name == "create":
79-
methods.append('POST')
80-
elif name == "update":
81-
methods.append('PUT')
82-
elif name == "destroy":
83-
methods.append('DELETE')
84-
else:
85-
methods.append('GET')
86-
87-
return methods
88-
else:
89-
raise TypeError("names must be a list")
90-
91-
def model_add_router(self, mod):
92-
if hasattr(mod, '__routes__'):
93-
for route in mod.__routes__:
94-
if inspect.isclass(route[2]):
95-
""" If it's a class it needs to extract the methods by function names
96-
magic functions are excluded
97-
"""
98-
route_name, slug, cls = route
99-
for (fn_name, fn_object) in self.get_cls_fn_members(cls):
100-
if inspect.isfunction(fn_object):
101-
mod.__method__.add_url_rule(
102-
rule=slug,
103-
endpoint=fn_name,
104-
view_func=fn_object,
105-
methods=self.get_http_methods([fn_name]))
106-
else:
107-
raise KeyError("Member is not a function.")
108-
109-
elif inspect.isfunction(route[2]):
110-
route_name, slug, fn, methods = route
111-
112-
mod.__method__.add_url_rule(
113-
rule=slug,
114-
endpoint=fn.__name__,
115-
view_func=fn,
116-
methods=methods)
117-
118-
@staticmethod
119-
def get_cls_fn_members(cls):
120-
return [member for member in inspect.getmembers(cls, predicate=inspect.isfunction)]
121-
122-
def add_blueprint(self, path):
123-
124-
""" find all packages in the current path """
125-
for loader, name, is_pkg in pkgutil.walk_packages(path, prefix="", onerror=None):
126-
""" if module found load module and save all attributes in the module found """
127-
mod = loader.find_module(name).load_module(name)
128-
129-
""" find the attribute method on each module """
130-
if hasattr(mod, '__method__'):
131-
self.model_add_router(mod)
132-
root_module = self.root_path.replace(".", "")
133-
url_prefix_name = str(name).replace(root_module, "")
134-
""" register to the blueprint if method attribute found """
135-
self.__app.register_blueprint(mod.__method__, url_prefix=self.blueprint_name(url_prefix_name))
136-
137-
else:
138-
""" prompt not found notification """
139-
# print('{} has no module attribute method'.format(mod))
140-
pass
27+
PackageExtractor(application=app, path=root_path)

module_router.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import inspect
2+
3+
4+
class ModuleRouter:
5+
def __init__(self, mod): # module
6+
self._module = mod
7+
if self._is_valid_module():
8+
self.model_add_router()
9+
10+
def model_add_router(self):
11+
if hasattr(self._module, '__routes__') and len(self._module.__routes__):
12+
route_type, route_data = self._routing_type(route=self._module.__routes__.pop(0))
13+
if route_type == 'cls':
14+
""" If it's a class it needs to extract the methods by function names
15+
magic functions are excluded
16+
"""
17+
route_name, slug, cls = route_data
18+
self.class_member_route(route=route_data, members=self.get_cls_fn_members(cls))
19+
20+
elif route_type == 'fn':
21+
route_name, slug, fn, methods = route_data
22+
23+
self._module.__method__.add_url_rule(
24+
rule=slug,
25+
endpoint=fn.__name__,
26+
view_func=fn,
27+
methods=methods)
28+
self.model_add_router()
29+
30+
def _is_valid_module(self):
31+
return hasattr(self._module, '__routes__') or hasattr(self._module, '__method__')
32+
33+
@staticmethod
34+
def _routing_type(route):
35+
__type = None
36+
if isinstance(route, tuple):
37+
if len(route) == 3 and inspect.isclass(route[2]):
38+
__type = 'cls'
39+
elif len(route) == 4 and inspect.isfunction(route[2]):
40+
if isinstance(route[3], (list, tuple, set)):
41+
__type = 'fn'
42+
else:
43+
raise TypeError("methods must be a list.")
44+
else:
45+
raise TypeError("Invalid route syntax.")
46+
return __type, route
47+
48+
@staticmethod
49+
def get_http_methods(names):
50+
if isinstance(names, list):
51+
methods = []
52+
53+
for name in names:
54+
if "__" not in name:
55+
if name == "index":
56+
methods.append('GET')
57+
elif name == "create":
58+
methods.append('POST')
59+
elif name == "update":
60+
methods.append('PUT')
61+
elif name == "destroy":
62+
methods.append('DELETE')
63+
else:
64+
methods.append('GET')
65+
66+
return methods
67+
else:
68+
raise TypeError("names must be a list")
69+
70+
@staticmethod
71+
def get_cls_fn_members(cls):
72+
return [member for member in inspect.getmembers(cls, predicate=inspect.isfunction)]
73+
74+
def class_member_route(self, route, members):
75+
if isinstance(members, (list, set)):
76+
if len(members):
77+
(fn_name, fn_object) = members.pop(0)
78+
route_name, slug, cls = route
79+
if inspect.isfunction(fn_object):
80+
self._module.__method__.add_url_rule(
81+
rule=slug,
82+
endpoint=fn_name,
83+
view_func=fn_object,
84+
methods=self.get_http_methods([fn_name]))
85+
else:
86+
raise KeyError("Member is not a function.")
87+
self.class_member_route(route, members)
88+
else:
89+
raise TypeError("members must be a list.")
90+
91+
def register_route(self, app, name):
92+
app.register_blueprint(self._module.__method__, url_prefix=self.blueprint_name(name))
93+
94+
@staticmethod
95+
def blueprint_name(name):
96+
97+
root_module = name.replace(".", "")
98+
99+
name = str(name).replace(root_module, "")
100+
""" set index automatically as home page """
101+
if "index" in name:
102+
name = str(name).replace("index", "")
103+
if "routes" in name:
104+
name = str(name).replace("routes", "")
105+
if "module" in name:
106+
name = str(name).replace("module", "")
107+
108+
""" remove the last . in the string it it ends with a .
109+
for the url structure must follow the flask routing format
110+
it should be /model/method instead of /model/method/
111+
"""
112+
if name[-1:] == ".":
113+
name = name[:-1]
114+
http_name = str(name).replace(".", "/")
115+
116+
return http_name

package_extractor.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import inspect
2+
import pkgutil
3+
from module_router import ModuleRouter
4+
5+
6+
class PackageExtractor:
7+
8+
__packages = None
9+
10+
def __init__(self, application, path):
11+
self.path = path
12+
self.application = application
13+
_packages = self.__inspect_packages(packages=pkgutil.walk_packages(path, prefix="", onerror=None))
14+
self.extract_packages(packages=_packages)
15+
16+
@staticmethod
17+
def __inspect_packages(packages):
18+
if inspect.isgenerator(packages):
19+
packages = [package for package in packages]
20+
21+
if isinstance(packages, (list, set)):
22+
if len(packages):
23+
return packages
24+
else:
25+
raise ValueError("Package does not have an item.")
26+
27+
def extract_packages(self, packages):
28+
if len(packages):
29+
loader, name, is_pkg = packages.pop(0)
30+
""" if module found load module and save all attributes in the module found """
31+
mod = loader.find_module(name).load_module(name)
32+
33+
""" find the attribute method on each module """
34+
if hasattr(mod, '__method__'):
35+
module_router = ModuleRouter(mod)
36+
37+
""" register to the blueprint if method attribute found """
38+
module_router.register_route(app=self.application, name=name)
39+
40+
else:
41+
""" prompt not found notification """
42+
# print('{} has no module attribute method'.format(mod))
43+
pass
44+
self.extract_packages(packages)
45+

0 commit comments

Comments
 (0)