Source code for erecord_vpz.models_mixins.models_mixins

# -*- coding: UTF-8 -*-

""" @file erecord_vpz/models_mixins.py
..

Copyright (C) 2014-2016 INRA http://www.inra.fr \n\n
This file is part of erecord - Record platform web development \n\n
License : see LICENSE file. Authors : see AUTHORS file.
@include LICENSE @include AUTHORS
"""

""" @package erecord_vpz.models_mixins
mixins for erecord_vpz model

see erecord_vpz

"""

import os
import json
import datetime

from erecord_cmn.configs.config import REPOSITORIES_HOME
from erecord_cmn.utils.vle import get_vlepath_pkg_name
from erecord_cmn.configs.config import REQUESTS_HOME_APP_VPZ

from erecord_cmn.utils.vle import get_rep_pkgname_list
from erecord_cmn.utils.vle import get_rep_pkgs_path

from erecord_vpz.models_mixins.workspace import RunhomeWorkspaceMixin
from erecord_vpz.models_mixins.workspace import DatahomeWorkspaceMixin
from erecord_vpz.models_mixins.workspace import ReporthomeWorkspaceMixin
from erecord_vpz.models_mixins.workspace import VlehomeWorkspaceMixin
from erecord_vpz.models_mixins.workspace import WorkspaceMixin

import shutil
from erecord_cmn.utils.dir_and_file import make_csv_file
from erecord_cmn.utils.dir_and_file import create_dirs_if_absent
from erecord_cmn.utils.dir_and_file import delete_path_if_present
from erecord_cmn.utils.dir_and_file import clean_dir
from erecord_cmn.utils.dir_and_file import get_available_pathname
from erecord_cmn.configs.config import ACTIVITY_LIFETIME

from erecord_cmn.utils.erecord_package import vle_run_vpz

from erecord_cmn.utils.logger import get_logger
LOGGER = get_logger(__name__) # should be passed as a parameter of methods ?

# Some mixins for the erecord_vpz models

