Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
aiscenblue committed Oct 28, 2017
1 parent 0f09377 commit 818ed36
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 115 deletions.
117 changes: 2 additions & 115 deletions core.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import pkgutil
import os
import inspect
from package_extractor import PackageExtractor

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

""" register blueprint to the current path """
self.add_blueprint(root_path)

def directory_path(self, path):

""" get all the list of files and directories """
for file in os.listdir(path):

""" prevent __pycache__ directory or any directory that has __ """
if "__" not in file:
""" get the full path directory """
dir_file = path + '/' + file

""" check is the path is a directory
only directories are picked
"""
if os.path.isdir(dir_file):
""" register blueprint on the directory """
self.add_blueprint(dir_file)

""" find sub directories on each directory found """
self.directory_path(path=dir_file)

@staticmethod
def blueprint_name(name):
""" set index automatically as home page """
if "index" in name:
name = str(name).replace("index", "")
if "routes" in name:
name = str(name).replace("routes", "")

""" remove the last . in the string it it ends with a .
for the url structure must follow the flask routing format
it should be /model/method instead of /model/method/
"""
if name[-1:] == ".":
name = name[:-1]
http_name = str(name).replace(".", "/")
print(http_name)
return http_name

@staticmethod
def get_http_methods(names):
if isinstance(names, list):
methods = []

for name in names:
if "__" not in name:
if name == "index":
methods.append('GET')
elif name == "create":
methods.append('POST')
elif name == "update":
methods.append('PUT')
elif name == "destroy":
methods.append('DELETE')
else:
methods.append('GET')

return methods
else:
raise TypeError("names must be a list")

def model_add_router(self, mod):
if hasattr(mod, '__routes__'):
for route in mod.__routes__:
if inspect.isclass(route[2]):
""" If it's a class it needs to extract the methods by function names
magic functions are excluded
"""
route_name, slug, cls = route
for (fn_name, fn_object) in self.get_cls_fn_members(cls):
if inspect.isfunction(fn_object):
mod.__method__.add_url_rule(
rule=slug,
endpoint=fn_name,
view_func=fn_object,
methods=self.get_http_methods([fn_name]))
else:
raise KeyError("Member is not a function.")

elif inspect.isfunction(route[2]):
route_name, slug, fn, methods = route

mod.__method__.add_url_rule(
rule=slug,
endpoint=fn.__name__,
view_func=fn,
methods=methods)

@staticmethod
def get_cls_fn_members(cls):
return [member for member in inspect.getmembers(cls, predicate=inspect.isfunction)]

def add_blueprint(self, path):

""" find all packages in the current path """
for loader, name, is_pkg in pkgutil.walk_packages(path, prefix="", onerror=None):
""" if module found load module and save all attributes in the module found """
mod = loader.find_module(name).load_module(name)

""" find the attribute method on each module """
if hasattr(mod, '__method__'):
self.model_add_router(mod)
root_module = self.root_path.replace(".", "")
url_prefix_name = str(name).replace(root_module, "")
""" register to the blueprint if method attribute found """
self.__app.register_blueprint(mod.__method__, url_prefix=self.blueprint_name(url_prefix_name))

else:
""" prompt not found notification """
# print('{} has no module attribute method'.format(mod))
pass
PackageExtractor(application=app, path=root_path)
116 changes: 116 additions & 0 deletions module_router.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import inspect


class ModuleRouter:
def __init__(self, mod): # module
self._module = mod
if self._is_valid_module():
self.model_add_router()

def model_add_router(self):
if hasattr(self._module, '__routes__') and len(self._module.__routes__):
route_type, route_data = self._routing_type(route=self._module.__routes__.pop(0))
if route_type == 'cls':
""" If it's a class it needs to extract the methods by function names
magic functions are excluded
"""
route_name, slug, cls = route_data
self.class_member_route(route=route_data, members=self.get_cls_fn_members(cls))

elif route_type == 'fn':
route_name, slug, fn, methods = route_data

self._module.__method__.add_url_rule(
rule=slug,
endpoint=fn.__name__,
view_func=fn,
methods=methods)
self.model_add_router()

def _is_valid_module(self):
return hasattr(self._module, '__routes__') or hasattr(self._module, '__method__')

@staticmethod
def _routing_type(route):
__type = None
if isinstance(route, tuple):
if len(route) == 3 and inspect.isclass(route[2]):
__type = 'cls'
elif len(route) == 4 and inspect.isfunction(route[2]):
if isinstance(route[3], (list, tuple, set)):
__type = 'fn'
else:
raise TypeError("methods must be a list.")
else:
raise TypeError("Invalid route syntax.")
return __type, route

@staticmethod
def get_http_methods(names):
if isinstance(names, list):
methods = []

for name in names:
if "__" not in name:
if name == "index":
methods.append('GET')
elif name == "create":
methods.append('POST')
elif name == "update":
methods.append('PUT')
elif name == "destroy":
methods.append('DELETE')
else:
methods.append('GET')

return methods
else:
raise TypeError("names must be a list")

@staticmethod
def get_cls_fn_members(cls):
return [member for member in inspect.getmembers(cls, predicate=inspect.isfunction)]

def class_member_route(self, route, members):
if isinstance(members, (list, set)):
if len(members):
(fn_name, fn_object) = members.pop(0)
route_name, slug, cls = route
if inspect.isfunction(fn_object):
self._module.__method__.add_url_rule(
rule=slug,
endpoint=fn_name,
view_func=fn_object,
methods=self.get_http_methods([fn_name]))
else:
raise KeyError("Member is not a function.")
self.class_member_route(route, members)
else:
raise TypeError("members must be a list.")

def register_route(self, app, name):
app.register_blueprint(self._module.__method__, url_prefix=self.blueprint_name(name))

@staticmethod
def blueprint_name(name):

root_module = name.replace(".", "")

name = str(name).replace(root_module, "")
""" set index automatically as home page """
if "index" in name:
name = str(name).replace("index", "")
if "routes" in name:
name = str(name).replace("routes", "")
if "module" in name:
name = str(name).replace("module", "")

""" remove the last . in the string it it ends with a .
for the url structure must follow the flask routing format
it should be /model/method instead of /model/method/
"""
if name[-1:] == ".":
name = name[:-1]
http_name = str(name).replace(".", "/")

return http_name
45 changes: 45 additions & 0 deletions package_extractor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import inspect
import pkgutil
from module_router import ModuleRouter


class PackageExtractor:

__packages = None

def __init__(self, application, path):
self.path = path
self.application = application
_packages = self.__inspect_packages(packages=pkgutil.walk_packages(path, prefix="", onerror=None))
self.extract_packages(packages=_packages)

@staticmethod
def __inspect_packages(packages):
if inspect.isgenerator(packages):
packages = [package for package in packages]

if isinstance(packages, (list, set)):
if len(packages):
return packages
else:
raise ValueError("Package does not have an item.")

def extract_packages(self, packages):
if len(packages):
loader, name, is_pkg = packages.pop(0)
""" if module found load module and save all attributes in the module found """
mod = loader.find_module(name).load_module(name)

""" find the attribute method on each module """
if hasattr(mod, '__method__'):
module_router = ModuleRouter(mod)

""" register to the blueprint if method attribute found """
module_router.register_route(app=self.application, name=name)

else:
""" prompt not found notification """
# print('{} has no module attribute method'.format(mod))
pass
self.extract_packages(packages)

0 comments on commit 818ed36

Please sign in to comment.