translator.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. from wtforms import FieldList, FormField
  2. from .iterators import iter_schema, iter_form
  3. from .utils import *
  4. from pydantic import ValidationError
  5. class SchemaToForm:
  6. _schema = None
  7. _errors = None
  8. def __init__(self, schema_class, form, lut=None):
  9. self.schema_class = schema_class
  10. self.form = form
  11. self.lut = lut if lut else lambda x: x
  12. def __call__(self, data):
  13. try:
  14. self._schema = self.schema_class(**data)
  15. self._errors = None
  16. except ValidationError as e:
  17. self._errors = defaultdict(list)
  18. for error in e.errors():
  19. light_error = {k: error[k] for k in error if k != 'loc'}
  20. recursive_dict_operation(
  21. self._errors,
  22. lambda d, k: d.setdefault(k, defaultdict(list)),
  23. lambda d, k: d[k].append(light_error),
  24. *error['loc']
  25. )
  26. self._errors = default_to_regular(self._errors)
  27. self._schema = self.schema_class.construct(data, self.schema_class.__fields__)
  28. @property
  29. def schema(self):
  30. return self._schema
  31. @property
  32. def errors(self):
  33. return self._errors
  34. @classmethod
  35. def get_item(cls, dict, key):
  36. for k in key:
  37. if is_int(k):
  38. sub_dict = dict[k]
  39. else:
  40. sub_dict = dict[k]
  41. return cls.get_item(sub_dict, key[1:])
  42. return dict
  43. @classmethod
  44. def get_field(cls, form, key):
  45. for k in key:
  46. if is_int(k):
  47. sub_form = form.entries[k]
  48. else:
  49. sub_form = getattr(form, k)
  50. return cls.get_field(sub_form, key[1:])
  51. return form
  52. @classmethod
  53. def get_schema(cls, schema, key):
  54. for k in key:
  55. if is_int(k):
  56. sub = schema[k]
  57. else:
  58. sub = getattr(schema, k)
  59. return cls.get_schema(sub, key[1:])
  60. return schema
  61. def set_data(self):
  62. for src_key, value in iter_schema(self.schema):
  63. dest_key = self.lut(src_key)
  64. dest_field = self.get_field(self.form, dest_key)
  65. dest_field.data = value
  66. def set_baked(self):
  67. for k, field in iter_form(self.form, leafs_only=False):
  68. field = self.get_field(self.form, k)
  69. if isinstance(field, FormField):
  70. field._baked_instance = self.get_schema(self.schema, k)
  71. def set_errors(self):
  72. for path, error_list in nested_dict_iter(self.errors):
  73. field = self.get_field(self.form, path)
  74. if isinstance(field, FormField):
  75. setattr(field.form, '_errors', error_list)
  76. else:
  77. setattr(field, 'errors', error_list)
  78. for path, error_list in nested_dict_iter(self.errors):
  79. paths_with_list = [
  80. (path[:n], path[n], path[n+1:])
  81. for n, val in enumerate(path) if is_int(val)
  82. ]
  83. for field_list, _, _ in paths_with_list:
  84. form = rgetattr(self.form, tuple(field_list))
  85. form.errors = [entry.errors for entry in form.entries]