Skip to content

Commit

Permalink
Docstrings for Extension & ExtensionsMaster
Browse files Browse the repository at this point in the history
Working on documentation with autodoc and docstrings, some more minor improvements in other docs.
  • Loading branch information
MarekSuchanek committed Feb 2, 2017
1 parent 9e1ef12 commit ca37059
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 10 deletions.
2 changes: 1 addition & 1 deletion docs/api/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ API
.. toctree::
:maxdepth: 3

repocribro
repocribro/extending.rst
4 changes: 0 additions & 4 deletions docs/api/repocribro.rst

This file was deleted.

22 changes: 22 additions & 0 deletions docs/api/repocribro/extending.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
repocribro.extending
====================

Extension
---------

.. autoclass:: repocribro.extending.Extension
:members:
:private-members:
:special-members: __init__
:undoc-members:
:show-inheritance:

ExtensionsMaster
----------------

.. autoclass:: repocribro.extending.ExtensionsMaster
:members:
:private-members:
:special-members: __init__
:undoc-members:
:show-inheritance:
2 changes: 1 addition & 1 deletion docs/credits.rst
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Credits
=======

This project was created as final semester work for the subject `MI-PYT (Advanced Python)`_
This project was created as final semester work for the awesome subject `MI-PYT (Advanced Python)`_
taught at the `Faculty of Information Technology`_, `Czech Technical
University in Prague`_ (FIT CTU) by `@hroncok`_ and `@encukou`_.

Expand Down
98 changes: 94 additions & 4 deletions repocribro/extending/extension.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
from .helpers import ExtensionView


def no_models():
return []


class Extension:
"""Generic **repocribro** extension class
It serves as base extension which does nothing but has prepared
all the attributes and methods needed. Particular real extensions
can override those attributes and methods to make so behavior
and extend repocribro. It also provides some useful methods to
those subclasses.
:var NAME: Name of extension
:var CATEGORY: Category of extension (basic, security, data, ...)
:var AUTHOR: Author(s) of extension
:var ADMIN_URL: Administration URL within site (best via url_for)
:var HOME_URL: Homepage url of extension (rtd, pocoo, ...)
:var GH_URL: GitHub url of extension project
"""
NAME = 'unknown'
CATEGORY = ''
AUTHOR = ''
Expand All @@ -14,47 +25,126 @@ class Extension:
GH_URL = None

def __init__(self, app, db, *args, **kwargs):
"""Inits the basic two parts of repocribro - flask app and DB
:param app: Flask application of repocribro
:type app: ``flask.Flask``
:param db: SQLAlchemy database of repocribro
:type db: ``flask_sqlalchemy.SQLAlchemy``
:param args: not used
:param kwargs: not used
"""
self.app = app
self.db = db

def call(self, hook_name, default, *args, **kwargs):
"""Call the operation via hook name
:param hook_name: Name of hook to be called
:type hook_name: str
:param default: Default return value if hook operation not found
:param args: Positional args to be passed to the hook operation
:param kwargs: Keywords args to be passed to the hook operation
:return: Result of the operation on the requested hook
"""
operation = getattr(self, hook_name, None)
if callable(operation):
return operation(*args, **kwargs)
else:
return default

def register_filters_from_dict(self, filters):
"""Registering functions as Jinja filters
:param filters: Dictionary where key is name of filter and
value is the function serving as filter
:type filters: dict of str: function
"""
for name, func in filters.items():
self.app.jinja_env.filters[name] = func

def register_blueprints_from_list(self, blueprints):
"""Registering Flask blueprints to the app
:param blueprints: List of Flask blueprints to be registered
:type blueprints: ``list`` of ``flask.blueprint``
"""
for blueprint in blueprints:
self.app.register_blueprint(blueprint)

@staticmethod
def provide_models():
"""Extension can provide (DB) models to the app by this method
:return: List of models provided by extension
:rtype: list of ``db.Model``
"""
return []

@staticmethod
def provide_blueprints():
"""Extension can provide Flask blueprints to the app by this method
:return: List of Flask blueprints provided by extension
:rtype: list of ``flask.blueprint``
"""
return []

@staticmethod
def provide_filters():
"""Extension can provide Jinja filters to the app by this method
:return: Dictionary with name + function/filter pairs
:rtype: dict of str: function
"""
return {}

def init_models(self, *args, **kwargs):
"""Hook operation for initiating the models and registering them
within db
:param args: not used
:param kwargs: not used
:return: None
"""
return self.provide_models()

def init_blueprints(self, *args, **kwargs):
"""Hook operation for initiating the blueprints and registering them
within repocribro Flask app
:param args: not used
:param kwargs: not used
"""
self.register_blueprints_from_list(self.provide_blueprints())

def init_filters(self, *args, **kwargs):
"""Hook operation for initiating the Jinja filters and registering them
within Jinja env of repocribro Flask app
:param args: not used
:param kwargs: not used
"""
self.register_filters_from_dict(self.provide_filters())

def introduce(self, *args, **kwargs):
"""Hook operation for getting short introduction of extension (mostly
for debug/log purpose)
:param args: not used
:param kwargs: not used
:return: Name of the extension
:rtype: str
"""
return getattr(self, 'NAME', 'unknown')

def view_admin_extensions(self, *args, **kwargs):
"""Hook operation for getting view model of the extension in order
to show it in the administration of app
:param args: not used
:param kwargs: not used
:return: Extensions view for this extension
:rtype: ``repocribro.extending.helpers.ExtensionView``
"""
return ExtensionView.from_class(self.__class__)
30 changes: 30 additions & 0 deletions repocribro/extending/extension_master.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,39 @@


class ExtensionsMaster:
"""Collector & master of Extensions
Extension master finds and holds all the **repocribro** extensions
and is used for calling operations on them and collecting the results.
:var ENTRYPOINT_GROUP: String used for looking up the extensions
:var LOAD_ERROR_MSG: Error message mask for extension load error
"""
ENTRYPOINT_GROUP = 'repocribro.ext'
LOAD_ERROR_MSG = 'Extension "{}" ({}) is not making an Extension ' \
'(sub)class instance. It will be ignored!'

@classmethod
def _collect_extensions(cls, name=None):
"""Method for selecting extensions within ``ENTRYPOINT_GROUP``
:param name: Can be used to select single entrypoint/extension
:type name: str
:return: Generator of selected entry points
:rtype: ``pkg_resources.WorkingSet.iter_entry_points``
"""
return pkg_resources.iter_entry_points(
group=cls.ENTRYPOINT_GROUP, name=name
)

# TODO: there might be some problem with ordering of extensions
def __init__(self, *args, **kwargs):
"""Collects all the extensions to be mantained by this object
:param args: positional args to be passed to extensions
:param kwargs: keywords args to be passed to extensions
"""
entry_points = self._collect_extensions()
self.exts = []
for ep in entry_points:
Expand All @@ -30,5 +51,14 @@ def __init__(self, *args, **kwargs):
self.exts.append(e)

def call(self, hook_name, default=None, *args, **kwargs):
"""Call the hook on all extensions registered
:param hook_name: Name of hook to be called
:type hook_name: str
:param default: Default return value if hook operation not found
:param args: Positional args to be passed to the hook operation
:param kwargs: Keywords args to be passed to the hook operation
:return: Result of the operation on the requested hook
"""
return [ext.call(hook_name, default, args, **kwargs)
for ext in self.exts]

0 comments on commit ca37059

Please sign in to comment.