mirror of
https://github.com/yweber/lodel2.git
synced 2026-04-09 19:59:58 +02:00
Deleting old stuff + bugfix in install/Makefile and in install/lodel_admin.py
This commit is contained in:
parent
d24b7a92d6
commit
006b0c4bc0
14 changed files with 8 additions and 603 deletions
6
Doxyfile
6
Doxyfile
|
|
@ -51,7 +51,7 @@ PROJECT_BRIEF = "Logiciel d'edition electronique v2"
|
|||
# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
|
||||
# to the output directory.
|
||||
|
||||
PROJECT_LOGO = "doc/img/openedition_logo.png"
|
||||
PROJECT_LOGO = doc/img/openedition_logo.png
|
||||
|
||||
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
|
||||
# into which the generated documentation will be written. If a relative path is
|
||||
|
|
@ -763,7 +763,7 @@ WARN_LOGFILE =
|
|||
# spaces.
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT =
|
||||
INPUT = .
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
|
|
@ -909,7 +909,7 @@ IMAGE_PATH = doc/img
|
|||
# code is scanned, but not when the output code is generated. If lines are added
|
||||
# or removed, the anchors will not be placed correctly.
|
||||
|
||||
INPUT_FILTER = "doxypy"
|
||||
INPUT_FILTER = doxypy
|
||||
|
||||
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
|
||||
# basis. Doxygen will compare the file name with each pattern and apply the
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
## @package install Contains the base files for a lodel2 instance
|
||||
#
|
||||
# An instance is composed of multiple things :
|
||||
#- a configuration directory ( @ref install/conf.d/ )
|
||||
#- a bootstraping script ( @ref install/loader.py )
|
||||
#- an utilities source code ( @ref install/lodel_admin.py )
|
||||
#- a Makefile that allow to run common instance operations (only refresh the dynamic code for now)
|
||||
Binary file not shown.
|
|
@ -6,4 +6,4 @@ dyncode:
|
|||
$(python) -c 'import lodel_admin; lodel_admin.refresh_dyncode()'
|
||||
|
||||
init_all_dbs:
|
||||
$(python) -c 'import lodel_admin; lodel_admin.init_all_dbs()'
|
||||
$(python) -c 'import lodel_admin; lodel_admin.init_all_dbs()'
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import loader
|
|||
|
||||
from lodel.settings import Settings
|
||||
from lodel import logger
|
||||
from .leapi_dyncode import *
|
||||
|
||||
## @brief Utility method to generate python code given an emfile and a
|
||||
# translator
|
||||
|
|
@ -48,5 +47,6 @@ def refresh_dyncode():
|
|||
|
||||
|
||||
def init_all_dbs():
|
||||
import leapi_dyncode
|
||||
#TODO
|
||||
pass
|
||||
|
|
@ -1 +0,0 @@
|
|||
__author__ = 'roland'
|
||||
|
|
@ -1 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
class GenericDataSource(object):
|
||||
|
||||
def __init__(self, *conn_args, **conn_kwargs):
|
||||
self.conn_args = conn_args
|
||||
self.conn_kwargs = conn_kwargs
|
||||
|
||||
## @brief returns a selection of documents from the datasource
|
||||
# @param target_cls 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
|
||||
def select(self, target_cls, field_list, filters, rel_filters=None, order=None, group=None, limit=None, offset=0,
|
||||
instanciate=True):
|
||||
pass
|
||||
|
||||
## @brief Deletes one record defined by its uid
|
||||
# @param target_cls Emclass : class of the record to delete
|
||||
# @param uid dict|list : a dictionary of fields and values composing the unique identifier of the record or a list of several dictionaries
|
||||
# @return int : number of deleted records
|
||||
def delete(self, target_cls, uid):
|
||||
pass
|
||||
|
||||
## @brief updates one or a list of records
|
||||
# @param target_cls Emclass : class of the object to insert
|
||||
# @param uids list : list of uids to update
|
||||
# @param datas dict : datas to update (new values)
|
||||
# @return int : Number of updated records
|
||||
def update(self, target_cls, uids, **datas):
|
||||
pass
|
||||
|
||||
## @brief Inserts a record in a given collection
|
||||
# @param target_cls Emclass : class of the object to insert
|
||||
# @param datas dict : datas to insert
|
||||
# @return bool
|
||||
def insert(self, target_cls, **datas):
|
||||
pass
|
||||
|
||||
## @brief Inserts a list of records in a given collection
|
||||
# @param target_cls Emclass : class of the objects inserted
|
||||
# @param datas_list
|
||||
# @return list : list of the inserted records' ids
|
||||
def insert_multi(self, target_cls, datas_list):
|
||||
pass
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
## @package lodel.datasource.migrationhandler.generic
|
||||
# @brief A generic migration handler
|
||||
#
|
||||
# According to it, every moditification is possible
|
||||
#
|
||||
|
||||
|
||||
## Manage model changes
|
||||
class GenericMigrationHandler(object):
|
||||
|
||||
def __init__(self, debug=False):
|
||||
self.debug = debug
|
||||
|
||||
## @brief Records a change in the EditorialModel and indicates whether or not it is possible to make it
|
||||
# @note The states (initial_state and new_state) contains only fields that changes
|
||||
def register_change(self, em, uid, initial_state, new_state):
|
||||
if self.debug:
|
||||
print("\n##############")
|
||||
print("GenericMigrationHandler debug. Changes for component with uid %s :" % uid)
|
||||
if initial_state is None:
|
||||
print("Component creation (uid = %s): \n\t" % uid, new_state)
|
||||
elif new_state is None:
|
||||
print("Component deletion (uid = %s): \n\t" % uid, initial_state)
|
||||
else:
|
||||
field_list = set(initial_state.keys()).union(set(new_state.keys()))
|
||||
for field_name in field_list:
|
||||
str_chg = "\t%s " % field_name
|
||||
if field_name in initial_state:
|
||||
str_chg += "'" + str(initial_state[field_name]) + "'"
|
||||
else:
|
||||
str_chg += " creating "
|
||||
str_chg += " => "
|
||||
if field_name in new_state:
|
||||
str_chg += "'" + str(new_state[field_name]) + "'"
|
||||
else:
|
||||
str_chg += " deletion "
|
||||
print(str_chg)
|
||||
|
||||
print("##############\n")
|
||||
|
||||
## @brief Not usefull for the moment
|
||||
def register_model_state(self, em, state_hash):
|
||||
if self.debug:
|
||||
print("New EditorialModel state registered : '%s'" % state_hash)
|
||||
|
|
@ -1,135 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import bson
|
||||
from bson.son import SON
|
||||
from collections import OrderedDict
|
||||
import pymongo
|
||||
# from pymongo import MongoClient
|
||||
from pymongo.errors import BulkWriteError
|
||||
import urllib
|
||||
|
||||
import lodel.datasource.mongodb.utils as utils
|
||||
|
||||
from lodel.datasource.generic.datasource import GenericDataSource
|
||||
|
||||
|
||||
class MongoDbDataSourceError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class MongoDbDataSource(GenericDataSource):
|
||||
|
||||
## @brief Instanciates a Database object given a connection name
|
||||
# @param connection_name str
|
||||
def __init__(self, connection_name='default'):
|
||||
self.database = utils.mongodbconnect(connection_name)
|
||||
|
||||
## @brief returns a selection of documents from the datasource
|
||||
# @param target_cls 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 used as "group by" fields. 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
|
||||
# @todo Implement the relations
|
||||
def select(self, target_cls, field_list, filters, rel_filters=None, order=None, group=None, limit=None, offset=0,
|
||||
instanciate=True):
|
||||
collection_name = utils.object_collection_name(target_cls.__class__)
|
||||
collection = self.database[collection_name]
|
||||
query_filters = utils.parse_query_filters(filters)
|
||||
query_result_ordering = utils.parse_query_order(order) if order is not None else None
|
||||
results_field_list = None if len(field_list) == 0 else field_list
|
||||
limit = limit if limit is not None else 0
|
||||
|
||||
if group is None:
|
||||
cursor = collection.find(
|
||||
filter=query_filters,
|
||||
projection=results_field_list,
|
||||
skip=offset,
|
||||
limit=limit,
|
||||
sort=query_result_ordering
|
||||
)
|
||||
else:
|
||||
pipeline = list()
|
||||
unwinding_list = list()
|
||||
grouping_dict = OrderedDict()
|
||||
sorting_list = list()
|
||||
for group_param in group:
|
||||
field_name = group_param[0]
|
||||
field_sort_option = group_param[1]
|
||||
sort_option = utils.MONGODB_SORT_OPERATORS_MAP[field_sort_option]
|
||||
unwinding_list.append({'$unwind': '$%s' % field_name})
|
||||
grouping_dict[field_name] = '$%s' % field_name
|
||||
sorting_list.append((field_name, sort_option))
|
||||
|
||||
sorting_list.extends(query_result_ordering)
|
||||
|
||||
pipeline.append({'$match': query_filters})
|
||||
if results_field_list is not None:
|
||||
pipeline.append({'$project': SON([{field_name: 1} for field_name in field_list])})
|
||||
pipeline.extend(unwinding_list)
|
||||
pipeline.append({'$group': grouping_dict})
|
||||
pipeline.extend({'$sort': SON(sorting_list)})
|
||||
if offset > 0:
|
||||
pipeline.append({'$skip': offset})
|
||||
if limit is not None:
|
||||
pipeline.append({'$limit': limit})
|
||||
|
||||
results = list()
|
||||
for document in cursor:
|
||||
results.append(document)
|
||||
|
||||
return results
|
||||
|
||||
## @brief Deletes one record defined by its uid
|
||||
# @param target_cls Emclass : class of the record to delete
|
||||
# @param uid dict|list : a dictionary of fields and values composing the unique identifier of the record or a list of several dictionaries
|
||||
# @return int : number of deleted records
|
||||
# @TODO Implement the error management
|
||||
def delete(self, target_cls, uid):
|
||||
if isinstance(uid, dict):
|
||||
uid = [uid]
|
||||
collection_name = utils.object_collection_name(target_cls.__class__)
|
||||
collection = self.database[collection_name]
|
||||
result = collection.delete_many(uid)
|
||||
return result.deleted_count
|
||||
|
||||
## @brief updates one or a list of records
|
||||
# @param target_cls Emclass : class of the object to insert
|
||||
# @param uids list : list of uids to update
|
||||
# @param datas dict : datas to update (new values)
|
||||
# @return int : Number of updated records
|
||||
# @todo check if the values need to be parsed
|
||||
def update(self, target_cls, uids, **datas):
|
||||
if not isinstance(uids, list):
|
||||
uids = [uids]
|
||||
collection_name = utils.object_collection_name(target_cls.__class__)
|
||||
collection = self.database[collection_name]
|
||||
results = collection.update_many({'uid': {'$in': uids}}, datas)
|
||||
return results.modified_count()
|
||||
|
||||
## @brief Inserts a record in a given collection
|
||||
# @param target_cls Emclass : class of the object to insert
|
||||
# @param datas dict : datas to insert
|
||||
# @return bool
|
||||
# @TODO Implement the error management
|
||||
def insert(self, target_cls, **datas):
|
||||
collection_name = utils.object_collection_name(target_cls.__class__)
|
||||
collection = self.database[collection_name]
|
||||
result = collection.insert_one(datas)
|
||||
return len(result.inserted_id)
|
||||
|
||||
## @brief Inserts a list of records in a given collection
|
||||
# @param target_cls Emclass : class of the objects inserted
|
||||
# @param datas_list
|
||||
# @return list : list of the inserted records' ids
|
||||
# @TODO Implement the error management
|
||||
def insert_multi(self, target_cls, datas_list):
|
||||
collection_name = utils.object_collection_name(target_cls.__class__)
|
||||
collection = self.database[collection_name]
|
||||
result = collection.insert_many(datas_list)
|
||||
return len(result.inserted_ids)
|
||||
|
|
@ -1,164 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import datetime
|
||||
|
||||
from lodel.leapi.datahandlers.base_classes import DataHandler
|
||||
from lodel.datasource.generic.migrationhandler import GenericMigrationHandler
|
||||
import lodel.datasource.mongodb.utils as utils
|
||||
from lodel.editorial_model.components import EmClass, EmField
|
||||
from lodel.editorial_model.model import EditorialModel
|
||||
|
||||
class MigrationHandlerChangeError(Exception):
|
||||
pass
|
||||
|
||||
class MongoDbMigrationHandler(GenericMigrationHandler):
|
||||
|
||||
COMMANDS_IFEXISTS_DROP = 'drop'
|
||||
COMMANDS_IFEXISTS_NOTHING = 'nothing'
|
||||
|
||||
INIT_COLLECTIONS_NAMES = ['object', 'relation', 'entitie', 'person', 'text', 'entry']
|
||||
|
||||
## @brief constructs a MongoDbMigrationHandler
|
||||
# @param conn_args dict : a dictionary containing the connection options
|
||||
# @param **kwargs : extra arguments
|
||||
def __init__(self, conn_args=None, **kwargs):
|
||||
|
||||
if conn_args is None:
|
||||
conn_args = utils.get_connection_args()
|
||||
|
||||
self.connection_name = conn_args['name']
|
||||
self.database = utils.mongodbconnect(self.connection_name)
|
||||
|
||||
# TODO : get the following parameters in the settings ?
|
||||
migrationhandler_settings = {'dry_run': False, 'foreign_keys': True, 'drop_if_exists': False}
|
||||
|
||||
self.dryrun = kwargs['dryrun'] if 'dryrun' in kwargs else migrationhandler_settings['dry_run']
|
||||
self.foreign_keys = kwargs['foreign_keys'] if 'foreign_keys' in kwargs else migrationhandler_settings['foreign_keys']
|
||||
self.drop_if_exists = kwargs['drop_if_exists'] if 'drop_if_exists' in kwargs else migrationhandler_settings['drop_if_exists']
|
||||
|
||||
self._install_collections()
|
||||
|
||||
def _install_collections(self):
|
||||
for collection_name in MongoDbMigrationHandler.INIT_COLLECTIONS_NAMES:
|
||||
collection_to_create = "%s%s" % ('class_', collection_name)
|
||||
self._create_collection(collection_name=collection_to_create)
|
||||
|
||||
## @brief Performs a change in the EditorialModel and indicates
|
||||
# @note The states contains only the changing fields in the form of a dict : {field_name1: fieldvalue1, ...}
|
||||
# @param model EditorialModel
|
||||
# @param uid str : the uid of the changing component
|
||||
# @param initial_state dict|None: dict representing the original state, None means the component will be created
|
||||
# @param new_state dict|None: dict representing the new state, None means the component will be deleted
|
||||
def register_change(self, model, uid, initial_state, new_state):
|
||||
if initial_state is not None and new_state is not None:
|
||||
if initial_state is None:
|
||||
state_change = 'new'
|
||||
elif new_state is None:
|
||||
state_change = 'del'
|
||||
else:
|
||||
state_change = 'upgrade'
|
||||
|
||||
component_class_name = model.classes(uid).__class__.name
|
||||
handler_func(component_class_name.lower() + '_' + state_change)
|
||||
if hasattr(self, handler_func):
|
||||
getattr(self, handler_func)(model, uid, initial_state, new_state)
|
||||
else:
|
||||
pass # TODO manage the case where no state at all was given
|
||||
|
||||
def register_model_state(self, em, state_hash):
|
||||
pass
|
||||
|
||||
## @brief creates a new collection corresponding to a given uid
|
||||
def emclass_new(self, model, uid, initial_state, new_state):
|
||||
emclass = model.classes(uid)
|
||||
if not isinstance(emclass, EmClass):
|
||||
raise ValueError("The given uid is not an EmClass uid")
|
||||
collection_name = utils.object_collection_name(emclass)
|
||||
self._create_collection(collection_name)
|
||||
|
||||
## @brief deletes a collection corresponding to a given uid
|
||||
def emclass_del(self, model, uid, initial_state, new_state):
|
||||
emclass = model.classes(uid)
|
||||
if not isinstance(emclass, EmClass):
|
||||
raise ValueError("The given uid is not an EmClass uid")
|
||||
collection_name = utils.object.collection_name(emclass)
|
||||
self._delete_collection(collection_name)
|
||||
|
||||
## @brief creates a new field in a collection
|
||||
# @param model EditorialModel
|
||||
# @param uid str
|
||||
# @param initial_state dict|None: dict representing the original state
|
||||
# @param new_state dict|None: dict representing the new state
|
||||
def emfield_new(self, model, uid, initial_state, new_state):
|
||||
if new_state['data_handler'] == 'relation':
|
||||
# find relational_type name, and class_name of the field
|
||||
class_name = self._class_collection_name_from_field(model, new_state)
|
||||
self._create_field_in_collection(class_name, uid, new_state)
|
||||
else:
|
||||
collection_name = self._class_collection_name_from_field(model, new_state)
|
||||
field_definition = self._field_defition(new_state['data_handler'], new_state)
|
||||
self._create_field_in_collection(collection_name, uid, field_definition)
|
||||
|
||||
## @brief deletes a field in a collection
|
||||
# @param model EditorialModel
|
||||
# @param uid str
|
||||
# @param initial_state dict|None: dict representing the original state
|
||||
# @param new_state dict|None: dict representing the new state
|
||||
def emfield_del(self, model, uid, initial_state, new_state):
|
||||
collection_name = self._class_collection_name_from_field(model, initial_state)
|
||||
field_name = model.field(uid).name
|
||||
self._delete_field_in_collection(collection_name, field_name)
|
||||
|
||||
## @brief Defines the default value when a new field is added to a collection's items
|
||||
# @param fieldtype str : name of the field's type
|
||||
# @param options dict : dictionary giving the options to use to initiate the field's value.
|
||||
# @return dict (containing a 'default' key with the default value)
|
||||
def _field_definition(self, fieldtype, options):
|
||||
basic_type = DataHandler.from_name(fieldtype).ftype
|
||||
if basic_type == 'datetime':
|
||||
if 'now_on_create' in options and options['now_on_create']:
|
||||
return {'default': datetime.datetime.utcnow()}
|
||||
if basic_type == 'relation':
|
||||
return {'default': []}
|
||||
|
||||
return {'default': ''}
|
||||
|
||||
def _class_collection_name_from_field(self, model, field):
|
||||
class_id = field['class_id']
|
||||
component_class = model.classes(class_id)
|
||||
component_collection = utils.object_collection_name(component_class)
|
||||
return component_collection
|
||||
|
||||
## @brief Creates a new collection in MongoDb Database
|
||||
# @param collection_name str
|
||||
# @param charset str
|
||||
# @param if_exists str : defines the behavior when the collection already exists (default : 'nothing')
|
||||
def _create_collection(self, collection_name, charset='utf8', if_exists=MongoDbMigrationHandler.COMMANDS_IFEXISTS_NOTHING):
|
||||
if collection_name in self.database.collection_names(include_system_collections=False):
|
||||
# The collection already exists
|
||||
if if_exists == MongoDbMigrationHandler.COMMANDS_IFEXISTS_DROP:
|
||||
self._delete_collection(collection_name)
|
||||
self.database.create_collection(name=collection_name)
|
||||
else:
|
||||
self.database.create_collection(name=collection_name)
|
||||
|
||||
## @brief Delete an existing collection in MongoDb Database
|
||||
# @param collection_name str
|
||||
def _delete_collection(self, collection_name):
|
||||
collection = self.database[collection_name]
|
||||
collection.drop_indexes()
|
||||
collection.drop()
|
||||
|
||||
## @brief Creates a new field in a collection
|
||||
# @param collection_name str
|
||||
# @param field str
|
||||
# @param options dict
|
||||
def _create_field_in_collection(self, collection_name, field, options):
|
||||
self.database[collection_name].update_many({field: {'$exists': False}}, {'$set': {field: options['default']}}, False)
|
||||
|
||||
## @brief Deletes a field in a collection
|
||||
# @param collection_name str
|
||||
# @param field_name str
|
||||
def _delete_field_in_collection(self, collection_name, field_name):
|
||||
if field_name != '_id':
|
||||
self.database[collection_name].update_many({field_name:{'$exists': True}}, {'$unset':{field_name:1}}, False)
|
||||
|
|
@ -1,190 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import pymongo
|
||||
from pymongo import MongoClient
|
||||
|
||||
from lodel.settings.settings import Settings as settings
|
||||
|
||||
common_collections = {
|
||||
'object': 'object',
|
||||
'relation': 'relation'
|
||||
}
|
||||
|
||||
collection_prefix = {
|
||||
'relation': 'rel_',
|
||||
'object': 'class_'
|
||||
}
|
||||
|
||||
LODEL_OPERATORS_MAP = {
|
||||
'=': {'name': '$eq', 'value_type': None},
|
||||
'<=': {'name': '$lte', 'value_type': None},
|
||||
'>=': {'name': '$gte', 'value_type': None},
|
||||
'!=': {'name': '$ne', 'value_type': None},
|
||||
'<': {'name': '$lt', 'value_type': None},
|
||||
'>': {'name': '$gt', 'value_type': None},
|
||||
'in': {'name': '$in', 'value_type': list},
|
||||
'not in': {'name': '$nin', 'value_type': list},
|
||||
'OR': {'name': '$or', 'value_type': list},
|
||||
'AND': {'name': '$and', 'value_type': list}
|
||||
}
|
||||
|
||||
LODEL_SORT_OPERATORS_MAP = {
|
||||
'ASC': pymongo.ASCENDING,
|
||||
'DESC': pymongo.DESCENDING
|
||||
}
|
||||
|
||||
MONGODB_SORT_OPERATORS_MAP = {
|
||||
'ASC': 1,
|
||||
'DESC': -1
|
||||
}
|
||||
|
||||
|
||||
MANDATORY_CONNECTION_ARGS = ('host', 'port', 'username', 'password', 'db_name')
|
||||
|
||||
|
||||
class MongoDbConnectionError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
## @brief Creates a connection to a MongoDb database
|
||||
def mongodbconnect(connection_name):
|
||||
connection_args = get_connection_args(connection_name)
|
||||
checked_connection_args = check_connection_args(connection_args)
|
||||
if len(checked_connection_args['errors']) > 0:
|
||||
raise MongoDbConnectionError("\r\n-".join(checked_connection_args['errors']))
|
||||
|
||||
# connection arguments are parsed after the check
|
||||
login, password, host, port, dbname = checked_connection_args['params']
|
||||
|
||||
# Connection creation
|
||||
connection_string = 'mongodb://%s:%s@%s:%s' % (login, password, host, port)
|
||||
connection = MongoClient(connection_string)
|
||||
|
||||
# Setting the database
|
||||
database = connection[dbname]
|
||||
|
||||
return database
|
||||
|
||||
|
||||
## @brief gets the settings given a connection name
|
||||
# @param connection_name str
|
||||
# @return dict
|
||||
# @todo Use the settings module to store the connections parameters
|
||||
def get_connection_args(connnection_name='default'):
|
||||
return {'host': 'localhost', 'port': 28015, 'username': 'lodel_admin', 'password': 'lapwd', 'db_name': 'lodel'}
|
||||
|
||||
|
||||
## @brief Checks the settings given a connection name
|
||||
# @param connection_args dict
|
||||
# @return dict
|
||||
# @throw MongoDbDataSourceError with the list of all the found errors
|
||||
# @todo optimize the error management
|
||||
def check_connection_args(connection_args):
|
||||
check_result = {'params': connection_args, 'errors': []}
|
||||
for connection_arg in MANDATORY_CONNECTION_ARGS:
|
||||
if connection_arg not in connection_args:
|
||||
check_result['errors'].append('Datasource connection error: %s parameter is missing.' % connection_arg)
|
||||
return check_result
|
||||
|
||||
|
||||
## @brief Returns a collection name given a Emclass
|
||||
# @param class_object EmClass
|
||||
# @return str
|
||||
def object_collection_name(class_object):
|
||||
if class_object.pure_abstract == False:
|
||||
class_parent = class_object.parents[0].uid
|
||||
collection_name = ("%s%s" % (collection_prefix['object'], class_parent)).lower()
|
||||
else:
|
||||
collection_name = ("%s%s" % (collection_prefix['object'], class_object.name)).lower()
|
||||
|
||||
return collection_name
|
||||
|
||||
|
||||
## @brief converts the query filters into MongoDB filters
|
||||
# @param query_filters list : list of query_filters as tuples or dicts
|
||||
# @param as_list bool : defines if the output will be a list (default: False)
|
||||
# @return dict|list
|
||||
# @todo refactor this function by adding a return_type argument (default= dict) which can be a dict or a list, then delete the convert_filter_list function
|
||||
def parse_query_filters(query_filters, as_list=False):
|
||||
parsed_filters = dict() if not as_list else list()
|
||||
for query_filter in query_filters:
|
||||
if isinstance(query_filter, tuple):
|
||||
if as_list:
|
||||
parsed_filters.append(convert_filter(query_filter))
|
||||
else:
|
||||
parsed_filters.update(convert_filter(query_filter))
|
||||
elif isinstance(query_filter, dict):
|
||||
query_item = list(query_filter.items())[0]
|
||||
key = LODEL_OPERATORS_MAP[query_item[0]]
|
||||
if as_list:
|
||||
parsed_filters.append({key: parse_query_filters(query_item[1], as_list=True)})
|
||||
else:
|
||||
parsed_filters.update({key: parse_query_filters(query_item[1], as_list=True)})
|
||||
else:
|
||||
# TODO Add an exception management here in case the filter is neither a tuple nor a dict
|
||||
pass
|
||||
return parsed_filters
|
||||
|
||||
|
||||
## @brief converts a Lodel query filter into a MongoDB filter
|
||||
# @param filter_params tuple : (FIELD, OPERATOR, VALUE) representing the query filter to convert
|
||||
# @return dict : {KEY: {OPERATOR:VALUE}}
|
||||
# @todo Add an error management for the operator mismatch
|
||||
def convert_filter(filter_params):
|
||||
key, operator, value = filter_params
|
||||
if operator not in ('like', 'not like'):
|
||||
if operator == 'in' and not isinstance(value, list):
|
||||
raise ValueError('A list should be used as value for an IN operator, %s given' % value.__class__)
|
||||
|
||||
converted_operator = LODEL_OPERATORS_MAP[operator]['name']
|
||||
converted_filter = {key: {converted_operator: value}}
|
||||
else:
|
||||
converted_filter = convert_like_filter(filter_params)
|
||||
return converted_filter
|
||||
|
||||
|
||||
## @brief Returns a list of sorting options
|
||||
# @param query_filters_order list
|
||||
# @return list
|
||||
def parse_query_order(query_filters_order):
|
||||
ordering = list()
|
||||
for query_filter_order in query_filters_order:
|
||||
field, direction = query_filter_order
|
||||
ordering.append((field, LODEL_SORT_OPERATORS_MAP[direction]))
|
||||
return ordering
|
||||
|
||||
|
||||
## @brief Converts "like" and "not like" filters into MongotDb filters
|
||||
# @param like_filter tuple
|
||||
# @return dict
|
||||
def convert_like_filter(like_filter):
|
||||
key, operator, value = like_filter
|
||||
|
||||
is_starting_with = value.endswith('*')
|
||||
is_ending_with = value.startswith('*')
|
||||
|
||||
if is_starting_with and not is_ending_with:
|
||||
regex_pattern = value.replace('*', '^')
|
||||
elif is_ending_with and not is_starting_with:
|
||||
regex_pattern = value.replace('*', '$')
|
||||
elif is_starting_with and is_ending_with:
|
||||
regex_pattern = '%s' % value
|
||||
else:
|
||||
regex_pattern = '^%s$' % value
|
||||
|
||||
regex_condition = {'$regex': regex_pattern, '$options': 'i'}
|
||||
converted_filter = {key: regex_condition}
|
||||
if operator.startswith('not'):
|
||||
converted_filter = {key: {'$not': regex_condition}}
|
||||
|
||||
return converted_filter
|
||||
|
||||
|
||||
## @brief identifier escaping
|
||||
# @param idname str: An identifier
|
||||
# @return str
|
||||
def escape_idname(idname):
|
||||
if '`' in idname:
|
||||
raise ValueError("Invalid name : '%s'" % idname)
|
||||
return '`%s`' % idname
|
||||
|
||||
|
|
@ -7,8 +7,8 @@ from lodel.editorial_model.model import EditorialModel
|
|||
from lodel.editorial_model.components import *
|
||||
from lodel.utils.mlstring import MlString
|
||||
|
||||
## @package lodel.editorial_model.translator Lodel 2 Editorial Model Translators
|
||||
## @brief Packahg for saving a Editorial µModel in a xml fiel and loading an Editorial Model from a xml file
|
||||
##@package lodel.editorial_model.translator.xmlfile Translator module designed
|
||||
#to load & save EM in XML
|
||||
#
|
||||
# Structure of a xml file which represents an editorial model:
|
||||
# <ul>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue