No Description
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.

field_data_handler.py 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. # -*- coding: utf-8 -*-
  2. import importlib
  3. class FieldDataHandler(object):
  4. help_text = 'Generic Field Data Handler'
  5. ## @brief List fields that will be exposed to the construct_data_method
  6. _construct_datas_deps = []
  7. ## @brief constructor
  8. # @param internal False | str : define whether or not a field is internal
  9. # @param immutable bool : indicates if the fieldtype has to be defined in child classes of LeObject or if it is
  10. # designed globally and immutable
  11. # @param **args
  12. # @throw NotImplementedError if it is instanciated directly
  13. def __init__(self, internal=False, immutable=False, **args):
  14. if self.__class__ == FieldDataHandler:
  15. raise NotImplementedError("Abstract class")
  16. self.internal = internal # Check this value ?
  17. self.immutable = bool(immutable)
  18. for argname, argval in args.items():
  19. setattr(self, argname, argval)
  20. ## Fieldtype name
  21. @staticmethod
  22. def name(cls):
  23. return cls.__module__.split('.')[-1]
  24. ## @brief checks if a fieldtype is internal
  25. # @return bool
  26. def is_internal(self):
  27. return self.internal is not False
  28. ## @brief calls the data_field defined _check_data_value() method
  29. # @return tuple (value, error|None)
  30. def check_data_value(self, value):
  31. return self._check_data_value(value)
  32. def _check_data_value(self, value):
  33. return value, None
  34. ## @brief checks if this class can override the given data handler
  35. # @param data_handler DataHandler
  36. # @return bool
  37. def can_override(self, data_handler):
  38. if data_handler.__class__.base_type != self.__class__.base_type:
  39. return False
  40. return True
  41. ## @brief Build field value
  42. # @param emcomponent EmComponent : An EmComponent child class instance
  43. # @param fname str : The field name
  44. # @param datas dict : dict storing fields values (from the component)
  45. # @param cur_value : the value from the current field (identified by fieldname)
  46. # @return the value
  47. # @throw RunTimeError if data construction fails
  48. def construct_data(self, emcomponent, fname, datas, cur_value):
  49. emcomponent_fields = emcomponent.fields()
  50. fname_data_handler = None
  51. if fname in emcomponent_fields:
  52. fname_data_handler = FieldDataHandler.from_name(emcomponent_fields[fname])
  53. if fname in datas.keys():
  54. return cur_value
  55. elif fname_data_handler is not None and hasattr(fname_data_handler, 'default'):
  56. return fname_data_handler.default
  57. elif fname_data_handler is not None and fname_data_handler.nullable:
  58. return None
  59. return RuntimeError("Unable to construct data for field %s", fname)
  60. ## @brief Check datas consistency
  61. # @param emcomponent EmComponent : An EmComponent child class instance
  62. # @param fname : the field name
  63. # @param datas dict : dict storing fields values
  64. # @return an Exception instance if fails else True
  65. # @todo A implémenter
  66. def check_data_consistency(self, emcomponent, fname, datas):
  67. return True
  68. ## @brief given a field type name, returns the associated python class
  69. # @param fieldtype_name str : A field type name
  70. # @return DataField child class
  71. @staticmethod
  72. def from_name(data_handler_name):
  73. data_handler_name = data_handler_name.lower()
  74. mod = None
  75. for mname in FieldDataHandler.modules_name(data_handler_name):
  76. try:
  77. mod = importlib.import_module(mname)
  78. except ImportError:
  79. pass
  80. if mod is None:
  81. raise NameError("Unknown data_handler name : '%s'" % data_handler_name)
  82. return mod.DataHandler
  83. ## @brief get a module name given a fieldtype name
  84. # @param fieldtype_name str : a field type name
  85. # @return a string representing a python module name
  86. @staticmethod
  87. def modules_name(fieldtype_name):
  88. return (
  89. 'lodel.leapi.datahandlers.data_fields.%s' % fieldtype_name,
  90. 'lodel.leapi.datahandlers.references.%s' % fieldtype_name
  91. )
  92. ## @brief __hash__ implementation for fieldtypes
  93. def __hash__(self):
  94. hash_dats = [self.__class__.__module__]
  95. for kdic in sorted([k for k in self.__dict__.keys() if not k.startswith('_')]):
  96. hash_dats.append((kdic, getattr(self, kdic)))
  97. return hash(tuple(hash_dats))