py.lib

Yohn Y. 2022-08-19 Parent:f1a05e880961 Child:4f4cc2fc9805

37:ae0107755941 Browse Files

. Исправление ошибок и рефакторинг

config_parse_helper.py dataclass_utils.py

     1.1 --- a/config_parse_helper.py	Fri Aug 19 00:07:55 2022 +0300
     1.2 +++ b/config_parse_helper.py	Fri Aug 19 02:36:30 2022 +0300
     1.3 @@ -28,12 +28,12 @@
     1.4          self.like = like
     1.5          self.is_complex = is_complex
     1.6  
     1.7 -    def __instancecheck__(self, instance):
     1.8 +    def check(self, instance):
     1.9          if self.like is None:
    1.10              return False
    1.11  
    1.12          else:
    1.13 -            return isinstance(instance, self.like)
    1.14 +            return check_instance(instance, self.like)
    1.15  
    1.16      def __repr__(self):
    1.17          return f'<TypeDescriber({self.__name__}, {self.like})>'
    1.18 @@ -42,8 +42,31 @@
    1.19          if val is None:
    1.20              return None
    1.21  
    1.22 +        elif not self.is_complex and check_instance(val, self.like):
    1.23 +            return val
    1.24 +
    1.25          else:
    1.26 -           return self.cast(val)
    1.27 +            return self.cast(val)
    1.28 +
    1.29 +
    1.30 +def check_instance(obj, types):
    1.31 +    if types is None:
    1.32 +        return False
    1.33 +
    1.34 +    elif isinstance(types, (tuple, list)):
    1.35 +        _flag = False
    1.36 +        for t in types:
    1.37 +            if check_instance(obj, t):
    1.38 +                _flag = True
    1.39 +                break
    1.40 +
    1.41 +        return _flag
    1.42 +
    1.43 +    elif isinstance(types, TypeDescriber):
    1.44 +        return types.check(obj)
    1.45 +
    1.46 +    else:
    1.47 +        return isinstance(obj, types)
    1.48  
    1.49  
    1.50  def cast_iterator(t: Union[type, TypeDescriber], lst: Iterable):
    1.51 @@ -51,14 +74,16 @@
    1.52      Обрабатывает последовательности единого типа.
    1.53      """
    1.54      for i in lst:
    1.55 -        if isinstance(i, t):
    1.56 +        if check_instance(i, t):
    1.57              yield i
    1.58  
    1.59 -        try:
    1.60 -            yield t(i)
    1.61 +        else:
    1.62 +            try:
    1.63 +                yield t(i)
    1.64  
    1.65 -        except (TypeError, ValueError) as e:
    1.66 -            raise ValueError(f'Не удалось привести значение к нужному типу: тип={t.__name__}; знач={i}')
    1.67 +            except (TypeError, ValueError) as e:
    1.68 +                raise ValueError(f'Не удалось привести значение к нужному типу: '
    1.69 +                                 f'тип={t.__name__}; знач={i}')
    1.70  
    1.71  
    1.72  def multi_item_tuple(tt, val):
    1.73 @@ -78,14 +103,16 @@
    1.74      res = []
    1.75  
    1.76      for i in range(t_len):
    1.77 -        if isinstance(val[i], tt[i]):
    1.78 -            yield val[i]
    1.79 +        if check_instance(val[i], tt[i]):
    1.80 +            res.append(val[i])
    1.81  
    1.82 -        try:
    1.83 -            res.append(tt[i](val[i]))
    1.84 +        else:
    1.85 +            try:
    1.86 +                res.append(tt[i](val[i]))
    1.87  
    1.88 -        except (TypeError, ValueError) as e:
    1.89 -            raise ValueError(f'Не удалось привести значение к нужному типу: тип={tt[i].__name__}; знач={val[i]}')
    1.90 +            except (TypeError, ValueError) as e:
    1.91 +                raise ValueError(f'Не удалось привести значение к нужному типу: '
    1.92 +                                 f'тип={tt[i].__name__}; знач={val[i]}')
    1.93  
    1.94      return tuple(res)
    1.95  
    1.96 @@ -105,9 +132,14 @@
    1.97      if len(tt) == 0:
    1.98          raise ValueError('Не указан ни один тип в составном типе Union')
    1.99  
   1.100 -    for t in tt:
   1.101 +    sorted_types_begin = [ t for t in tt if t in (int, float, bool)]
   1.102 +    sorted_types_body = [ t for t in tt if t not in (int, float, bool, str)]
   1.103 +    sorted_types_end = [ t for t in tt if t == str]
   1.104 +
   1.105 +    for t in sorted_types_begin + sorted_types_body + sorted_types_end:
   1.106 +        _t = get_type_describer(t)
   1.107          try:
   1.108 -            res = t(val)
   1.109 +            res = _t(val)
   1.110              break
   1.111  
   1.112          except (TypeError, ValueError) as e:
     2.1 --- a/dataclass_utils.py	Fri Aug 19 00:07:55 2022 +0300
     2.2 +++ b/dataclass_utils.py	Fri Aug 19 02:36:30 2022 +0300
     2.3 @@ -30,12 +30,12 @@
     2.4          self.like = like
     2.5          self.is_complex = is_complex
     2.6  
     2.7 -    def __instancecheck__(self, instance):
     2.8 +    def check(self, instance):
     2.9          if self.like is None:
    2.10              return False
    2.11  
    2.12          else:
    2.13 -            return isinstance(instance, self.like)
    2.14 +            return check_instance(instance, self.like)
    2.15  
    2.16      def __repr__(self):
    2.17          return f'<TypeDescriber({self.__name__}, {self.like})>'
    2.18 @@ -44,8 +44,31 @@
    2.19          if val is None:
    2.20              return None
    2.21  
    2.22 +        elif not self.is_complex and check_instance(val, self.like):
    2.23 +            return val
    2.24 +
    2.25          else:
    2.26 -           return self.cast(val)
    2.27 +            return self.cast(val)
    2.28 +
    2.29 +
    2.30 +def check_instance(obj, types):
    2.31 +    if types is None:
    2.32 +        return False
    2.33 +
    2.34 +    elif isinstance(types, (tuple, list)):
    2.35 +        _flag = False
    2.36 +        for t in types:
    2.37 +            if check_instance(obj, t):
    2.38 +                _flag = True
    2.39 +                break
    2.40 +
    2.41 +        return _flag
    2.42 +
    2.43 +    elif isinstance(types, TypeDescriber):
    2.44 +        return types.check(obj)
    2.45 +
    2.46 +    else:
    2.47 +        return isinstance(obj, types)
    2.48  
    2.49  
    2.50  def cast_iterator(t: Union[type, TypeDescriber], lst: Iterable):
    2.51 @@ -53,14 +76,16 @@
    2.52      Обрабатывает последовательности единого типа.
    2.53      """
    2.54      for i in lst:
    2.55 -        if isinstance(i, t):
    2.56 +        if check_instance(i, t):
    2.57              yield i
    2.58  
    2.59 -        try:
    2.60 -            yield t(i)
    2.61 +        else:
    2.62 +            try:
    2.63 +                yield t(i)
    2.64  
    2.65 -        except (TypeError, ValueError) as e:
    2.66 -            raise ValueError(f'Не удалось привести значение к нужному типу: тип={t.__name__}; знач={i}')
    2.67 +            except (TypeError, ValueError) as e:
    2.68 +                raise ValueError(f'Не удалось привести значение к нужному типу: '
    2.69 +                                 f'тип={t.__name__}; знач={i}')
    2.70  
    2.71  
    2.72  def multi_item_tuple(tt, val):
    2.73 @@ -80,14 +105,16 @@
    2.74      res = []
    2.75  
    2.76      for i in range(t_len):
    2.77 -        if isinstance(val[i], tt[i]):
    2.78 -            yield val[i]
    2.79 +        if check_instance(val[i], tt[i]):
    2.80 +            res.append(val[i])
    2.81  
    2.82 -        try:
    2.83 -            res.append(tt[i](val[i]))
    2.84 +        else:
    2.85 +            try:
    2.86 +                res.append(tt[i](val[i]))
    2.87  
    2.88 -        except (TypeError, ValueError) as e:
    2.89 -            raise ValueError(f'Не удалось привести значение к нужному типу: тип={tt[i].__name__}; знач={val[i]}')
    2.90 +            except (TypeError, ValueError) as e:
    2.91 +                raise ValueError(f'Не удалось привести значение к нужному типу: '
    2.92 +                                 f'тип={tt[i].__name__}; знач={val[i]}')
    2.93  
    2.94      return tuple(res)
    2.95  
    2.96 @@ -107,9 +134,14 @@
    2.97      if len(tt) == 0:
    2.98          raise ValueError('Не указан ни один тип в составном типе Union')
    2.99  
   2.100 -    for t in tt:
   2.101 +    sorted_types_begin = [ t for t in tt if t in (int, float, bool)]
   2.102 +    sorted_types_body = [ t for t in tt if t not in (int, float, bool, str)]
   2.103 +    sorted_types_end = [ t for t in tt if t == str]
   2.104 +
   2.105 +    for t in sorted_types_begin + sorted_types_body + sorted_types_end:
   2.106 +        _t = get_type_describer(t)
   2.107          try:
   2.108 -            res = t(val)
   2.109 +            res = _t(val)
   2.110              break
   2.111  
   2.112          except (TypeError, ValueError) as e:
   2.113 @@ -134,9 +166,11 @@
   2.114  
   2.115      _p = []
   2.116  
   2.117 +    tt_cast = [get_type_describer(t) for t in tt]
   2.118 +
   2.119      for k, v in _d.items():
   2.120          try:
   2.121 -            _p.append((tt[0](k), tt[1](v)))
   2.122 +            _p.append((tt_cast[0](k), tt_cast[1](v)))
   2.123  
   2.124          except (TypeError, ValueError) as e:
   2.125              raise ValueError(f'Не удалось привести значения элемента словаря к требуемому типу: '
   2.126 @@ -224,7 +258,7 @@
   2.127          if len(_args) == 0:
   2.128              raise ValueError('Не указан ни один тип в конструкции Union')
   2.129  
   2.130 -        _cast_args = tuple(map(get_type_describer, _args))
   2.131 +        _cast_args = tuple(map(get_type_describer, [ i for i in _args if i is not None]))
   2.132          _args_name = ', '.join(map(lambda x: x.__name__, _args))
   2.133  
   2.134          return TypeDescriber(
   2.135 @@ -264,7 +298,7 @@
   2.136          if _has(obj, fld.name):
   2.137              val = _get(obj, fld.name)
   2.138              type_desc = get_type_describer(fld.type)
   2.139 -            if val is not None and not isinstance(val, type_desc):
   2.140 +            if val is not None:
   2.141                  try:
   2.142                      val = type_desc(val)
   2.143