From 72316b0f0ab5636994998c0f34ddf6b020bc1d36 Mon Sep 17 00:00:00 2001 From: Roland Haroutiounian Date: Fri, 24 Mar 2017 15:40:28 +0100 Subject: [PATCH] Documentation on the lodel.plugin.datasource_plugin et lodel.plugin.exceptions modules --- lodel/plugin/datasource_plugin.py | 203 +++++++++++++++--------------- lodel/plugin/exceptions.py | 3 + 2 files changed, 108 insertions(+), 98 deletions(-) diff --git a/lodel/plugin/datasource_plugin.py b/lodel/plugin/datasource_plugin.py index 024224a..1a8c6cf 100644 --- a/lodel/plugin/datasource_plugin.py +++ b/lodel/plugin/datasource_plugin.py @@ -1,3 +1,8 @@ +## @package lodel.plugin.datasource_plugin Datasource plugins management module +# +# It contains the base classes for all the datasource plugins that could be added to Lodel + + from lodel.context import LodelContext LodelContext.expose_modules(globals(), { 'lodel.plugin.plugins': ['Plugin'], @@ -7,58 +12,61 @@ LodelContext.expose_modules(globals(), { 'lodel.exceptions': ['LodelException', 'LodelExceptions', 'LodelFatalError', 'DataNoneValid', 'FieldValidationError']}) +## @brief The plugin type that is used in the global settings of Lodel _glob_typename = 'datasource' -##@brief Datasource class in plugins HAVE TO inherit from this abstract class +## @brief Main abstract class from which the plugins' datasource classes must inherit. class AbstractDatasource(object): - ##@brief Trigger LodelFatalError when abtract method called + ## @brief Trigger LodelFatalError when abtract method called + # @throw LodelFatalError if there is an attempt to instanciate an object from this class @staticmethod def _abs_err(): raise LodelFatalError("This method is abstract and HAVE TO be \ reimplemented by plugin datasource child class") - ##@brief The constructor + ## + # @param *conn_args + # @param **conn_kwargs def __init__(self, *conn_args, **conn_kwargs): self._abs_err() - ##@brief Provide a new uniq numeric ID - #@param emcomp LeObject subclass (not instance) : To know on wich things we - #have to be uniq - #@return an integer + ## @brief Provides a new uniq numeric ID + # @param emcomp LeObject subclass (not instance) : defines against which objects type the id should be unique + # @return int def new_numeric_id(self, emcomp): self._abs_err() - ##@brief returns a selection of documents from the datasource - #@param target Emclass - #@param field_list list - #@param filters list : List of filters - #@param rel_filters list : List of relational filters - #@param order list : List of column to order. ex: order = [('title', 'ASC'),] - #@param group list : List of tupple representing the column to group together. ex: group = [('title', 'ASC'),] - #@param limit int : Number of records to be returned - #@param offset int: used with limit to choose the start record - #@param instanciate bool : If true, the records are returned as instances, else they are returned as dict - #@return list + ## @brief Returns a selection of documents from the datasource + # @param target Emclass : class of the documents + # @param field_list list : fields to get from the datasource + # @param filters list : List of filters + # @param rel_filters list : List of relational filters (default value : None) + # @param order list : List of column to order. ex: order = [('title', 'ASC'),] (default value : None) + # @param group list : List of tupple representing the column to group together. ex: group = [('title', 'ASC'),] (default value : None) + # @param limit int : Number of records to be returned (default value None) + # @param offset int: used with limit to choose the start record (default value : 0) + # @param instanciate bool : If true, the records are returned as instances, else they are returned as dict (default value : True) + # @return list def select(self, target, field_list, filters, rel_filters=None, order=None, group=None, limit=None, offset=0, instanciate=True): self._abs_err() - ##@brief Deletes records according to given filters - #@param target Emclass : class of the record to delete - #@param filters list : List of filters - #@param relational_filters list : List of relational filters - #@return int : number of deleted records + ## @brief Deletes records according to given filters + # @param target Emclass : class of the record to delete + # @param filters list : List of filters + # @param relational_filters list : List of relational filters + # @return int : number of deleted records def delete(self, target, filters, relational_filters): self._abs_err() ## @brief updates records according to given filters - #@param target Emclass : class of the object to insert - #@param filters list : List of filters - #@param relational_filters list : List of relational filters - #@param upd_datas dict : datas to update (new values) - #@return int : Number of updated records + # @param target Emclass : class of the object to insert + # @param filters list : List of filters + # @param relational_filters list : List of relational filters + # @param upd_datas dict : datas to update (new values) + # @return int : Number of updated records def update(self, target, filters, relational_filters, upd_datas): self._abs_err() @@ -77,22 +85,21 @@ reimplemented by plugin datasource child class") self._abs_err() -##@brief Designed to handles datasources plugins +## @brief Represents a Datasource plugin # -#A datasource provide data access to LeAPI typically a connector on a DB -#or an API +# It will provide an access to a data collection to LeAPI (i.e. database connector, API ...). # -#Provide methods to initialize datasource attribute in LeAPI LeObject child -#classes (see @ref leapi.leobject.LeObject._init_datasources() ) +# It provides the methods needed to initialize the datasource attribute in LeAPI LeObject child +# classes (see @ref leapi.leobject.LeObject._init_datasources() ) # -#@note For the moment implementation is done with a retro-compatibilities -#priority and not with a convenience priority. -#@todo Refactor and rewrite lodel2 datasource handling -#@todo Write abstract classes for Datasource and MigrationHandler !!! +# @note For the moment implementation is done with a retro-compatibilities priority and not with a convenience priority. +# @todo Refactor and rewrite lodel2 datasource handling +# @todo Write abstract classes for Datasource and MigrationHandler !!! class DatasourcePlugin(Plugin): _type_conf_name = _glob_typename - ##@brief Stores confspecs indicating where DatasourcePlugin list is stored + + ## @brief Stores confspecs indicating where DatasourcePlugin list is stored _plist_confspecs = { 'section': 'lodel2', 'key': 'datasource_connectors', @@ -104,15 +111,17 @@ class DatasourcePlugin(Plugin): 'none_is_valid': False}) } - ##@brief Construct a DatasourcePlugin - #@param name str : plugin name - #@see plugins.Plugin + ## + # @param name str : plugin's name + # @see plugins.Plugin def __init__(self, name): super().__init__(name) self.__datasource_cls = None - ##@brief Accessor to the datasource class - #@return A python datasource class + ## @brief Returns an accessor to the datasource class + # @return A python datasource class + # @throw DatasourcePluginError if the plugin's datasource class is not a child of + # @ref lodel.plugin.datasource_plugin.AbstractDatasource def datasource_cls(self): if self.__datasource_cls is None: self.__datasource_cls = self.loader_module().Datasource @@ -122,17 +131,15 @@ class DatasourcePlugin(Plugin): lodel.plugin.datasource_plugin.AbstractDatasource" % (self.name)) return self.__datasource_cls - ##@brief Accessor to migration handler class - #@return A python migration handler class + ## @brief Returns an accessor to migration handler class + # @return A python migration handler class def migration_handler_cls(self): return self.loader_module().migration_handler_class() - ##@brief Return an initialized Datasource instance - #@param ds_name str : The name of the datasource to instanciate - #@param ro bool - #@return A properly initialized Datasource instance - #@throw SettingsError if an error occurs in settings - #@throw DatasourcePluginError for various errors + ## @brief Returns an initialized Datasource instance + # @param ds_name str : The name of the datasource to instanciate + # @param ro bool : indicates if it will be in read only mode, else it will be in write only mode + # @return A properly initialized Datasource instance @classmethod def init_datasource(cls, ds_name, ro): plugin_name, ds_identifier = cls.plugin_name(ds_name, ro) @@ -140,9 +147,10 @@ lodel.plugin.datasource_plugin.AbstractDatasource" % (self.name)) ds_cls = cls.get_datasource(plugin_name) return ds_cls(**ds_conf) - ##@brief Return an initialized MigrationHandler instance - #@param ds_name str : The datasource name - #@return A properly initialized MigrationHandler instance + ## @brief Returns an initialized MigrationHandler instance + # @param ds_name str : The datasource name + # @return A properly initialized MigrationHandler instance + # @throw PluginError if a read only datasource instance was given to the migration handler. @classmethod def init_migration_handler(cls, ds_name): plugin_name, ds_identifier = cls.plugin_name(ds_name, False) @@ -156,13 +164,12 @@ migration handler !!!") return mh_cls(**ds_conf) - ##@brief Given a datasource name returns a DatasourcePlugin name - #@param ds_name str : datasource name - #@param ro bool : if true consider the datasource as readonly - #@return a DatasourcePlugin name - #@throw PluginError if datasource name not found - #@throw DatasourcePermError if datasource is read_only but ro flag arg is - #false + ## @brief Given a datasource name returns a DatasourcePlugin name + # @param ds_name str : datasource name + # @param ro bool : if true consider the datasource as readonly + # @return a DatasourcePlugin name + # @throw DatasourcePluginError if the given datasource is unknown or not configured, or if there is a conflict in its "read-only" property (between the instance and the settings). + # @throw SettingsError if there are misconfigured datasource settings. @staticmethod def plugin_name(ds_name, ro): LodelContext.expose_modules(globals(), { @@ -195,11 +202,11 @@ True found in settings for datasource '%s'" % ds_name) DS_PLUGIN_NAME.DS_INSTANCE_NAME. But got %s" % ds_identifier) return res - ##@brief Try to fetch a datasource configuration - #@param ds_identifier str : datasource name - #@param ds_plugin_name : datasource plugin name - #@return a dict containing datasource initialisation options - #@throw NameError if a datasource plugin or instance cannot be found + ## @brief Returns a datasource's configuration + # @param ds_identifier str : datasource name + # @param ds_plugin_name : datasource plugin name + # @return a dict containing datasource initialisation options + # @throw DatasourcePluginError if a datasource plugin or instance cannot be found @staticmethod def _get_ds_connection_conf(ds_identifier,ds_plugin_name): LodelContext.expose_modules(globals(), { @@ -216,56 +223,55 @@ DS_PLUGIN_NAME.DS_INSTANCE_NAME. But got %s" % ds_identifier) ds_conf = getattr(ds_conf, ds_identifier) return {k: getattr(ds_conf,k) for k in ds_conf._fields } - ##@brief DatasourcePlugin instance accessor - #@param ds_name str : plugin name - #@return a DatasourcePlugin instance - #@throw PluginError if no plugin named ds_name found - #@throw PluginTypeError if ds_name ref to a plugin that is not a - #DatasourcePlugin + ## @brief Returns a DatasourcePlugin instance from a plugin's name + # @param ds_name str : plugin name + # @return DatasourcePlugin + # @throw PluginError if no plugin named ds_name found (@see lodel.plugin.plugins.Plugin) + # @throw PluginTypeError if ds_name ref to a plugin that is not a DatasourcePlugin @classmethod def get(cls, ds_name): - pinstance = super().get(ds_name) #Will raise PluginError if bad name + pinstance = super().get(ds_name) # Will raise PluginError if bad name if not isinstance(pinstance, DatasourcePlugin): raise PluginTypeErrror("A name of a DatasourcePlugin was excepted \ but %s is a %s" % (ds_name, pinstance.__class__.__name__)) return pinstance - ##@brief Return a datasource class given a datasource name - #@param ds_plugin_name str : datasource plugin name - #@throw PluginError if ds_name is not an existing plugin name - #@throw PluginTypeError if ds_name is not the name of a DatasourcePlugin + ## @brief Returns a datasource class given a datasource name + # @param ds_plugin_name str : datasource plugin name + # @return Datasource class @classmethod def get_datasource(cls, ds_plugin_name): return cls.get(ds_plugin_name).datasource_cls() - ##@brief Given a plugin name returns a migration handler class - #@param ds_plugin_name str : a datasource plugin name + ## @brief Returns a migration handler class, given a plugin name + # @param ds_plugin_name str : a datasource plugin name + # @return MigrationHandler class @classmethod def get_migration_handler(cls, ds_plugin_name): return cls.get(ds_plugin_name).migration_handler_cls() -##@page lodel2_datasources Lodel2 datasources +## @page lodel2_datasources Lodel2 datasources # -#@par lodel2_datasources_intro Intro +# @par lodel2_datasources_intro Introduction # A single lodel2 website can interact with multiple datasources. This page -# aims to describe configuration & organisation of datasources in lodel2. +# aims to describe configuration and organisation of datasources in lodel2. # Each object is attached to a datasource. This association is done in the -# editorial model, the datasource is identified by a name. +# editorial model, in which the datasource is identified by its name. # -#@par Datasources declaration -# To define a datasource you have to write something like this in confs file : -#
-#[lodel2.datasources.DATASOURCE_NAME]
-#identifier = DATASOURCE_FAMILY.SOURCE_NAME
-#
-# See below for DATASOURCE_FAMILY & SOURCE_NAME +# @par Datasources declaration +# To define a datasource you have to write something like this in configuration file : +#
+# [lodel2.datasources.DATASOURCE_NAME]
+# identifier = DATASOURCE_FAMILY.SOURCE_NAME
+# 
+# See below for DATASOURCE_FAMILY & SOURCE_NAME # -#@par Datasources plugins -# Each datasource family is a plugin ( -#@ref plugin_doc "More informations on plugins" ). For example mysql or a -#mongodb plugins. Here is the CONFSPEC variable templates for datasources -#plugin +# @par Datasources plugins +# Each datasource family is a plugin ( @ref plugin_doc "More informations on plugins" ). +# For example mysql or a mongodb plugins. \n +# +# Here is the CONFSPEC variable templates for datasources plugin #
 #CONFSPEC = {
 #                'lodel2.datasource.example.*' : {
@@ -275,7 +281,8 @@ but %s is a %s" % (ds_name, pinstance.__class__.__name__))
 #                }
 #}
 #
-#MySQL example +# +#MySQL example \n #
 #CONFSPEC = {
 #                'lodel2.datasource.mysql.*' : {
@@ -291,8 +298,8 @@ but %s is a %s" % (ds_name, pinstance.__class__.__name__))
 #}
 #
# -#@par Configuration example -#
+# @par Configuration example
+# 
 # [lodel2.datasources.main]
 # identifier = mysql.Core
 # [lodel2.datasources.revues_write]
diff --git a/lodel/plugin/exceptions.py b/lodel/plugin/exceptions.py
index 90904d1..6e8155f 100644
--- a/lodel/plugin/exceptions.py
+++ b/lodel/plugin/exceptions.py
@@ -1,3 +1,6 @@
+## @package lodel.plugin.exceptions Plugin management specific exceptions
+
+
 class PluginError(Exception):
     pass