table_col_builder.py 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. # Copyright 2021-2024 Avaiga Private Limited
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  4. # the License. You may obtain a copy of the License at
  5. #
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  9. # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
  10. # specific language governing permissions and limitations under the License.
  11. import re
  12. import typing as t
  13. from .._warnings import _warn
  14. from .boolean import _is_boolean, _is_true
  15. from .clientvarname import _to_camel_case
  16. def _get_column_desc(columns: t.Dict[str, t.Any], key: str) -> t.Optional[t.Dict[str, t.Any]]:
  17. return next((x for x in columns.values() if x.get("dfid") == key), None)
  18. def _get_name_indexed_property(attributes: t.Dict[str, t.Any], name: str) -> t.Dict[str, t.Any]:
  19. ret = {}
  20. index_re = re.compile(name + r"\[(.*)\]$")
  21. for key in attributes.keys():
  22. if m := index_re.match(key):
  23. ret[m.group(1)] = attributes.get(key)
  24. return ret
  25. def _update_col_desc_from_indexed(
  26. attributes: t.Dict[str, t.Any], columns: t.Dict[str, t.Any], name: str, elt_name: str
  27. ):
  28. col_value = _get_name_indexed_property(attributes, name)
  29. for k, v in col_value.items():
  30. if col_desc := next((x for x in columns.values() if x.get("dfid") == k), None):
  31. if col_desc.get(_to_camel_case(name)) is None:
  32. col_desc[_to_camel_case(name)] = str(v)
  33. else:
  34. _warn(f"{elt_name}: {name}[{k}] is not in the list of displayed columns.")
  35. def _enhance_columns( # noqa: C901
  36. attributes: t.Dict[str, t.Any], hash_names: t.Dict[str, str], columns: t.Dict[str, t.Any], elt_name: str
  37. ):
  38. _update_col_desc_from_indexed(attributes, columns, "nan_value", elt_name)
  39. _update_col_desc_from_indexed(attributes, columns, "width", elt_name)
  40. filters = _get_name_indexed_property(attributes, "filter")
  41. for k, v in filters.items():
  42. if _is_true(v):
  43. if col_desc := _get_column_desc(columns, k):
  44. col_desc["filter"] = True
  45. else:
  46. _warn(f"{elt_name}: filter[{k}] is not in the list of displayed columns.")
  47. editables = _get_name_indexed_property(attributes, "editable")
  48. for k, v in editables.items():
  49. if _is_boolean(v):
  50. if col_desc := _get_column_desc(columns, k):
  51. col_desc["notEditable"] = not _is_true(v)
  52. else:
  53. _warn(f"{elt_name}: editable[{k}] is not in the list of displayed columns.")
  54. group_by = _get_name_indexed_property(attributes, "group_by")
  55. for k, v in group_by.items():
  56. if _is_true(v):
  57. if col_desc := _get_column_desc(columns, k):
  58. col_desc["groupBy"] = True
  59. else:
  60. _warn(f"{elt_name}: group_by[{k}] is not in the list of displayed columns.")
  61. apply = _get_name_indexed_property(attributes, "apply")
  62. for k, v in apply.items(): # pragma: no cover
  63. if col_desc := _get_column_desc(columns, k):
  64. if callable(v):
  65. value = hash_names.get(f"apply[{k}]")
  66. elif isinstance(v, str):
  67. value = v.strip()
  68. else:
  69. _warn(f"{elt_name}: apply[{k}] should be a user or predefined function.")
  70. value = None
  71. if value:
  72. col_desc["apply"] = value
  73. else:
  74. _warn(f"{elt_name}: apply[{k}] is not in the list of displayed columns.")
  75. styles = _get_name_indexed_property(attributes, "style")
  76. for k, v in styles.items(): # pragma: no cover
  77. if col_desc := _get_column_desc(columns, k):
  78. if callable(v):
  79. value = hash_names.get(f"style[{k}]")
  80. elif isinstance(v, str):
  81. value = v.strip()
  82. else:
  83. value = None
  84. if value in columns.keys():
  85. _warn(f"{elt_name}: style[{k}] cannot reference a column's name '{value}'.")
  86. elif value:
  87. col_desc["style"] = value
  88. else:
  89. _warn(f"{elt_name}: style[{k}] is not in the list of displayed columns.")
  90. tooltips = _get_name_indexed_property(attributes, "tooltip")
  91. for k, v in tooltips.items(): # pragma: no cover
  92. if col_desc := _get_column_desc(columns, k):
  93. if callable(v):
  94. value = hash_names.get(f"tooltip[{k}]")
  95. elif isinstance(v, str):
  96. value = v.strip()
  97. else:
  98. value = None
  99. if value in columns.keys():
  100. _warn(f"{elt_name}: tooltip[{k}] cannot reference a column's name '{value}'.")
  101. elif value:
  102. col_desc["tooltip"] = value
  103. else:
  104. _warn(f"{elt_name}: tooltip[{k}] is not in the list of displayed columns.")
  105. formats = _get_name_indexed_property(attributes, "format_fn")
  106. for k, v in formats.items(): # pragma: no cover
  107. if col_desc := _get_column_desc(columns, k):
  108. if callable(v):
  109. value = hash_names.get(f"format_fn[{k}]")
  110. elif isinstance(v, str):
  111. value = v.strip()
  112. else:
  113. value = None
  114. if value in columns.keys():
  115. _warn(f"{elt_name}: format_fn[{k}] cannot reference a column's name '{value}'.")
  116. elif value:
  117. col_desc["formatFn"] = value
  118. else:
  119. _warn(f"{elt_name}: format_fn[{k}] is not in the list of displayed columns.")
  120. editable = attributes.get("editable", False)
  121. loveable = _is_boolean(editable) and _is_true(editable)
  122. loves = _get_name_indexed_property(attributes, "lov")
  123. for k, v in loves.items(): # pragma: no cover
  124. col_desc = _get_column_desc(columns, k)
  125. if col_desc and (
  126. loveable
  127. or not col_desc.get("notEditable", True)
  128. or t.cast(str, col_desc.get("type", "")).startswith("bool")
  129. ):
  130. value = v.strip().split(";") if isinstance(v, str) else v # type: ignore[assignment]
  131. if value is not None and not isinstance(value, (list, tuple)):
  132. _warn(f"{elt_name}: lov[{k}] should be a list.")
  133. value = None
  134. if value is not None:
  135. new_value = list(filter(lambda i: i is not None, value))
  136. if len(new_value) < len(value):
  137. col_desc["freeLov"] = True
  138. value = new_value
  139. col_desc["lov"] = value
  140. elif not col_desc:
  141. _warn(f"{elt_name}: lov[{k}] is not in the list of displayed columns.")
  142. return columns