mirror of
https://github.com/yweber/lodel2.git
synced 2025-11-25 23:06:55 +01:00
192 lines
8.5 KiB
Python
192 lines
8.5 KiB
Python
#-*- coding: utf-8 -*-
|
|
|
|
## @package EditorialModel.randomem
|
|
#
|
|
# @warning BROKEN because there is no more fieldgroups
|
|
# Provide methods for random EM generation
|
|
|
|
import random
|
|
from EditorialModel.backend.dummy_backend import EmBackendDummy
|
|
from EditorialModel.model import Model
|
|
from EditorialModel.fields import EmField
|
|
from EditorialModel.types import EmType
|
|
from EditorialModel.classtypes import EmClassType
|
|
from Lodel.utils.mlstring import MlString
|
|
|
|
|
|
class RandomEm(object):
|
|
|
|
## @brief Instanciate a class allowing to generate random EM
|
|
# @see RandomEm::random_em()
|
|
def __init__(self, backend=None, **kwargs):
|
|
self.backend = backend
|
|
self.kwargs = kwargs
|
|
|
|
## @brief Return a random EM
|
|
# @return A random EM
|
|
def gen(self):
|
|
return self.random_em(self.backend, **self.kwargs)
|
|
|
|
@classmethod
|
|
## @brief Generate a random editorial model
|
|
#
|
|
# The random generator can be tuned with integer parameters
|
|
# that represent probability or maximum numbers of items.
|
|
# The probability (chances) works like 1/x chances to append
|
|
# with x the tunable parameter
|
|
# Tunable generator parameters :
|
|
# - classtype : Chances for a classtype to be empty (default 0)
|
|
# - nclass : Maximum number of classes per classtypes (default 5)
|
|
# - nofg : Chances for a classe to have no fieldgroup associated to it (default 10)
|
|
# - notype : Chances for a classe to have no type associated to it (default 5)
|
|
# - seltype : Chances for a type to select an optionnal field (default 2)
|
|
# - ntypesuperiors : Chances for a type to link with a superiors (default 3)
|
|
# - nofields : Chances for a fieldgroup to be empty (default 10)
|
|
# - nfields : Maximum number of field per fieldgroups (default 8)
|
|
# - rfields : Maximum number of relation_to_type attributes fields (default 5)
|
|
# - optfield : Chances for a field to be optionnal (default 2)
|
|
# @param backend : A backend to use with the new EM
|
|
# @param **kwargs dict : Provide tunable generation parameter
|
|
# @param cls
|
|
# @return A randomly generate EM
|
|
def random_em(cls, backend=None, **kwargs):
|
|
ed_mod = Model(EmBackendDummy if backend is None else backend)
|
|
|
|
chances = {
|
|
'classtype': 0, # a class in classtype
|
|
'nclass': 5, # max number of classes per classtype
|
|
'nofg': 10, # no fieldgroup in a class
|
|
'nfg': 5, # max number of fieldgroups per classes
|
|
'notype': 10, # no types in a class
|
|
'ntype': 8, # max number of types in a class
|
|
'seltype': 2, # chances to select an optional field
|
|
'ntypesuperiors': 2, # chances to link with a superior
|
|
'nofields': 10, # no fields in a fieldgroup
|
|
'nfields': 8, # max number of fields per fieldgroups
|
|
'nr2tfields': 1, # max number of rel2type fields per fieldgroups
|
|
'rfields': 5, # max number of attributes relation fields
|
|
'optfield': 2, # chances to be optionnal
|
|
}
|
|
|
|
for name, value in kwargs.items():
|
|
if name not in chances:
|
|
#warning
|
|
pass
|
|
else:
|
|
chances[name] = value
|
|
|
|
#classes creation
|
|
for classtype in EmClassType.getall():
|
|
if random.randint(0, chances['classtype']) == 0:
|
|
for _ in range(random.randint(1, chances['nclass'])):
|
|
cdats = cls._rnd_component_datas()
|
|
cdats['classtype'] = classtype['name']
|
|
ed_mod.create_component('EmClass', cdats)
|
|
|
|
for emclass in ed_mod.classes():
|
|
#fieldgroups creation
|
|
"""
|
|
if random.randint(0, chances['nofg']) != 0:
|
|
for _ in range(random.randint(1, chances['nfg'])):
|
|
fgdats = cls._rnd_component_datas()
|
|
fgdats['class_id'] = emclass.uid
|
|
ed_mod.create_component('EmFieldGroup', fgdats)
|
|
"""
|
|
|
|
#types creation
|
|
if random.randint(0, chances['notype']) != 0:
|
|
for _ in range(random.randint(1, chances['ntype'])):
|
|
tdats = cls._rnd_component_datas()
|
|
tdats['class_id'] = emclass.uid
|
|
ed_mod.create_component('EmType', tdats)
|
|
|
|
#random type hierarchy
|
|
for emtype in ed_mod.components(EmType):
|
|
possible = emtype.possible_superiors()
|
|
for nat in possible:
|
|
if len(possible[nat]) > 0 and random.randint(0, chances['ntypesuperiors']) == 0:
|
|
random.shuffle(possible[nat])
|
|
for i in range(random.randint(1, len(possible[nat]))):
|
|
emtype.add_superior(possible[nat][i], nat)
|
|
|
|
#fields creation
|
|
ft_l = [ftname for ftname in EmField.fieldtypes_list() if ftname != 'pk' and ftname != 'rel2type']
|
|
for emc in ed_mod.components('EmClass'):
|
|
if random.randint(0, chances['nofields']) != 0:
|
|
for _ in range(random.randint(1, chances['nfields'])):
|
|
field_type = ft_l[random.randint(0, len(ft_l) - 1)]
|
|
fdats = cls._rnd_component_datas()
|
|
fdats['fieldtype'] = field_type
|
|
fdats['class_id'] = emc.uid
|
|
if random.randint(0, chances['optfield']) == 0:
|
|
fdats['optional'] = True
|
|
ed_mod.create_component('EmField', fdats)
|
|
|
|
#rel2type creation (in case none where created before
|
|
for emc in ed_mod.components('EmClass'):
|
|
for _ in range(random.randint(0, chances['nr2tfields'])):
|
|
field_type = 'rel2type'
|
|
fdats = cls._rnd_component_datas()
|
|
fdats['fieldtype'] = field_type
|
|
fdats['class_id'] = emc.uid
|
|
emtypes = ed_mod.components(EmType)
|
|
fdats['rel_to_type_id'] = emtypes[random.randint(0, len(emtypes) - 1)].uid
|
|
if random.randint(0, chances['optfield']) == 0:
|
|
fdats['optional'] = True
|
|
ed_mod.create_component('EmField', fdats)
|
|
|
|
# relationnal fields creation
|
|
ft_l = [field_type for field_type in EmField.fieldtypes_list() if field_type != 'rel2type' and field_type != 'pk']
|
|
for emrelf in [f for f in ed_mod.components(EmField) if f.fieldtype == 'rel2type']:
|
|
for _ in range(0, chances['rfields']):
|
|
field_type = ft_l[random.randint(0, len(ft_l) - 1)]
|
|
fdats = cls._rnd_component_datas()
|
|
fdats['rel_field_id'] = emrelf.uid
|
|
fdats['fieldtype'] = field_type
|
|
fdats['class_id'] = emrelf.class_id
|
|
if random.randint(0, chances['optfield']) == 0:
|
|
fdats['optional'] = True
|
|
ed_mod.create_component('EmField', fdats)
|
|
|
|
#selection optionnal fields
|
|
for emtype in ed_mod.components(EmType):
|
|
selectable = [field for field in emtype.em_class.fields() if field.optional]
|
|
for field in selectable:
|
|
if random.randint(0, chances['seltype']) == 0:
|
|
emtype.select_field(field)
|
|
return ed_mod
|
|
|
|
@staticmethod
|
|
## @brief Generate a random string
|
|
# @warning dirty cache trick with globals()
|
|
# @return a randomly selected string
|
|
def _rnd_str(words_src='/usr/share/dict/words'):
|
|
if '_words' not in globals() or globals()['_words_fname'] != words_src:
|
|
globals()['_words_fname'] = words_src
|
|
with open(words_src, 'r') as fpw:
|
|
globals()['_words'] = [l.strip() for l in fpw]
|
|
words = globals()['_words']
|
|
return words[random.randint(0, len(words) - 1)]
|
|
|
|
@classmethod
|
|
## @brief Generate a random MlString
|
|
# @param nlng : Number of langs in the MlString
|
|
# @return a random MlString with nlng translations
|
|
# @todo use a dict to generated langages
|
|
def _rnd_mlstr(cls, nlng):
|
|
ret = MlString()
|
|
for _ in range(nlng):
|
|
ret.set(cls._rnd_str(), cls._rnd_str())
|
|
return ret
|
|
|
|
@classmethod
|
|
## @brief returns randomly generated datas for an EmComponent
|
|
# @return a dict with name, string and help_text
|
|
def _rnd_component_datas(cls):
|
|
mlstr_nlang = 2
|
|
ret = dict()
|
|
ret['name'] = cls._rnd_str()
|
|
ret['string'] = cls._rnd_mlstr(mlstr_nlang)
|
|
ret['help_text'] = cls._rnd_mlstr(mlstr_nlang)
|
|
|
|
return ret
|