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

utils.py 8.6 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. # Copyright 2020 Huawei Technologies Co., Ltd
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. # ============================================================================
  15. """Lineage writer utils."""
  16. import os
  17. from functools import wraps
  18. from marshmallow import ValidationError
  19. from mindinsight.lineagemgr.common.exceptions.error_code import LineageErrors, LineageErrorMsg
  20. from mindinsight.lineagemgr.common.exceptions.exceptions import LineageParamTypeError, LineageParamValueError
  21. from mindinsight.lineagemgr.common.log import logger as log
  22. from mindinsight.lineagemgr.common.validator.validate_path import safe_normalize_path
  23. from mindinsight.lineagemgr.querier.query_model import FIELD_MAPPING
  24. from mindinsight.utils.exceptions import MindInsightException
  25. class LineageParamRunContextError(MindInsightException):
  26. """The input parameter run_context error in lineage module."""
  27. def __init__(self, msg):
  28. super(LineageParamRunContextError, self).__init__(
  29. error=LineageErrors.PARAM_RUN_CONTEXT_ERROR,
  30. message=LineageErrorMsg.PARAM_RUN_CONTEXT_ERROR.value.format(msg),
  31. http_code=400
  32. )
  33. class LineageGetModelFileError(MindInsightException):
  34. """The get model file error in lineage module."""
  35. def __init__(self, msg):
  36. super(LineageGetModelFileError, self).__init__(
  37. error=LineageErrors.LINEAGE_GET_MODEL_FILE_ERROR,
  38. message=LineageErrorMsg.LINEAGE_GET_MODEL_FILE_ERROR.value.format(msg),
  39. http_code=400
  40. )
  41. class LineageLogError(MindInsightException):
  42. """The lineage collector error."""
  43. def __init__(self, msg):
  44. super(LineageLogError, self).__init__(
  45. error=LineageErrors.LOG_LINEAGE_INFO_ERROR,
  46. message=LineageErrorMsg.LOG_LINEAGE_INFO_ERROR.value.format(msg),
  47. http_code=400
  48. )
  49. def try_except(logger):
  50. """
  51. Catch or raise exceptions while collecting lineage.
  52. Args:
  53. logger (logger): The logger instance which logs the warning info.
  54. Returns:
  55. function, the decorator which we use to retry the decorated function.
  56. """
  57. def try_except_decorate(func):
  58. @wraps(func)
  59. def wrapper(self, *args, **kwargs):
  60. try:
  61. func(self, *args, **kwargs)
  62. except (AttributeError, MindInsightException,
  63. LineageParamRunContextError, LineageLogError,
  64. LineageGetModelFileError, IOError) as err:
  65. logger.error(err)
  66. try:
  67. raise_except = self.raise_exception
  68. except AttributeError:
  69. raise_except = False
  70. if raise_except is True:
  71. raise
  72. return wrapper
  73. return try_except_decorate
  74. def validate_int_params(int_param, param_name):
  75. """
  76. Verify the parameter which type is integer valid or not.
  77. Args:
  78. int_param (int): parameter that is integer,
  79. including epoch, dataset_batch_size, step_num
  80. param_name (str): the name of parameter,
  81. including epoch, dataset_batch_size, step_num
  82. Raises:
  83. MindInsightException: If the parameters are invalid.
  84. """
  85. if not isinstance(int_param, int) or int_param <= 0 or int_param > pow(2, 63) - 1:
  86. if param_name == 'step_num':
  87. log.error('Invalid step_num. The step number should be a positive integer.')
  88. raise MindInsightException(error=LineageErrors.PARAM_STEP_NUM_ERROR,
  89. message=LineageErrorMsg.PARAM_STEP_NUM_ERROR.value)
  90. if param_name == 'dataset_batch_size':
  91. log.error('Invalid dataset_batch_size. '
  92. 'The batch size should be a positive integer.')
  93. raise MindInsightException(error=LineageErrors.PARAM_BATCH_SIZE_ERROR,
  94. message=LineageErrorMsg.PARAM_BATCH_SIZE_ERROR.value)
  95. def validate_file_path(file_path, allow_empty=False):
  96. """
  97. Verify that the file_path is valid.
  98. Args:
  99. file_path (str): Input file path.
  100. allow_empty (bool): Whether file_path can be empty.
  101. Raises:
  102. MindInsightException: If the parameters are invalid.
  103. """
  104. try:
  105. if allow_empty and not file_path:
  106. return file_path
  107. return safe_normalize_path(file_path, raise_key='dataset_path', safe_prefixes=None)
  108. except ValidationError as error:
  109. log.error(str(error))
  110. raise MindInsightException(error=LineageErrors.PARAM_FILE_PATH_ERROR,
  111. message=str(error))
  112. EVAL_RUN_CONTEXT_ERROR_MSG_MAPPING = {
  113. 'metrics': LineageErrorMsg.PARAM_EVAL_METRICS_ERROR.value,
  114. }
  115. EVAL_RUN_CONTEXT_ERROR_MAPPING = {
  116. 'valid_dataset': LineageErrors.PARAM_DATASET_ERROR,
  117. 'metrics': LineageErrors.PARAM_EVAL_METRICS_ERROR
  118. }
  119. def validate_raise_exception(raise_exception):
  120. """
  121. Validate raise_exception.
  122. Args:
  123. raise_exception (bool): decide raise exception or not,
  124. if True, raise exception; else, catch exception and continue.
  125. Raises:
  126. MindInsightException: If the parameters are invalid.
  127. """
  128. if not isinstance(raise_exception, bool):
  129. log.error("Invalid raise_exception. It should be True or False.")
  130. raise MindInsightException(
  131. error=LineageErrors.PARAM_RAISE_EXCEPTION_ERROR,
  132. message=LineageErrorMsg.PARAM_RAISE_EXCEPTION_ERROR.value
  133. )
  134. def validate_user_defined_info(user_defined_info):
  135. """
  136. Validate user defined info, delete the item if its key is in lineage.
  137. Args:
  138. user_defined_info (dict): The user defined info.
  139. Raises:
  140. LineageParamTypeError: If the type of parameters is invalid.
  141. LineageParamValueError: If user defined keys have been defined in lineage.
  142. """
  143. if not isinstance(user_defined_info, dict):
  144. log.error("Invalid user defined info. It should be a dict.")
  145. raise LineageParamTypeError("Invalid user defined info. It should be dict.")
  146. for key, value in user_defined_info.items():
  147. if not isinstance(key, str):
  148. error_msg = "Dict key type {} is not supported in user defined info." \
  149. "Only str is permitted now.".format(type(key))
  150. log.error(error_msg)
  151. raise LineageParamTypeError(error_msg)
  152. if not isinstance(value, (int, str, float)):
  153. error_msg = "Dict value type {} is not supported in user defined info." \
  154. "Only str, int and float are permitted now.".format(type(value))
  155. log.error(error_msg)
  156. raise LineageParamTypeError(error_msg)
  157. field_map = set(FIELD_MAPPING.keys())
  158. user_defined_keys = set(user_defined_info.keys())
  159. insertion = list(field_map & user_defined_keys)
  160. if insertion:
  161. for key in insertion:
  162. user_defined_info.pop(key)
  163. raise LineageParamValueError("There are some keys have defined in lineage. "
  164. "Duplicated key(s): %s. " % insertion)
  165. def make_directory(path):
  166. """Make directory."""
  167. if path is None or not isinstance(path, str) or not path.strip():
  168. log.error("Invalid input path: %r.", path)
  169. raise LineageParamTypeError("Invalid path type")
  170. # convert relative path to abs path
  171. path = os.path.realpath(path)
  172. log.debug("The abs path is %r", path)
  173. # check path exist and its write permissions]
  174. if os.path.exists(path):
  175. real_path = path
  176. else:
  177. # All exceptions need to be caught because create directory maybe have some limit(permissions)
  178. log.debug("The directory(%s) doesn't exist, will create it", path)
  179. try:
  180. os.makedirs(path, exist_ok=True)
  181. real_path = path
  182. except PermissionError as err:
  183. log.error("No write permission on the directory(%r), error = %r", path, err)
  184. raise LineageParamTypeError("No write permission on the directory.")
  185. return real_path