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.

datas_base.py 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. #-*- coding: utf-8 -*-
  2. import warnings
  3. import datetime
  4. import time
  5. import os
  6. from lodel.context import LodelContext
  7. LodelContext.expose_modules(globals(), {
  8. 'lodel.leapi.datahandlers.base_classes': ['DataField'],
  9. 'lodel.exceptions': ['LodelException', 'LodelExceptions',
  10. 'LodelFatalError', 'DataNoneValid', 'FieldValidationError']})
  11. ##
  12. ## @brief Data field designed to handle boolean values
  13. class Boolean(DataField):
  14. help = 'A basic boolean field'
  15. base_type = 'bool'
  16. ## @brief A boolean field
  17. def __init__(self, **kwargs):
  18. ##
  19. # @remarks Commented out code left in the code base. Consider deletion.
  20. #if 'check_data_value' not in kwargs:
  21. # kwargs['check_data_value'] = self._check_data_value
  22. super().__init__(ftype='bool', **kwargs)
  23. ##
  24. # @brief Checks value.
  25. #
  26. # @param value mixed:
  27. # @throw FieldValidationError: if value is not valid
  28. # @return value
  29. def _check_data_value(self, value):
  30. value = super()._check_data_value(value)
  31. if not isinstance(value, bool):
  32. raise FieldValidationError("The value '%s' is not, and will never, be a boolean" % value)
  33. return value
  34. ##
  35. # @brief Data field designed to handle integer values.
  36. class Integer(DataField):
  37. help = 'Basic integer field'
  38. base_type = 'int'
  39. cast_type = int
  40. def __init__(self, **kwargs):
  41. super().__init__(**kwargs)
  42. ##
  43. # @brief Checks and casts value in appropriate type
  44. #
  45. # @param value *:
  46. # @param strict bool: Whether the value type should be treated strictly or cast.
  47. # @throw FieldValidationError: if value is inappropriate or can not be cast
  48. # @return value
  49. def _check_data_value(self, value, strict=False):
  50. value = super()._check_data_value(value)
  51. if (strict and not isinstance(value, int)):
  52. raise FieldValidationError("The value '%s' is not a python type integer" % value)
  53. try:
  54. if strict:
  55. value = int(value)
  56. else:
  57. value = int(float(value))
  58. except(ValueError, TypeError):
  59. raise FieldValidationError("The value '%s' is not an integer nor could be cast to." % value)
  60. return value
  61. ##
  62. # @brief Data field designed to handle string
  63. class Varchar(DataField):
  64. help = 'Basic string (varchar) field. Default size is 64 characters'
  65. base_type = 'char'
  66. ##
  67. # @brief A string field
  68. #
  69. # @brief max_length int: The maximum length of this field
  70. def __init__(self, max_length=64, **kwargs):
  71. self.max_length = int(max_length)
  72. super().__init__(**kwargs)
  73. ##
  74. # @brief checks if this class can override the given data handler
  75. #
  76. # @param data_handler DataHandler
  77. # @return bool
  78. def can_override(self, data_handler):
  79. if not super().can_override(data_handler):
  80. return False
  81. if data_handler.max_length != self.max_length:
  82. return False
  83. return True
  84. ##
  85. # @brief Check and cast value in appropriate type
  86. #
  87. # @param value *:
  88. # @throw FieldValidationError if value is inappropriate or can not be cast
  89. # @return value
  90. def _check_data_value(self, value):
  91. value = super()._check_data_value(value)
  92. if not isinstance(value, str):
  93. raise FieldValidationError("The value '%s' can't be a str" % value)
  94. if len(value) > self.max_length:
  95. raise FieldValidationError("The value '%s' is longer than the maximum length of this field (%s)" % (value, self.max_length))
  96. return value
  97. ##
  98. # @brief Data field designed to handle date & time
  99. class DateTime(DataField):
  100. help = 'A datetime field. Take two boolean options now_on_update and now_on_create'
  101. base_type = 'datetime'
  102. ##
  103. # @brief A datetime field
  104. #
  105. # @param now_on_update bool : If true, the date is set to NOW on update
  106. # @param now_on_create bool : If true, the date is set to NEW on creation
  107. # @param **kwargs
  108. #
  109. # @remarks Is it intended that DateTime objects can not be instantiated with
  110. # a provided arbitrary string value or something else?
  111. def __init__(self, now_on_update=False, now_on_create=False, **kwargs):
  112. self.now_on_update = now_on_update
  113. self.now_on_create = now_on_create
  114. self.datetime_format = '%Y-%m-%d' if 'format' not in kwargs else kwargs['format']
  115. super().__init__(**kwargs)
  116. ##
  117. # @brief Check and cast value in appropriate type
  118. #
  119. # @param value mixed:
  120. # @throw FieldValidationError: if value is inappropriate or can not be cast
  121. # @return value
  122. def _check_data_value(self, value):
  123. value = super()._check_data_value(value)
  124. if isinstance(value, str):
  125. try:
  126. value = datetime.datetime.fromtimestamp(time.mktime(time.strptime(value, self.datetime_format)))
  127. except ValueError:
  128. raise FieldValidationError("The value '%s' cannot be converted as a datetime" % value)
  129. if not isinstance(value, datetime.datetime):
  130. raise FieldValidationError("Tue value has to be a string or a datetime")
  131. return value
  132. def _construct_data(self, emcomponent, fname, datas, cur_value):
  133. if (self.now_on_create and cur_value is None) or self.now_on_update:
  134. return datetime.datetime.now()
  135. return cur_value
  136. ##
  137. # @brief Data field designed to handle long string
  138. class Text(DataField):
  139. help = 'A text field (big string)'
  140. base_type = 'text'
  141. def __init__(self, **kwargs):
  142. super(self.__class__, self).__init__(ftype='text', **kwargs)
  143. ##
  144. # @brief Check and cast value in appropriate type
  145. #
  146. # @param value *
  147. # @throw FieldValidationError if value is unappropriate or can not be cast
  148. # @return value
  149. def _check_data_value(self, value):
  150. value = super()._check_data_value(value)
  151. if not isinstance(value, str):
  152. raise FieldValidationError("The content passed to this Text field is not a convertible to a string")
  153. return value
  154. ##
  155. # @brief Data field designed to handle Files
  156. class File(DataField):
  157. base_type = 'file'
  158. ##
  159. # @brief a file field
  160. #
  161. # @param upload_path str : None by default
  162. # @param **kwargs
  163. def __init__(self, upload_path=None, **kwargs):
  164. self.upload_path = upload_path
  165. super().__init__(**kwargs)
  166. ##
  167. # @todo Add a check for the validity of the given value (should have a correct path syntax)
  168. def _check_data_value(self, value):
  169. return super()._check_data_value(value)