[docs]class VpzPathMixin(object): """additional methods for VpzPath """
[docs] def for_vpzact_creation(self): """ Prepares the creation of a VpzAct from a VpzPath """ res = None e = get_vlepath_pkg_name(vpzpath=self.vpzpath, limit=REPOSITORIES_HOME) if e is None : msg = "unavailable vpzpath '"+self.vpzpath+"'" raise Exception(msg) (vlepath,pkgname,vpzname) = e v = vle_identify(vlepath) if v is None : msg = "unavailable vle version configuration for '"+vlepath+"'" raise Exception(msg) (vleversion, vle_usr_path) = v now = datetime.datetime.now() text = "Vpz activity (VpzAct) created from VpzPath. " text = text+ "VpzPath id : " + str(self.id) + ", " text = text+ "vpzpath : " + self.vpzpath + ". " text = text+ "vle version : " + vleversion + ". " text = text+ "vle usr path : " + vle_usr_path + ". " text = text+ "Time:" + str(now) + "." res = { 'vlepath':vlepath, 'pkgname': pkgname, 'vpzname': vpzname, 'vleversion': vleversion, 'vleusrpath': vle_usr_path, 'textorigin': text, } return res
[docs]class AttachedToVpzActMixin(object): """additional methods for a model attached to a VpzAct """
[docs] @classmethod def create(cls, vpzact, **kwargs): """create the object attached to vpzact """ obj = cls(vpzact=vpzact, **kwargs) return obj
[docs]class VpzOriginMixin(object): """additional methods for VpzOrigin """
[docs] def set_undefined_value_text(self): self.text = "undefined"
[docs] def is_undefined_value_text(self): return self.text == "undefined"
[docs]class VpzWorkspaceMixin(RunhomeWorkspaceMixin, DatahomeWorkspaceMixin, ReporthomeWorkspaceMixin, VlehomeWorkspaceMixin, WorkspaceMixin): """additional methods for VpzWorkspace """
[docs] def define_and_build(self, as_vlehome=False, as_reporthome=False, as_datahome=False, as_runhome=False): """ Defines and builds a VpzWorkspace Chooses/defines fields values (homepath, vlehome, reporthome, datahome, runhome) and creates the required directories (at least homepath). A workspace may concern vlehome, reporthome, datahome, runhome. Those subdirectories will there be created or not depending on as_vlehome, as_reporthome, as_datahome, as_runhome. """ self.homepath = self.get_undefined_value() self.vlehome = self.get_undefined_value() self.reporthome = self.get_undefined_value() self.datahome = self.get_undefined_value() self.runhome = self.get_undefined_value() homepath = get_available_pathname(rootpath=REQUESTS_HOME_APP_VPZ, rootname="user_") (deletion_done, creation_done) = clean_dir(dirpath=homepath) if deletion_done : LOGGER.error(u"%s has been deleted before to be recreated, whereas it was supposed not to exist", homepath) self.homepath = homepath self.datahome = self.init_datahome(LOGGER=LOGGER, as_datahome=as_datahome) self.reporthome = self.init_reporthome(LOGGER=LOGGER, as_reporthome=as_reporthome) self.runhome = self.init_runhome(LOGGER=LOGGER, as_runhome=as_runhome) self.vlehome = self.init_vlehome(LOGGER=LOGGER, as_vlehome=as_vlehome)
[docs] def get_homepath(self): return self.homepath
[docs] def clean_workspace(self): clean_dir(dirpath=self.homepath)
[docs] def clear_workspace(self): delete_path_if_present(path=self.homepath)
[docs] def clear_dirs(self): self.clear_vlehome() self.clear_reporthome() self.clear_datahome() self.clear_runhome() self.clear_workspace()
[docs]class VpzActMixin(object): """additional methods for VpzAct """
[docs] def get_ordered_vlepackage_list(self): """builds and returns an ordered list about the vpzact vle package \ and its dependency packages. The list elements are, for each vle package : (package name, package path name), where the vpzact vle package (ie \ named pkgname) is the first one. Since the real dependency packages of the vpzact vle package are not \ clearly known, all the other vle packages of the vpzact models \ repository (ie corresponding with path vlepath) are considered as \ potential dependency packages. """ pkgname_list = get_rep_pkgname_list(rep_path=self.vlepath, vle_version=self.vleversion) if self.pkgname in pkgname_list : pkgname_list.remove(self.pkgname) pkgname_list.insert(0, self.pkgname) pkgs_path = get_rep_pkgs_path(rep_path=self.vlepath, vle_version=self.vleversion) vlepackage_list = [(pkgname, os.path.join(pkgs_path, pkgname)) for pkgname in pkgname_list] return vlepackage_list
[docs] def is_old(self): """vpzact is old if created_at 'older' than ACTIVITY_LIFETIME """ d = self.created_at + datetime.timedelta(days=ACTIVITY_LIFETIME) now = datetime.datetime.now() if d.toordinal() < now.toordinal() : return True else : return False
[docs]class VpzInputMixin(object): """additional methods for VpzInput """ pass
[docs]class VpzOutputMixin(object): """additional methods for VpzOutput """
[docs] def run(self, plan, restype): """Runs the simulation relative to self.vpzact to define self.res The simulation running method depends on plan ('single' or 'linear') \ and restype ('dataframe' or 'matrix'). Uses json result based on run_vpz simulator of erecord package """ #print "VpzOutputMixin, run : plan ", plan, " restype ", restype self.res = None # default res = None vlehome_path = self.vpzact.vpzworkspace.get_vlehome() runvle_path = self.vpzact.vpzworkspace.define_and_build_runhome_subdirectory(rootname="run_") vle_version = self.vpzact.vleversion vle_usr_path = self.vpzact.vleusrpath pkgname = self.vpzact.pkgname vpzname = self.vpzact.vpzname jres = vle_run_vpz(runvle_path=runvle_path, vlehome_path=vlehome_path, vle_version=vle_version, vle_usr_path=vle_usr_path, pkgname=pkgname, vpzname=vpzname, plan=plan, restype=restype) keys = jres.keys() if "plan" in keys : plan = jres["plan"] if "restype" in keys : restype = jres["restype"] if "res" in keys : res = jres["res"] if type(res) is str : # error case msg = "Simulation running error ... " + res raise Exception(msg) # empty cases if res is None : # single case res = dict() if type(res) is list : # linear case if res == [None] : res = list() self.res = res self.plan = plan self.restype = restype
#print "run" #print "RESULT type(self.res) : ", type(self.res)
[docs] @classmethod def build_output_outname(cls, oname): """Builds and returns the outname value of an output data from its oname value. This method is used to interpret the res content of VpzOutput in \ relation with the VleOut denominations (vname, oname, selection_name). oname is the oname value of the output data as a VleOut. outname comes from the result produced by a vle simulation (cf res \ of VpzOutput). Identity method since oname equals outname. """ return oname
[docs] @classmethod def build_output_oname(cls, outname): """Builds and returns the oname value of an output data from its outname value. This method is used to interpret the res content of VpzOutput in \ relation with the VleOut denominations (vname, oname, selection_name). oname is the oname value of the output data as a VleOut. outname comes from the result produced by a vle simulation (cf res \ of VpzOutput). Identity method since oname equals outname. """ return outname
[docs] @classmethod def UNUSED__build_output_outname(cls, oname): """Builds and returns the outname value of an output data from its oname value. This method is used to interpret the res content of VpzOutput in \ relation with the VleOut denominations (vname, oname, selection_name). oname is the oname value of the output data as a VleOut. outname comes from the result produced by a vle simulation (cf res \ of VpzOutput). outname looks like oname but is quite different (cf \ ':' instead of ',') """ outname = oname[::-1].replace(',',':',1)[::-1] return outname
[docs] @classmethod def UNUSED__build_output_oname(cls, outname): """Builds and returns the oname value of an output data from its outname value. This method is used to interpret the res content of VpzOutput in \ relation with the VleOut denominations (vname, oname, selection_name). oname is the oname value of the output data as a VleOut. outname comes from the result produced by a vle simulation (cf res \ of VpzOutput). outname looks like oname but is quite different (cf \ ':' instead of ',') """ oname = outname[::-1].replace(':',',',1)[::-1] return oname
[docs] def format_res_ok(self): """ Verifies the format of res according to plan and restype. Returns True or False. """ def format_ok_dataframe_single(res): format_ok = True if not isinstance(res, dict) : format_ok = False else : for view in res.values(): if not isinstance(view, dict) : format_ok = False else : for out in view.values() : if not isinstance(out, list) : format_ok = False return format_ok def format_ok_matrix_single(res): format_ok = True if not isinstance(res, dict) : format_ok = False else : for view in res.values(): if not isinstance(view, list) : format_ok = False else : for out in view : if not isinstance(out, list) : format_ok = False return format_ok res = json.loads(self.res) if self.restype == 'dataframe' : if self.plan == 'single' : format_ok = format_ok_dataframe_single(res) elif self.plan == 'linear' : format_ok = True if not isinstance(res, list) : format_ok = False else : for r in res: if not format_ok_dataframe_single(r): format_ok = False elif self.restype == 'matrix' : if self.plan == 'single' : format_ok = format_ok_matrix_single(res) elif self.plan == 'linear' : format_ok = True if not isinstance(res, list) : format_ok = False else : for r in res: if not format_ok_matrix_single(r): format_ok = False return format_ok
[docs] def print_res(self): print "--- self.res : " if (self.plan=='single') and (self.restype=='dataframe'): for viewname,viewvalue in self.res.iteritems() : print viewname, " : " for outname,outvalue in viewvalue.iteritems() : print " ", outname, " : ", outvalue elif (self.plan=='linear') and (self.restype=='dataframe'): for m,mv in enumerate(list(self.res)) : print "(", m, ") :" for viewname,viewvalue in mv.iteritems() : print viewname, " : " for outname,outvalue in viewvalue.iteritems() : print " ", outname, " : ", outvalue if (self.plan=='single') and (self.restype=='matrix'): for viewname,viewvalue in self.res.iteritems() : print viewname, " : " #print viewvalue for out in viewvalue : print " ", out if (self.plan=='linear') and (self.restype=='matrix'): for m,mv in enumerate(list(self.res)) : print "(", m, ") :" for viewname,viewvalue in mv.iteritems() : print viewname, " : " #print viewvalue for out in viewvalue : print " ", out print "---"