1
0
Fork 0
mirror of https://github.com/yweber/lodel2.git synced 2025-11-22 05:36:54 +01:00

Merge branch 'newlodel' of git.labocleo.org:lodel2 into newlodel

This commit is contained in:
prieto 2016-04-21 10:44:49 +02:00
commit 462d09d876
5 changed files with 131 additions and 12 deletions

View file

@ -1,3 +1 @@
#-*- coding: utf-8 -*-
from .utils.starter import init_lodel

View file

@ -0,0 +1,46 @@
# -*- 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)

View file

@ -1,4 +1,8 @@
# -*- 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
@ -64,12 +68,11 @@ class MongoDbDataSource(GenericDataSource):
# @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 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 grouping
# @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):
@ -79,13 +82,41 @@ class MongoDbDataSource(GenericDataSource):
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
cursor = collection.find(
filter=query_filters,
projection=results_field_list,
skip=offset,
limit=limit,
sort=query_result_ordering
)
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)

View file

@ -1 +1,41 @@
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
from lodel.datasource.generic.migrationhandler import GenericMigrationHandler
from lodel.datasource.mongodb.datasource import MongoDbDataSource
from lodel.editorial_model.components import EmClass, EmField
class MigrationHandlerChangeError(Exception):
pass
## @brief Modifies a MongoDb database given editorial model changes
class MongoDbMigrationHandler(GenericMigrationHandler):
## @brief constructs a MongoDbMigrationHandler
# @param conn_args dict : a dictionary containing connection options
# @param **kwargs : extra arguments given to the connection methods
def __init__(self, conn_args=None, **kwargs):
if conn_args is None:
conn_args = {} # TODO : récupérer les options de connexion dans les settings
self.connection_name = conn_args['name']
# del conn_args['module']
self.db_conn = MongoDbDataSource(self.connection_name)
# TODO Réimplémenter la partie sur les settings
mh_settings = {}
self.dryrun = kwargs['dryrun'] if 'dryrun' in kwargs else mh_settings['dryrun']
self.foreign_keys = kwargs['foreign_keys'] if 'foreign_keys' in kwargs else mh_settings['foreign_keys']
self.drop_if_exists = kwargs['drop_if_exists'] if 'drop_if_exists' in kwargs else mh_settings['drop_if_exists']
self._create_default_collections(self.drop_if_exists)
## @brief Modify the database given an EM change
#
# @param em model : The EditorialModel.model object to provide the global context.
# @param uid str : The uid of the changed component.
# @param initial_state dict|None : dict with field name as key and field value as value. Represents the original state. None means it's a creation of a new component.
# @param new_state dict|None : dict with field name as key and field value as value. Represents the new state. None means it's a component deletion.
# @throw MigrationHandlerChangeError if the change was refused
def register_change(self, em, uid, initial_state, new_state):
pass
def _create_default_collections(self, drop_if_exist=False):
pass

View file

@ -25,6 +25,10 @@ LODEL_SORT_OPERATORS_MAP = {
'DESC': pymongo.DESCENDING
}
MONGODB_SORT_OPERATORS_MAP = {
'ASC': 1,
'DESC': -1
}
## @brief Returns a collection name given a Emclass name
# @param class_name str : The class name