Ingen beskrivning
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

randomem.py 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. #-*- coding: utf-8 -*-
  2. ## @package EditorialModel.randomem
  3. #
  4. # @warning BROKEN because there is no more fieldgroups
  5. # Provide methods for random EM generation
  6. import random
  7. from EditorialModel.backend.dummy_backend import EmBackendDummy
  8. from EditorialModel.model import Model
  9. from EditorialModel.fields import EmField
  10. from EditorialModel.types import EmType
  11. from EditorialModel.classtypes import EmClassType
  12. from Lodel.utils.mlstring import MlString
  13. class RandomEm(object):
  14. ## @brief Instanciate a class allowing to generate random EM
  15. # @see RandomEm::random_em()
  16. def __init__(self, backend=None, **kwargs):
  17. self.backend = backend
  18. self.kwargs = kwargs
  19. ## @brief Return a random EM
  20. # @return A random EM
  21. def gen(self):
  22. return self.random_em(self.backend, **self.kwargs)
  23. @classmethod
  24. ## @brief Generate a random editorial model
  25. #
  26. # The random generator can be tuned with integer parameters
  27. # that represent probability or maximum numbers of items.
  28. # The probability (chances) works like 1/x chances to append
  29. # with x the tunable parameter
  30. # Tunable generator parameters :
  31. # - classtype : Chances for a classtype to be empty (default 0)
  32. # - nclass : Maximum number of classes per classtypes (default 5)
  33. # - nofg : Chances for a classe to have no fieldgroup associated to it (default 10)
  34. # - notype : Chances for a classe to have no type associated to it (default 5)
  35. # - seltype : Chances for a type to select an optionnal field (default 2)
  36. # - ntypesuperiors : Chances for a type to link with a superiors (default 3)
  37. # - nofields : Chances for a fieldgroup to be empty (default 10)
  38. # - nfields : Maximum number of field per fieldgroups (default 8)
  39. # - rfields : Maximum number of relation_to_type attributes fields (default 5)
  40. # - optfield : Chances for a field to be optionnal (default 2)
  41. # @param backend : A backend to use with the new EM
  42. # @param **kwargs dict : Provide tunable generation parameter
  43. # @param cls
  44. # @return A randomly generate EM
  45. def random_em(cls, backend=None, **kwargs):
  46. ed_mod = Model(EmBackendDummy if backend is None else backend)
  47. chances = {
  48. 'classtype': 0, # a class in classtype
  49. 'nclass': 5, # max number of classes per classtype
  50. 'nofg': 10, # no fieldgroup in a class
  51. 'nfg': 5, # max number of fieldgroups per classes
  52. 'notype': 10, # no types in a class
  53. 'ntype': 8, # max number of types in a class
  54. 'seltype': 2, # chances to select an optional field
  55. 'ntypesuperiors': 2, # chances to link with a superior
  56. 'nofields': 10, # no fields in a fieldgroup
  57. 'nfields': 8, # max number of fields per fieldgroups
  58. 'nr2tfields': 1, # max number of rel2type fields per fieldgroups
  59. 'rfields': 5, # max number of attributes relation fields
  60. 'optfield': 2, # chances to be optionnal
  61. }
  62. for name, value in kwargs.items():
  63. if name not in chances:
  64. #warning
  65. pass
  66. else:
  67. chances[name] = value
  68. #classes creation
  69. for classtype in EmClassType.getall():
  70. if random.randint(0, chances['classtype']) == 0:
  71. for _ in range(random.randint(1, chances['nclass'])):
  72. cdats = cls._rnd_component_datas()
  73. cdats['classtype'] = classtype['name']
  74. ed_mod.create_component('EmClass', cdats)
  75. for emclass in ed_mod.classes():
  76. #fieldgroups creation
  77. """
  78. if random.randint(0, chances['nofg']) != 0:
  79. for _ in range(random.randint(1, chances['nfg'])):
  80. fgdats = cls._rnd_component_datas()
  81. fgdats['class_id'] = emclass.uid
  82. ed_mod.create_component('EmFieldGroup', fgdats)
  83. """
  84. #types creation
  85. if random.randint(0, chances['notype']) != 0:
  86. for _ in range(random.randint(1, chances['ntype'])):
  87. tdats = cls._rnd_component_datas()
  88. tdats['class_id'] = emclass.uid
  89. ed_mod.create_component('EmType', tdats)
  90. #random type hierarchy
  91. for emtype in ed_mod.components(EmType):
  92. possible = emtype.possible_superiors()
  93. for nat in possible:
  94. if len(possible[nat]) > 0 and random.randint(0, chances['ntypesuperiors']) == 0:
  95. random.shuffle(possible[nat])
  96. for i in range(random.randint(1, len(possible[nat]))):
  97. emtype.add_superior(possible[nat][i], nat)
  98. #fields creation
  99. ft_l = [ftname for ftname in EmField.fieldtypes_list() if ftname != 'pk' and ftname != 'rel2type']
  100. for emc in ed_mod.components('EmClass'):
  101. if random.randint(0, chances['nofields']) != 0:
  102. for _ in range(random.randint(1, chances['nfields'])):
  103. field_type = ft_l[random.randint(0, len(ft_l) - 1)]
  104. fdats = cls._rnd_component_datas()
  105. fdats['fieldtype'] = field_type
  106. fdats['class_id'] = emc.uid
  107. if random.randint(0, chances['optfield']) == 0:
  108. fdats['optional'] = True
  109. ed_mod.create_component('EmField', fdats)
  110. #rel2type creation (in case none where created before
  111. for emc in ed_mod.components('EmClass'):
  112. for _ in range(random.randint(0, chances['nr2tfields'])):
  113. field_type = 'rel2type'
  114. fdats = cls._rnd_component_datas()
  115. fdats['fieldtype'] = field_type
  116. fdats['class_id'] = emc.uid
  117. emtypes = ed_mod.components(EmType)
  118. fdats['rel_to_type_id'] = emtypes[random.randint(0, len(emtypes) - 1)].uid
  119. if random.randint(0, chances['optfield']) == 0:
  120. fdats['optional'] = True
  121. ed_mod.create_component('EmField', fdats)
  122. # relationnal fields creation
  123. ft_l = [field_type for field_type in EmField.fieldtypes_list() if field_type != 'rel2type' and field_type != 'pk']
  124. for emrelf in [f for f in ed_mod.components(EmField) if f.fieldtype == 'rel2type']:
  125. for _ in range(0, chances['rfields']):
  126. field_type = ft_l[random.randint(0, len(ft_l) - 1)]
  127. fdats = cls._rnd_component_datas()
  128. fdats['rel_field_id'] = emrelf.uid
  129. fdats['fieldtype'] = field_type
  130. fdats['class_id'] = emrelf.class_id
  131. if random.randint(0, chances['optfield']) == 0:
  132. fdats['optional'] = True
  133. ed_mod.create_component('EmField', fdats)
  134. #selection optionnal fields
  135. for emtype in ed_mod.components(EmType):
  136. selectable = [field for field in emtype.em_class.fields() if field.optional]
  137. for field in selectable:
  138. if random.randint(0, chances['seltype']) == 0:
  139. emtype.select_field(field)
  140. return ed_mod
  141. @staticmethod
  142. ## @brief Generate a random string
  143. # @warning dirty cache trick with globals()
  144. # @return a randomly selected string
  145. def _rnd_str(words_src='/usr/share/dict/words'):
  146. if '_words' not in globals() or globals()['_words_fname'] != words_src:
  147. globals()['_words_fname'] = words_src
  148. with open(words_src, 'r') as fpw:
  149. globals()['_words'] = [l.strip() for l in fpw]
  150. words = globals()['_words']
  151. return words[random.randint(0, len(words) - 1)]
  152. @classmethod
  153. ## @brief Generate a random MlString
  154. # @param nlng : Number of langs in the MlString
  155. # @return a random MlString with nlng translations
  156. # @todo use a dict to generated langages
  157. def _rnd_mlstr(cls, nlng):
  158. ret = MlString()
  159. for _ in range(nlng):
  160. ret.set(cls._rnd_str(), cls._rnd_str())
  161. return ret
  162. @classmethod
  163. ## @brief returns randomly generated datas for an EmComponent
  164. # @return a dict with name, string and help_text
  165. def _rnd_component_datas(cls):
  166. mlstr_nlang = 2
  167. ret = dict()
  168. ret['name'] = cls._rnd_str()
  169. ret['string'] = cls._rnd_mlstr(mlstr_nlang)
  170. ret['help_text'] = cls._rnd_mlstr(mlstr_nlang)
  171. return ret