_page.py 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  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. # _Page for multipage support
  12. from __future__ import annotations
  13. import logging
  14. import re
  15. import typing as t
  16. import warnings
  17. from ._warnings import TaipyGuiAlwaysWarning
  18. if t.TYPE_CHECKING:
  19. from ._renderers import Page
  20. from .gui import Gui
  21. _DETECT_CLOSING_TAGS = re.compile(r"<([A-Z][-\w]*)(([^>\"]+\"[^\"]*\")*\s*)?(><\/\1>)", flags=re.MULTILINE)
  22. _SUBSTR_CLOSING_TAG = "<\\1\\2/>"
  23. class _Page(object):
  24. def __init__(self) -> None:
  25. self._rendered_jsx: t.Optional[str] = None
  26. self._renderer: t.Optional[Page] = None
  27. self._style: t.Optional[t.Union[str, t.Dict[str, t.Any]]] = None
  28. self._route: t.Optional[str] = None
  29. self._head: t.Optional[list] = None
  30. def render(self, gui: Gui, silent: t.Optional[bool] = False):
  31. if self._renderer is None:
  32. raise RuntimeError(f"Can't render page {self._route}: no renderer found")
  33. with warnings.catch_warnings(record=True) as w:
  34. warnings.resetwarnings()
  35. with gui._set_locals_context(self._renderer._get_module_name()):
  36. self._rendered_jsx = self._renderer.render(gui)
  37. if silent:
  38. s = ""
  39. for wm in w:
  40. if wm.category is TaipyGuiAlwaysWarning:
  41. s += f" - {wm.message}\n"
  42. if s:
  43. logging.warning("\033[1;31m\n" + s)
  44. else:
  45. if (
  46. self._rendered_jsx
  47. and isinstance(self._rendered_jsx, str)
  48. and (
  49. result := _DETECT_CLOSING_TAGS.sub(
  50. _SUBSTR_CLOSING_TAG,
  51. self._rendered_jsx.replace(">style</TaipyStyle>", "/>"),
  52. )
  53. )
  54. ):
  55. self._rendered_jsx = result
  56. if w:
  57. s = "\033[1;31m\n"
  58. s += (
  59. message
  60. := f"--- {len(w)} warning(s) were found for page '{'/' if self._route == gui._get_root_page_name() else self._route}' {self._renderer._get_content_detail(gui)} ---\n" # noqa: E501
  61. )
  62. for i, wm in enumerate(w):
  63. s += f" - Warning {i + 1}: {wm.message}\n"
  64. s += "-" * len(message)
  65. s += "\033[0m\n"
  66. logging.warning(s)
  67. if hasattr(self._renderer, "head"):
  68. self._head = list(self._renderer.head) # type: ignore
  69. # return renderer module_name from frame
  70. return self._renderer._get_module_name()