import typing as t    import pandas as pd    from ..gui import Gui  from ..utils import _MapDict  from .data_format import _DataFormat  from .pandas_data_accessor import _PandasDataAccessor      class _ArrayDictDataAccessor(_PandasDataAccessor):      __types = (dict, list, tuple, _MapDict)        @staticmethod      def get_supported_classes() -> t.List[str]:          return [t.__name__ for t in _ArrayDictDataAccessor.__types]  # type: ignore        def __get_dataframe(self, value: t.Any) -> t.Union[t.List[pd.DataFrame], pd.DataFrame]:          if isinstance(value, list):              if not value or isinstance(value[0], (str, int, float, bool)):                  return pd.DataFrame({"0": value})              types = {type(x) for x in value}              if len(types) == 1:                  type_elt = next(iter(types), None)                  if type_elt == list:                      lengths = {len(x) for x in value}                      return (                          pd.DataFrame(value)                          if len(lengths) == 1                          else [pd.DataFrame({f"{i}/0": v}) for i, v in enumerate(value)]                      )                  elif type_elt == dict:                      return [pd.DataFrame(v) for v in value]                  elif type_elt == _MapDict:                      return [pd.DataFrame(v._dict) for v in value]                  elif type_elt == pd.DataFrame:                      return value                elif len(types) == 2 and list in types and pd.DataFrame in types:                  return [v if isinstance(v, pd.DataFrame) else pd.DataFrame({f"{i}/0": v}) for i, v in enumerate(value)]          elif isinstance(value, _MapDict):              return pd.DataFrame(value._dict)          return pd.DataFrame(value)        def get_col_types(self, var_name: str, value: t.Any) -> t.Union[None, t.Dict[str, str]]:  # type: ignore          if isinstance(value, _ArrayDictDataAccessor.__types):  # type: ignore              return super().get_col_types(var_name, self.__get_dataframe(value))          return None        def get_data(  # noqa: C901          self, guiApp: Gui, var_name: str, value: t.Any, payload: t.Dict[str, t.Any], data_format: _DataFormat      ) -> t.Dict[str, t.Any]:          if isinstance(value, _ArrayDictDataAccessor.__types):  # type: ignore              return super().get_data(guiApp, var_name, self.__get_dataframe(value), payload, data_format)          return {}


from .data_accessor import _DataAccessor  from .decimator import LTTB, RDP, MinMaxDecimator, ScatterDecimator  from .utils import Decimator


import inspect  import typing as t  from abc import ABC, abstractmethod    from .._warnings import _warn  from ..utils import _TaipyData  from .data_format import _DataFormat      class _DataAccessor(ABC):      _WS_DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%fZ"        @staticmethod      @abstractmethod      def get_supported_classes() -> t.List[str]:          pass        @abstractmethod      def get_data(          self, guiApp: t.Any, var_name: str, value: t.Any, payload: t.Dict[str, t.Any], data_format: _DataFormat      ) -> t.Dict[str, t.Any]:          pass        @abstractmethod      def get_col_types(self, var_name: str, value: t.Any) -> t.Dict[str, str]:          pass      class _InvalidDataAccessor(_DataAccessor):      @staticmethod      def get_supported_classes() -> t.List[str]:          return [type(None).__name__]        def get_data(          self, guiApp: t.Any, var_name: str, value: t.Any, payload: t.Dict[str, t.Any], data_format: _DataFormat      ) -> t.Dict[str, t.Any]:          return {}        def get_col_types(self, var_name: str, value: t.Any) -> t.Dict[str, str]:          return {}      class _DataAccessors(object):      def __init__(self) -> None:          self.__access_4_type: t.Dict[str, _DataAccessor] = {}            self.__invalid_data_accessor = _InvalidDataAccessor()            self.__data_format = _DataFormat.JSON            from .array_dict_data_accessor import _ArrayDictDataAccessor          from .numpy_data_accessor import _NumpyDataAccessor          from .pandas_data_accessor import _PandasDataAccessor            self._register(_PandasDataAccessor)          self._register(_ArrayDictDataAccessor)          self._register(_NumpyDataAccessor)        def _register(self, cls: t.Type[_DataAccessor]) -> None:          if not inspect.isclass(cls):              raise AttributeError("The argument of 'DataAccessors.register' should be a class")          if not issubclass(cls, _DataAccessor):              raise TypeError(f"Class {cls.__name__} is not a subclass of DataAccessor")          names = cls.get_supported_classes()          if not names:              raise TypeError(f"method {cls.__name__}.get_supported_classes returned an invalid value")          # check existence          inst: t.Optional[_DataAccessor] = None          for name in names:              inst = self.__access_4_type.get(name)              if inst:                  break          if inst is None:              try:                  inst = cls()              except Exception as e:                  raise TypeError(f"Class {cls.__name__} cannot be instanciated") from e              if inst:                  for name in names:                      self.__access_4_type[name] = inst  # type: ignore        def __get_instance(self, value: _TaipyData) -> _DataAccessor:  # type: ignore          value = value.get()          access = self.__access_4_type.get(type(value).__name__)          if access is None:              _warn(f"Can't find Data Accessor for type {type(value).__name__}.")              return self.__invalid_data_accessor          return access        def _get_data(          self, guiApp: t.Any, var_name: str, value: _TaipyData, payload: t.Dict[str, t.Any]      ) -> t.Dict[str, t.Any]:          return self.__get_instance(value).get_data(guiApp, var_name, value.get(), payload, self.__data_format)        def _get_col_types(self, var_name: str, value: _TaipyData) -> t.Dict[str, str]:          return self.__get_instance(value).get_col_types(var_name, value.get())        def _set_data_format(self, data_format: _DataFormat):          self.__data_format = data_format


from __future__ import annotations    import typing as t  from abc import ABC, abstractmethod    import numpy as np    from .._warnings import _warn    if t.TYPE_CHECKING:      import pandas as pd      class Decimator(ABC):      """Base class for decimating chart data.        *Decimating* is the term used to name the process of reducing the number of      data points displayed in charts while retaining the overall shape of the traces.      `Decimator` is a base class that does decimation on data sets.        Taipy GUI comes out-of-the-box with several implementation of this class for      different use cases.      """        _CHART_MODES: t.List[str] = []        def __init__(self, threshold: t.Optional[int], zoom: t.Optional[bool]) -> None:          """Initialize a new `Decimator`.            Arguments:              threshold (Optional[int]): The minimum amount of data points before the                  decimator class is applied.              zoom (Optional[bool]): set to True to reapply the decimation                  when zoom or re-layout events are triggered.          """          super().__init__()          self.threshold = threshold          self._zoom = zoom if zoom is not None else True        def _is_applicable(self, data: t.Any, nb_rows_max: int, chart_mode: str):          if chart_mode not in self._CHART_MODES:              _warn(f"{type(self).__name__} is only applicable for {' '.join(self._CHART_MODES)}.")              return False          if self.threshold is None:              if nb_rows_max < len(data):                  return True          elif self.threshold < len(data):              return True          return False        @abstractmethod      def decimate(self, data: np.ndarray, payload: t.Dict[str, t.Any]) -> np.ndarray:          """Decimate function.            This method is executed when the appropriate conditions specified in the          constructor are met. This function implements the algorithm that determines          which data points are kept or dropped.            Arguments:              data (numpy.array): An array containing all the data points represented as                  tuples.              payload (Dict[str, any]): additional information on charts that is provided                  at runtime.            Returns:              An array of Boolean mask values. The array should set True or False for each                  of its indexes where True indicates that the corresponding data point                  from *data* should be preserved, or False requires that this                  data point be dropped.          """          return NotImplementedError  # type: ignore      def _df_data_filter(      dataframe: pd.DataFrame,      x_column_name: t.Optional[str],      y_column_name: str,      z_column_name: str,      decimator: Decimator,      payload: t.Dict[str, t.Any],      is_copied: bool,  ):      df = dataframe.copy() if not is_copied else dataframe      if not x_column_name:          index = 0          while f"tAiPy_index_{index}" in df.columns:              index += 1          x_column_name = f"tAiPy_index_{index}"          df[x_column_name] = df.index      column_list = [x_column_name, y_column_name, z_column_name] if z_column_name else [x_column_name, y_column_name]      points = df[column_list].to_numpy()      mask = decimator.decimate(points, payload)      return df[mask], is_copied      def _df_relayout(      dataframe: pd.DataFrame,      x_column: t.Optional[str],      y_column: str,      chart_mode: str,      x0: t.Optional[float],      x1: t.Optional[float],      y0: t.Optional[float],      y1: t.Optional[float],      is_copied: bool,  ):      if chart_mode not in ["lines+markers", "markers"]:          return dataframe, is_copied      # if chart data is invalid      if x0 is None or x1 is None or y0 is None or y1 is None:          return dataframe, is_copied      df = dataframe.copy() if not is_copied else dataframe      is_copied = True      has_x_col = True        if not x_column:          index = 0          while f"tAiPy_index_{index}" in df.columns:              index += 1          x_column = f"tAiPy_index_{index}"          df[x_column] = df.index          has_x_col = False        # if chart_mode is empty      if chart_mode == "lines+markers":          # only filter by x column          df = df.loc[(df[x_column] > x0) & (df[x_column] < x1)]      else:          # filter by both x and y columns          df = df.loc[(df[x_column] > x0) & (df[x_column] < x1) & (df[y_column] > y0) & (df[y_column] < y1)]  # noqa      if not has_x_col:          df.drop(x_column, axis=1, inplace=True)      return df, is_copied


from enum import Enum      class _DataFormat(Enum):      JSON = "JSON"      APACHE_ARROW = "ARROW"


import base64  import pathlib  import tempfile  import typing as t  import urllib.parse  from importlib import util  from pathlib import Path  from sys import getsizeof    from .._warnings import _warn  from ..utils import _get_non_existent_file_path, _variable_decode    _has_magic_module = False    if util.find_spec("magic"):      import magic        _has_magic_module = True      class _ContentAccessor:      def __init__(self, data_url_max_size: int) -> None:          self.__content_paths: t.Dict[str, pathlib.Path] = {}          self.__url_is_image: t.Dict[str, bool] = {}          self.__paths: t.Dict[pathlib.Path, str] = {}          self.__data_url_max_size = data_url_max_size          self.__temp_dir_path = Path(tempfile.gettempdir())        def get_path(self, path: pathlib.Path) -> str:          url_path = self.__paths.get(path)          if url_path is None:              self.__paths[path] = url_path = "taipyStatic" + str(len(self.__paths))          return url_path        def get_content_path(          self, url_path: str, file_name: str, bypass: t.Optional[str]      ) -> t.Tuple[t.Union[pathlib.Path, None], bool]:          content_path = self.__content_paths.get(url_path)          if not content_path:              return (None, True)          return (content_path, bypass is not None or self.__url_is_image.get(f"{url_path}/{file_name}", False))        def __get_mime_from_file(self, path: pathlib.Path):          if _has_magic_module:              try:                  return magic.from_file(str(path), mime=True)              except Exception as e:                  _warn(f"Exception reading mime type in '{path}'", e)          return None        def __get_display_name(self, var_name: str) -> str:          if not isinstance(var_name, str):              return var_name          if var_name.startswith("_tpC_"):              var_name = var_name[5:]          if var_name.startswith("tpec_"):              var_name = var_name[5:]          return _variable_decode(var_name)[0]        def get_info(self, var_name: str, value: t.Any, image: bool) -> t.Union[str, t.Tuple[str], t.Any]:  # noqa: C901          if value is None:              return ""          newvalue = value          mime = None          if not isinstance(newvalue, (str, pathlib.Path)) and (              getsizeof(newvalue) > self.__data_url_max_size or not _has_magic_module          ):              # write data to file              file_name = "TaiPyContent.bin"              if _has_magic_module:                  try:                      mime = magic.from_buffer(value, mime=True)                      file_name = "TaiPyContent." + mime.split("/")[-1]                  except Exception as e:                      _warn(f"{self.__get_display_name(var_name)} ({type(value)}) cannot be typed", e)              file_path = _get_non_existent_file_path(self.__temp_dir_path, file_name)              try:                  with open(file_path, "wb") as temp_file:                      temp_file.write(value)              except Exception as e:                  _warn(f"{self.__get_display_name(var_name)} ({type(value)}) cannot be written to file {file_path}", e)              newvalue = file_path          if isinstance(newvalue, (str, pathlib.Path)):              path = pathlib.Path(newvalue) if isinstance(newvalue, str) else newvalue              if not path.is_file():                  if (                      var_name != "Gui.download"                      and not str(path).startswith("http")                      and not str(path).startswith("/")                      and not str(path).strip().lower().startswith("<svg")                  ):                      _warn(f"{self.__get_display_name(var_name)}: file '{value}' does not exist.")                  return str(value)              if image:                  if not mime:                      mime = self.__get_mime_from_file(path)                  if mime and not mime.startswith("image"):                      _warn(f"{self.__get_display_name(var_name)}: file '{path}' mime type ({mime}) is not an image.")                      return f"Invalid content: {mime}"              dir_path = path.resolve().parent              url_path = self.get_path(dir_path)              self.__content_paths[url_path] = dir_path              file_url = f"{url_path}/{path.name}"              self.__url_is_image[file_url] = image              return (urllib.parse.quote_plus(file_url, safe="/"),)          elif _has_magic_module:              try:                  mime = magic.from_buffer(value, mime=True)                  if not image or mime.startswith("image"):                      return f"data:{mime};base64," + str(base64.b64encode(value), "utf-8")                  _warn(f"{self.__get_display_name(var_name)}: ({type(value)}) does not have an image mime type: {mime}.")                  return f"Invalid content: {mime}"              except Exception as e:                  _warn(f"{self.__get_display_name(var_name)}: ({type(value)}) cannot be base64 encoded", e)                  return "Cannot be base64 encoded"          else:              _warn(                  "python-magic (and python-magic-bin on Windows) packages need to be installed if you want to process content as an array of bytes."              )              return "Cannot guess content type"


from __future__ import annotations    import typing as t  from types import SimpleNamespace    from .._warnings import _warn      class _DataScopes:      _GLOBAL_ID = "global"        def __init__(self) -> None:          self.__scopes: t.Dict[str, SimpleNamespace] = {_DataScopes._GLOBAL_ID: SimpleNamespace()}          self.__single_client = True        def set_single_client(self, value: bool) -> None:          self.__single_client = value        def is_single_client(self) -> bool:          return self.__single_client        def get_scope(self, client_id: t.Optional[str]) -> SimpleNamespace:          if self.__single_client:              return self.__scopes[_DataScopes._GLOBAL_ID]          # global context in case request is not registered or client_id is not available (such as in the context of running tests)          if not client_id:              _warn("Empty session id, using global scope instead.")              return self.__scopes[_DataScopes._GLOBAL_ID]          if client_id not in self.__scopes:              _warn(                  f"Session id {client_id} not found in data scope. Taipy will automatically create a scope for this session id but you may have to reload your page."              )              self.create_scope(client_id)          return self.__scopes[client_id]        def get_all_scopes(self) -> t.Dict[str, SimpleNamespace]:          return self.__scopes        def create_scope(self, id: str) -> None:          if self.__single_client:              return          if id is None:              _warn("Empty session id, might be due to unestablished WebSocket connection.")              return          if id not in self.__scopes:              self.__scopes[id] = SimpleNamespace()        def delete_scope(self, id: str) -> None:  # pragma: no cover          if self.__single_client:              return          if id is None:              _warn("Empty session id, might be due to unestablished WebSocket connection.")              return          if id in self.__scopes:              del self.__scopes[id]


import typing as t  from datetime import datetime  from importlib import util    import numpy as np  import pandas as pd    from .._warnings import _warn  from ..gui import Gui  from ..types import PropertyType  from ..utils import _RE_PD_TYPE, _get_date_col_str_name  from .data_accessor import _DataAccessor  from .data_format import _DataFormat  from .utils import _df_data_filter, _df_relayout    _has_arrow_module = False  if util.find_spec("pyarrow"):      _has_arrow_module = True      import pyarrow as pa      class _PandasDataAccessor(_DataAccessor):      __types = (pd.DataFrame,)        __INDEX_COL = "_tp_index"        __AGGREGATE_FUNCTIONS: t.List[str] = ["count", "sum", "mean", "median", "min", "max", "std", "first", "last"]        @staticmethod      def get_supported_classes() -> t.List[str]:          return [t.__name__ for t in _PandasDataAccessor.__types]  # type: ignore        @staticmethod      def __user_function(          row: pd.Series, gui: Gui, column_name: t.Optional[str], user_function: t.Callable, function_name: str      ) -> str:  # pragma: no cover          args = []          if column_name:              args.append(row[column_name])          args.extend((row.name, row))          if column_name:              args.append(column_name)          try:              return str(gui._call_function_with_state(user_function, args))          except Exception as e:              _warn(f"Exception raised when calling user function {function_name}()", e)          return ""        def __is_date_column(self, data: pd.DataFrame, col_name: str) -> bool:          col_types = data.dtypes[data.dtypes.index.astype(str) == col_name]          return len(col_types[col_types.astype(str).str.startswith("datetime")]) > 0  # type: ignore        def __build_transferred_cols(          self,          gui: Gui,          payload_cols: t.Any,          dataframe: pd.DataFrame,          styles: t.Optional[t.Dict[str, str]] = None,          tooltips: t.Optional[t.Dict[str, str]] = None,          is_copied: t.Optional[bool] = False,          new_indexes: t.Optional[np.ndarray] = None,          handle_nan: t.Optional[bool] = False,      ) -> pd.DataFrame:          if isinstance(payload_cols, list) and len(payload_cols):              col_types = dataframe.dtypes[dataframe.dtypes.index.astype(str).isin(payload_cols)]          else:              col_types = dataframe.dtypes          cols = col_types.index.astype(str).tolist()          if styles:              if not is_copied:                  # copy the df so that we don't "mess" with the user's data                  dataframe = dataframe.copy()                  is_copied = True              for k, v in styles.items():                  col_applied = False                  func = gui._get_user_function(v)                  if callable(func):                      col_applied = self.__apply_user_function(gui, func, k if k in cols else None, v, dataframe, "tps__")                  if not col_applied:                      dataframe[v] = v                  cols.append(col_applied or v)          if tooltips:              if not is_copied:                  # copy the df so that we don't "mess" with the user's data                  dataframe = dataframe.copy()                  is_copied = True              for k, v in tooltips.items():                  col_applied = False                  func = gui._get_user_function(v)                  if callable(func):                      col_applied = self.__apply_user_function(gui, func, k if k in cols else None, v, dataframe, "tpt__")                  cols.append(col_applied or v)          # deal with dates          datecols = col_types[col_types.astype(str).str.startswith("datetime")].index.tolist()  # type: ignore          if len(datecols) != 0:              if not is_copied:                  # copy the df so that we don't "mess" with the user's data                  dataframe = dataframe.copy()              tz = Gui._get_timezone()              for col in datecols:                  newcol = _get_date_col_str_name(cols, col)                  cols.append(newcol)                  re_type = _RE_PD_TYPE.match(str(col_types[col]))                  grps = re_type.groups() if re_type else ()                  if len(grps) > 4 and grps[4]:                      dataframe[newcol] = (                          dataframe[col]                          .dt.tz_convert("UTC")                          .dt.strftime(_DataAccessor._WS_DATE_FORMAT)                          .astype(str)                          .replace("nan", "NaT" if handle_nan else None)                      )                  else:                      dataframe[newcol] = (                          dataframe[col]                          .dt.tz_localize(tz)                          .dt.tz_convert("UTC")                          .dt.strftime(_DataAccessor._WS_DATE_FORMAT)                          .astype(str)                          .replace("nan", "NaT" if handle_nan else None)                      )                # remove the date columns from the list of columns              cols = list(set(cols) - set(datecols))          dataframe = dataframe.iloc[new_indexes] if new_indexes is not None else dataframe          dataframe = dataframe.loc[:, dataframe.dtypes[dataframe.dtypes.index.astype(str).isin(cols)].index]  # type: ignore          return dataframe        def __apply_user_function(          self,          gui: Gui,          user_function: t.Callable,          column_name: t.Optional[str],          function_name: str,          data: pd.DataFrame,          prefix: t.Optional[str],      ):          try:              new_col_name = f"{prefix}{column_name}__{function_name}" if column_name else function_name              data[new_col_name] = data.apply(                  _PandasDataAccessor.__user_function,                  axis=1,                  args=(gui, column_name, user_function, function_name),              )              return new_col_name          except Exception as e:              _warn(f"Exception raised when invoking user function {function_name}()", e)          return False        def __format_data(          self,          data: pd.DataFrame,          data_format: _DataFormat,          orient: str,          start: t.Optional[int] = None,          rowcount: t.Optional[int] = None,          data_extraction: t.Optional[bool] = None,          handle_nan: t.Optional[bool] = False,      ) -> t.Dict[str, t.Any]:          ret: t.Dict[str, t.Any] = {              "format": str(data_format.value),          }          if rowcount is not None:              ret["rowcount"] = rowcount          if start is not None:              ret["start"] = start          if data_extraction is not None:              ret["dataExtraction"] = data_extraction  # Extract data out of dictionary on front-end          if data_format == _DataFormat.APACHE_ARROW:              if not _has_arrow_module:                  raise RuntimeError("Cannot use Arrow as pyarrow package is not installed")              # Convert from pandas to Arrow              table = pa.Table.from_pandas(data)              # Create sink buffer stream              sink = pa.BufferOutputStream()              # Create Stream writer              writer = pa.ipc.new_stream(sink, table.schema)              # Write data to table              writer.write_table(table)              writer.close()              # End buffer stream              buf = sink.getvalue()              # Convert buffer to Python bytes and return              ret["data"] = buf.to_pybytes()              ret["orient"] = orient          else:              # Workaround for Python built in JSON encoder that does not yet support ignore_nan              ret["data"] = data.replace([np.nan, pd.NA], [None, None]).to_dict(orient=orient)  # type: ignore          return ret        def get_col_types(self, var_name: str, value: t.Any) -> t.Union[None, t.Dict[str, str]]:  # type: ignore          if isinstance(value, _PandasDataAccessor.__types):  # type: ignore              return {str(k): v for k, v in value.dtypes.apply(lambda x: x.name.lower()).items()}          elif isinstance(value, list):              ret_dict: t.Dict[str, str] = {}              for i, v in enumerate(value):                  ret_dict.update({f"{i}/{k}": v for k, v in v.dtypes.apply(lambda x: x.name.lower()).items()})              return ret_dict          return None        def __get_data(  # noqa: C901          self,          gui: Gui,          var_name: str,          value: pd.DataFrame,          payload: t.Dict[str, t.Any],          data_format: _DataFormat,          col_prefix: t.Optional[str] = "",      ) -> t.Dict[str, t.Any]:          columns = payload.get("columns", [])          if col_prefix:              columns = [c[len(col_prefix) :] if c.startswith(col_prefix) else c for c in columns]          ret_payload = {"pagekey": payload.get("pagekey", "unknown page")}          paged = not payload.get("alldata", False)          is_copied = False            # add index if not chart          if paged:              if _PandasDataAccessor.__INDEX_COL not in value.columns:                  value = value.copy()                  is_copied = True                  value[_PandasDataAccessor.__INDEX_COL] = value.index              if columns and _PandasDataAccessor.__INDEX_COL not in columns:                  columns.append(_PandasDataAccessor.__INDEX_COL)            # filtering          filters = payload.get("filters")          if isinstance(filters, list) and len(filters) > 0:              query = ""              vars = []              for fd in filters:                  col = fd.get("col")                  val = fd.get("value")                  action = fd.get("action")                  if isinstance(val, str):                      if self.__is_date_column(value, col):                          val = datetime.fromisoformat(val[:-1])                      vars.append(val)                  val = f"@vars[{len(vars) - 1}]" if isinstance(val, (str, datetime)) else val                  right = f".str.contains({val})" if action == "contains" else f" {action} {val}"                  if query:                      query += " and "                  query += f"`{col}`{right}"              try:                  value = value.query(query)                  is_copied = True              except Exception as e:                  _warn(f"Dataframe filtering: invalid query '{query}' on {value.head()}", e)            if paged:              aggregates = payload.get("aggregates")              applies = payload.get("applies")              if isinstance(aggregates, list) and len(aggregates) and isinstance(applies, dict):                  applies_with_fn = {                      k: v if v in _PandasDataAccessor.__AGGREGATE_FUNCTIONS else gui._get_user_function(v)                      for k, v in applies.items()                  }                    for col in columns:                      if col not in applies_with_fn.keys():                          applies_with_fn[col] = "first"                  try:                      value = value.groupby(aggregates).agg(applies_with_fn)                  except Exception:                      _warn(f"Cannot aggregate {var_name} with groupby {aggregates} and aggregates {applies}.")              inf = payload.get("infinite")              if inf is not None:                  ret_payload["infinite"] = inf              # real number of rows is needed to calculate the number of pages              rowcount = len(value)              # here we'll deal with start and end values from payload if present              if isinstance(payload["start"], int):                  start = int(payload["start"])              else:                  try:                      start = int(str(payload["start"]), base=10)                  except Exception:                      _warn(f'start should be an int value {payload["start"]}.')                      start = 0              if isinstance(payload["end"], int):                  end = int(payload["end"])              else:                  try:                      end = int(str(payload["end"]), base=10)                  except Exception:                      end = -1              if start < 0 or start >= rowcount:                  start = 0              if end < 0 or end >= rowcount:                  end = rowcount - 1              # deal with sort              order_by = payload.get("orderby")              if isinstance(order_by, str) and len(order_by):                  try:                      if value.columns.dtype.name == "int64":                          order_by = int(order_by)                      new_indexes = value[order_by].values.argsort(axis=0)                      if payload.get("sort") == "desc":                          # reverse order                          new_indexes = new_indexes[::-1]                      new_indexes = new_indexes[slice(start, end + 1)]                  except Exception:                      _warn(f"Cannot sort {var_name} on columns {order_by}.")                      new_indexes = slice(start, end + 1)  # type: ignore              else:                  new_indexes = slice(start, end + 1)  # type: ignore              value = self.__build_transferred_cols(                  gui,                  columns,                  value,                  styles=payload.get("styles"),                  tooltips=payload.get("tooltips"),                  is_copied=is_copied,                  new_indexes=new_indexes,                  handle_nan=payload.get("handlenan", False),              )              dictret = self.__format_data(                  value, data_format, "records", start, rowcount, handle_nan=payload.get("handlenan", False)              )          else:              ret_payload["alldata"] = True              decimator_payload: t.Dict[str, t.Any] = payload.get("decimatorPayload", {})              decimators = decimator_payload.get("decimators", [])              nb_rows_max = decimator_payload.get("width")              for decimator_pl in decimators:                  decimator = decimator_pl.get("decimator")                  decimator_instance = (                      gui._get_user_instance(decimator, PropertyType.decimator.value) if decimator is not None else None                  )                  if isinstance(decimator_instance, PropertyType.decimator.value):                      x_column, y_column, z_column = (                          decimator_pl.get("xAxis", ""),                          decimator_pl.get("yAxis", ""),                          decimator_pl.get("zAxis", ""),                      )                      chart_mode = decimator_pl.get("chartMode", "")                      if decimator_instance._zoom and "relayoutData" in decimator_payload and not z_column:                          relayoutData = decimator_payload.get("relayoutData", {})                          x0 = relayoutData.get("xaxis.range[0]")                          x1 = relayoutData.get("xaxis.range[1]")                          y0 = relayoutData.get("yaxis.range[0]")                          y1 = relayoutData.get("yaxis.range[1]")                            value, is_copied = _df_relayout(                              value, x_column, y_column, chart_mode, x0, x1, y0, y1, is_copied                          )                        if nb_rows_max and decimator_instance._is_applicable(value, nb_rows_max, chart_mode):                          try:                              value, is_copied = _df_data_filter(                                  value,                                  x_column,                                  y_column,                                  z_column,                                  decimator=decimator_instance,                                  payload=decimator_payload,                                  is_copied=is_copied,                              )                              gui._call_on_change(f"{var_name}.{decimator}.nb_rows", len(value))                          except Exception as e:                              _warn(f"Limit rows error with {decimator} for Dataframe", e)              value = self.__build_transferred_cols(gui, columns, value, is_copied=is_copied)              dictret = self.__format_data(value, data_format, "list", data_extraction=True)          ret_payload["value"] = dictret          return ret_payload        def get_data(          self, gui: Gui, var_name: str, value: t.Any, payload: t.Dict[str, t.Any], data_format: _DataFormat      ) -> t.Dict[str, t.Any]:          if isinstance(value, list):              # If is_chart data              if payload.get("alldata", False):                  ret_payload = {                      "alldata": True,                      "value": {"multi": True},                      "pagekey": payload.get("pagekey", "unknown page"),                  }                  data = []                  for i, v in enumerate(value):                      ret = (                          self.__get_data(gui, var_name, v, payload, data_format, f"{i}/")                          if isinstance(v, pd.DataFrame)                          else {}                      )                      ret_val = ret.get("value", {})                      data.append(ret_val.pop("data", None))                      ret_payload.get("value", {}).update(ret_val)                  ret_payload["value"]["data"] = data                  return ret_payload              else:                  value = value[0]          if isinstance(value, _PandasDataAccessor.__types):  # type: ignore              return self.__get_data(gui, var_name, value, payload, data_format)          return {}


import typing as t    import numpy as np    from ..utils import Decimator      class ScatterDecimator(Decimator):      """A decimator designed for scatter charts.        This algorithm fits the data points into a grid. If multiple points are in the same grid      cell, depending on the chart configuration, some points are removed to reduce the number      points being displayed.        This class can only be used with scatter charts.      """        _CHART_MODES = ["markers"]        def __init__(          self,          binning_ratio: t.Optional[float] = None,          max_overlap_points: t.Optional[int] = None,          threshold: t.Optional[int] = None,          zoom: t.Optional[bool] = True,      ):          """Initialize a new `ScatterDecimator`.            Arguments:              binning_ratio (Optional[float]): the size of the data grid for the algorithm.                  The higher the value, the smaller the grid size.              max_overlap_points (Optional(int)): the maximum number of points for a single cell                  within the data grid within the algorithm. This dictates how dense a single                  grid cell can be.              threshold (Optional[int]): The minimum amount of data points before the                  decimation is applied.              zoom (Optional[bool]): set to True to reapply the decimation                  when zoom or re-layout events are triggered.          """          super().__init__(threshold, zoom)          binning_ratio = binning_ratio if binning_ratio is not None else 1          self._binning_ratio = binning_ratio if binning_ratio > 0 else 1          self._max_overlap_points = max_overlap_points if max_overlap_points is not None else 3        def decimate(self, data: np.ndarray, payload: t.Dict[str, t.Any]) -> np.ndarray:          n_rows = data.shape[0]          mask = np.empty(n_rows, dtype=bool)          width = payload.get("width", None)          height = payload.get("height", None)          if width is None or height is None:              mask.fill(True)              return mask          mask.fill(False)          grid_x, grid_y = round(width / self._binning_ratio), round(height / self._binning_ratio)          x_col, y_col = data[:, 0], data[:, 1]          min_x, max_x = np.amin(x_col), np.amax(x_col)          min_y, max_y = np.amin(y_col), np.amax(y_col)          min_max_x_diff, min_max_y_diff = max_x - min_x, max_y - min_y          x_grid_map = np.rint((x_col - min_x) * grid_x / min_max_x_diff).astype(int)          y_grid_map = np.rint((y_col - min_y) * grid_y / min_max_y_diff).astype(int)          z_grid_map = None          grid_shape = (grid_x + 1, grid_y + 1)          if len(data[0]) == 3:              grid_z = grid_x              grid_shape = (grid_x + 1, grid_y + 1, grid_z + 1)  # type: ignore              z_col = data[:, 2]              min_z, max_z = np.amin(z_col), np.amax(z_col)              min_max_z_diff = max_z - min_z              z_grid_map = np.rint((z_col - min_z) * grid_z / min_max_z_diff).astype(int)          grid = np.empty(grid_shape, dtype=int)          grid.fill(0)          if z_grid_map is not None:              for i in np.arange(n_rows):                  if grid[x_grid_map[i], y_grid_map[i], z_grid_map[i]] < self._max_overlap_points:                      grid[x_grid_map[i], y_grid_map[i], z_grid_map[i]] += 1                      mask[i] = True          else:              for i in np.arange(n_rows):                  if grid[x_grid_map[i], y_grid_map[i]] < self._max_overlap_points:                      grid[x_grid_map[i], y_grid_map[i]] += 1                      mask[i] = True          return mask


from .lttb import LTTB  from .minmax import MinMaxDecimator  from .rdp import RDP  from .scatter_decimator import ScatterDecimator


import typing as t    import numpy as np    from ..utils import Decimator      class MinMaxDecimator(Decimator):      """A decimator using the MinMax algorithm.        The MinMax algorithm is an efficient algorithm that preserves the peaks within the data. It      can work very well with noisy signal data where data peeks need to be highlighted.        This class can only be used with line charts.      """        _CHART_MODES = ["lines+markers"]        def __init__(self, n_out: int, threshold: t.Optional[int] = None, zoom: t.Optional[bool] = True):          """Initialize a new `MinMaxDecimator`.            Arguments:              n_out (int): The maximum number of points that will be displayed after decimation.              threshold (Optional[int]): The minimum amount of data points before the                  decimation is applied.              zoom (Optional[bool]): set to True to reapply the decimation                  when zoom or re-layout events are triggered.          """          super().__init__(threshold, zoom)          self._n_out = n_out // 2        def decimate(self, data: np.ndarray, payload: t.Dict[str, t.Any]) -> np.ndarray:          if self._n_out >= data.shape[0]:              return np.full(len(data), False)          # Create a boolean mask          x = data[:, 0]          y = data[:, 1]          num_bins = self._n_out          pts_per_bin = x.size // num_bins          # Create temp to hold the reshaped & slightly cropped y          y_temp = y[: num_bins * pts_per_bin].reshape((num_bins, pts_per_bin))          # use argmax/min to get column locations          cc_max = np.argmax(y_temp, axis=1)          cc_min = np.argmin(y_temp, axis=1)          rr = np.arange(0, num_bins)          # compute the flat index to where these are          flat_max = cc_max + rr * pts_per_bin          flat_min = cc_min + rr * pts_per_bin          mm_mask = np.full((x.size,), False)          mm_mask[flat_max] = True          mm_mask[flat_min] = True          return mm_mask


import typing as t    import numpy as np    from ..utils import Decimator      class LTTB(Decimator):      """A decimator using the LTTB algorithm.        The LTTB algorithm is an high performance algorithm that significantly reduces the number of      data points. It can work very well with time-series data to show trends using by using only      a few data points.        This class can only be used with line charts.      """        _CHART_MODES = ["lines+markers"]        def __init__(self, n_out: int, threshold: t.Optional[int] = None, zoom: t.Optional[bool] = True) -> None:          """Initialize a new `LTTB`.            Arguments:              n_out (int): The maximum number of points that will be displayed after decimation.              threshold (Optional[int]): The minimum amount of data points before the                  decimation is applied.              zoom (Optional[bool]): set to True to reapply the decimation                  when zoom or re-layout events are triggered.          """          super().__init__(threshold, zoom)          self._n_out = n_out        @staticmethod      def _areas_of_triangles(a, bs, c):          bs_minus_a = bs - a          a_minus_bs = a - bs          return 0.5 * abs((a[0] - c[0]) * (bs_minus_a[:, 1]) - (a_minus_bs[:, 0]) * (c[1] - a[1]))        def decimate(self, data: np.ndarray, payload: t.Dict[str, t.Any]) -> np.ndarray:          n_out = self._n_out          if n_out >= data.shape[0]:              return np.full(len(data), True)            if n_out < 3:              raise ValueError("Can only down-sample to a minimum of 3 points")            # Split data into bins          n_bins = n_out - 2          data_bins = np.array_split(data[1:-1], n_bins)            prev_a = data[0]          start_pos = 0            # Prepare output mask array          # First and last points are the same as in the input.          out_mask = np.full(len(data), False)          out_mask[0] = True          out_mask[len(data) - 1] = True            # Largest Triangle Three Buckets (LTTB):          # In each bin, find the point that makes the largest triangle          # with the point saved in the previous bin          # and the centroid of the points in the next bin.          for i in range(len(data_bins)):              this_bin = data_bins[i]              next_bin = data_bins[i + 1] if i < n_bins - 1 else data[-1:]              a = prev_a              bs = this_bin              c = next_bin.mean(axis=0)                areas = LTTB._areas_of_triangles(a, bs, c)              bs_pos = np.argmax(areas)              prev_a = bs[bs_pos]              out_mask[start_pos + bs_pos] = True              start_pos += len(this_bin)            return out_mask


import typing as t    import numpy as np    from ..utils import Decimator      class RDP(Decimator):      """A decimator using the RDP algorithm.        The RDP algorithm reduces a shape made of line segments into a similar shape with      less points. This algorithm should be used if the final visual representation is      prioritized over the performance of the application.        This class can only be used with line charts.      """        _CHART_MODES = ["lines+markers"]        def __init__(          self,          epsilon: t.Optional[int] = None,          n_out: t.Optional[int] = None,          threshold: t.Optional[int] = None,          zoom: t.Optional[bool] = True,      ):          """Initialize a new `RDP`.            Arguments:              epsilon (Optional[int]): The epsilon value for the RDP algorithm. If this value                  is being used, the *n_out* argument is ignored.              n_out (Optional(int)): The maximum number of points that are displayed after                  decimation. This value is ignored if the epsilon value is used.<br/>                  This process is not very efficient so consider using `LTTB` or `MinMaxDecimator`                  if the provided data has more than 100.000 data points.              threshold (Optional[int]): The minimum amount of data points before the                  decimation is applied.              zoom (Optional[bool]): set to True to reapply the decimation                  when zoom or re-layout events are triggered.          """          super().__init__(threshold, zoom)          self._epsilon = epsilon          self._n_out = n_out        @staticmethod      def dsquared_line_points(P1, P2, points):          """          Calculate only squared distance, only needed for comparison          """          xdiff = P2[0] - P1[0]          ydiff = P2[1] - P1[1]          nom = (ydiff * points[:, 0] - xdiff * points[:, 1] + P2[0] * P1[1] - P2[1] * P1[0]) ** 2          denom = ydiff**2 + xdiff**2          return np.divide(nom, denom)        @staticmethod      def __rdp_epsilon(data, epsilon: int):          # initiate mask array          # same amount of points          mask = np.empty(data.shape[0], dtype=bool)            # Assume all points are valid and falsify those which are found          mask.fill(True)            # The stack to select start and end index          stack: t.List[t.Tuple[int, int]] = [(0, data.shape[0] - 1)]  # type: ignore            while stack:              # Pop the last item              (start, end) = stack.pop()                # nothing to calculate if no points in between              if end - start <= 1:                  continue                # Calculate distance to points              P1 = data[start]              P2 = data[end]              points = data[start + 1 : end]              dsq = RDP.dsquared_line_points(P1, P2, points)                mask_eps = dsq > epsilon**2                if mask_eps.any():                  # max point outside eps                  # Include index that was sliced out                  # Also include the start index to get absolute index                  # And not relative                  mid = np.argmax(dsq) + 1 + start                  stack.append((start, mid))  # type: ignore                  stack.append((mid, end))  # type: ignore                else:                  # Points in between are redundant                  mask[start + 1 : end] = False            return mask        @staticmethod      def __rdp_points(M, n_out):          M_len = M.shape[0]            if M_len <= n_out:              mask = np.empty(M_len, dtype=bool)              mask.fill(True)              return mask            weights = np.empty(M_len)          # weights.fill(0)          weights[0] = float("inf")          weights[M_len - 1] = float("inf")            stack = [(0, M_len - 1)]            while stack:              (start, end) = stack.pop()              if end - start <= 1:                  continue              dsq = RDP.dsquared_line_points(M[start], M[end], M[start + 1 : end])              max_dist_index = np.argmax(dsq) + start + 1              weights[max_dist_index] = np.amax(dsq)              stack.append((start, max_dist_index))              stack.append((max_dist_index, end))            maxTolerance = np.sort(weights)[M_len - n_out]            return weights >= maxTolerance        def decimate(self, data: np.ndarray, payload: t.Dict[str, t.Any]) -> np.ndarray:          if self._epsilon:              return RDP.__rdp_epsilon(data, self._epsilon)          elif self._n_out:              return RDP.__rdp_points(data, self._n_out)          raise RuntimeError("RDP Decimator failed to run. Fill in either 'epsilon' or 'n_out' value")


import typing as t    from ..utils.singleton import _Singleton    if t.TYPE_CHECKING:      from ._element import _Block      class _BuilderContextManager(object, metaclass=_Singleton):      def __init__(self):          self.__blocks: t.List["_Block"] = []        def push(self, element: "_Block") -> None:          self.__blocks.append(element)        def pop(self) -> t.Optional["_Block"]:          return self.__blocks.pop() if self.__blocks else None        def peek(self) -> t.Optional["_Block"]:          return self.__blocks[-1] if self.__blocks else None


from ._api_generator import _ElementApiGenerator  from ._element import html    # separate import for "Page" class so stubgen can properly generate pyi file  from .page import Page    _ElementApiGenerator().add_default()


import typing as t    from .._renderers import _Renderer  from ._context_manager import _BuilderContextManager  from ._element import _Block, _DefaultBlock, _Element      class Page(_Renderer):      """Page generator for the Builder API.        This class is used to create a page created with the Builder API.
      Instance of this class can be added to the application using `Gui.add_page()^`.        This class is typically be used as a Python Context Manager to add the elements.
      Here is how you can create a single-page application, creating the elements with code:      ```py      from taipy.gui import Gui      from taipy.gui.builder import Page, button        def do_something(state):          pass        with Page() as page:          button(label="Press me", on_action=do_something)        Gui(page).run()      ```      """        def __init__(self, element: t.Optional[_Element] = None, **kwargs) -> None:          """Initialize a new page.            Arguments:              element (*Element*): An optional element, defined in the `taipy.gui.builder` module,                  that is created in the page.
                  The default creates a `part` where several elements can be stored.          """          if element is None:              element = _DefaultBlock()          kwargs["content"] = element          super().__init__(**kwargs)        # Generate JSX from Element Object      def render(self, gui) -> str:          if self._base_element is None:              return "
No Base Element found for Page
"          return self._base_element._render(gui)        def add(self, *elements: _Element):          if not isinstance(self._base_element, _Block):              raise RuntimeError("Can't add child element to non-block element")          for element in elements:              if element not in self._base_element._children:                  self._base_element._children.append(element)          return self        def __enter__(self):          if self._base_element is None:              raise RuntimeError("Can't use context manager with missing block element for Page")          if not isinstance(self._base_element, _Block):              raise RuntimeError("Can't add child element to non-block element")          _BuilderContextManager().push(self._base_element)          return self        def __exit__(self, exc_type, exc_value, traceback):          _BuilderContextManager().pop()


import typing as t    from .._renderers.factory import _Factory      class _BuilderFactory(_Factory):      @staticmethod      def create_element(gui, element_type: str, properties: t.Dict[str, t.Any]) -> t.Tuple[str, str]:          builder_html = _Factory.call_builder(gui, element_type, properties, True)          if builder_html is None:              return f"<div>INVALID SYNTAX - Element is '{element_type}'", "div"          return builder_html  # type: ignore


from __future__ import annotations    import copy  import typing as t  from abc import ABC, abstractmethod  from collections.abc import Iterable    from ._context_manager import _BuilderContextManager  from ._factory import _BuilderFactory    if t.TYPE_CHECKING:      from ..gui import Gui      class _Element(ABC):      """NOT DOCUMENTED"""        _ELEMENT_NAME = ""      _DEFAULT_PROPERTY = ""        def __new__(cls, *args, **kwargs):          obj = super(_Element, cls).__new__(cls)          parent = _BuilderContextManager().peek()          if parent is not None:              parent.add(obj)          return obj        def __init__(self, *args, **kwargs):          self._properties: t.Dict[str, t.Any] = {}          if args and self._DEFAULT_PROPERTY != "":              self._properties = {self._DEFAULT_PROPERTY: args[0]}          self._properties.update(kwargs)          self.parse_properties()        def update(self, **kwargs):          self._properties.update(kwargs)          self.parse_properties()        # Convert property value to string      def parse_properties(self):          self._properties = {k: _Element._parse_property(v) for k, v in self._properties.items()}        # Get a deepcopy version of the properties      def _deepcopy_properties(self):          return copy.deepcopy(self._properties)        @staticmethod      def _parse_property(value: t.Any) -> t.Any:          if isinstance(value, (str, dict, Iterable)):              return value          if hasattr(value, "__name__"):              return str(getattr(value, "__name__"))          return str(value)        @abstractmethod      def _render(self, gui: "Gui") -> str:          pass      class _Block(_Element):      """NOT DOCUMENTED"""        def __init__(self, *args, **kwargs):          super().__init__(*args, **kwargs)          self._children: t.List[_Element] = []        def add(self, *elements: _Element):          for element in elements:              if element not in self._children:                  self._children.append(element)          return self        def __enter__(self):          _BuilderContextManager().push(self)          return self        def __exit__(self, exc_type, exc_value, traceback):          _BuilderContextManager().pop()        def _render(self, gui: "Gui") -> str:          el = _BuilderFactory.create_element(gui, self._ELEMENT_NAME, self._deepcopy_properties())          return f"{el[0]}{self._render_children(gui)}</{el[1]}>"        def _render_children(self, gui: "Gui") -> str:          return "\n".join([child._render(gui) for child in self._children])      class _DefaultBlock(_Block):      _ELEMENT_NAME = "part"        def __init__(self, *args, **kwargs):          super().__init__(*args, **kwargs)      class html(_Block):      """A visual element defined as an HTML tag.        Use this class to integrate raw HTML to your page.        This element can be used as a block element.      """        def __init__(self, *args, **kwargs):          """Create a new `html` block.            Arguments:              args (any[]): A list of one or two unnamed arguments:                    - *args[0]* is the HTML tag name. If empty or None, this represents an HTML text                    node.                  - *args[1]* (optional) is the text of this element.
                    Note that special HTML characters (such as '<' or '&') do not need to be protected.              kwargs (dict[str, any]): the HTML attributes for this element.
                  These should be valid attribute names, with valid attribute values.            Examples:              - To generate `<br/>`, use:                 ```                 html("br")                 ```              - To generate `<h1>My page title</h1>`, use:                 ```                 html("h1", "My page title")                 ```              - To generate `<h1 id="page-title">My page title</h1>`, use:                 ```                 html("h1", "My page title", id="page-title")                 ```              - To generate `<p>This is a <b>Taipy GUI</b> element.</p>`, use:                 ```                 with html("p"):                     html(None, "This is a ")                     html("b", "Taipy GUI")                     html(None, " element.")                 ```          """          super().__init__(*args, **kwargs)          if not args:              raise RuntimeError("Can't render html element. Missing html tag name.")          self._ELEMENT_NAME = args[0] if args[0] else None          self._content = args[1] if len(args) > 1 else ""        def _render(self, gui: "Gui") -> str:          if self._ELEMENT_NAME:              attrs = ""              if self._properties:                  attrs = " " + " ".join([f'{k}="{str(v)}"' for k, v in self._properties.items()])              return f"<{self._ELEMENT_NAME}{attrs}>{self._content}{self._render_children(gui)}</{self._ELEMENT_NAME}>"          else:              return self._content      class _Control(_Element):      """NOT DOCUMENTED"""        def __init__(self, *args, **kwargs):          super().__init__(*args, **kwargs)        def _render(self, gui: "Gui") -> str:          el = _BuilderFactory.create_element(gui, self._ELEMENT_NAME, self._deepcopy_properties())          return (              f"
{el[0]}</{el[1]}>
"              if f"<{el[1]}" in el[0] and f"</{el[1]}" not in el[0]              else f"
{el[0]}
"          )        def __enter__(self):          raise RuntimeError(f"Can't use Context Manager for control type '{self._ELEMENT_NAME}'")        def __exit__(self, exc_type, exc_value, traceback):          raise RuntimeError(f"Can't use Context Manager for control type '{self._ELEMENT_NAME}'")


import inspect  import json  import os  import sys  import types  import typing as t    from taipy.logger._taipy_logger import _TaipyLogger    from ..utils.singleton import _Singleton  from ._element import _Block, _Control    if t.TYPE_CHECKING:      from ..extension.library import ElementLibrary      class _ElementApiGenerator(object, metaclass=_Singleton):      def __init__(self):          self.__module: t.Optional[types.ModuleType] = None        @staticmethod      def find_default_property(property_list: t.List[t.Dict[str, t.Any]]) -> str:          for property in property_list:              if "default_property" in property and property["default_property"] is True:                  return property["name"]          return ""        def add_default(self):          current_frame = inspect.currentframe()          error_message = "Cannot generate elements API for the current module"          if current_frame is None:              raise RuntimeError(f"{error_message}: No frame found.")          if current_frame.f_back is None:              raise RuntimeError(f"{error_message}: taipy-gui module not found.")          module_name = current_frame.f_back.f_globals["__name__"]          self.__module = module = sys.modules[module_name]          with open(os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "viselements.json"))) as viselements:              data = json.load(viselements)              if "blocks" not in data or "controls" not in data:                  raise RuntimeError(f"{error_message}: Invalid viselements.json file.")              for blockElement in data["blocks"]:                  default_property = _ElementApiGenerator.find_default_property(blockElement[1]["properties"])                  setattr(                      module,                      blockElement[0],                      _ElementApiGenerator.create_block_api(blockElement[0], blockElement[0], default_property),                  )              for controlElement in data["controls"]:                  default_property = _ElementApiGenerator.find_default_property(controlElement[1]["properties"])                  setattr(                      module,                      controlElement[0],                      _ElementApiGenerator.create_control_api(controlElement[0], controlElement[0], default_property),                  )        def add_library(self, library: "ElementLibrary"):          library_name = library.get_name()          if self.__module is None:              _TaipyLogger._get_logger().info(                  f"Python API for extension library '{library_name}' is not available. To fix this, import 'taipy.gui.builder' before importing the extension library."              )              return          library_module = getattr(self.__module, library_name, None)          if library_module is None:              library_module = types.ModuleType(library_name)              setattr(self.__module, library_name, library_module)          for element_name, element in library.get_elements().items():              setattr(                  library_module,                  element_name,                  _ElementApiGenerator().create_control_api(                      element_name, f"{library_name}.{element_name}", element.default_attribute                  ),              )        @staticmethod      def create_block_api(          classname: str,          element_name: str,          default_property: str,      ):          return _ElementApiGenerator.create_element_api(classname, element_name, default_property, _Block)        @staticmethod      def create_control_api(          classname: str,          element_name: str,          default_property: str,      ):          return _ElementApiGenerator.create_element_api(classname, element_name, default_property, _Control)        @staticmethod      def create_element_api(          classname: str,          element_name: str,          default_property: str,          ElementBaseClass: t.Union[t.Type[_Block], t.Type[_Control]],      ):          return type(              classname,              (ElementBaseClass,),              {                  "__init__": lambda self, *args, **kwargs: ElementBaseClass.__init__(self, *args, **kwargs),                  "_ELEMENT_NAME": element_name,                  "_DEFAULT_PROPERTY": default_property,              },          )


import typing as t  from abc import ABC, abstractmethod  from os import path    from ..page import Page  from ..utils import _is_in_notebook, _varname_from_content  from ._html import _TaipyHTMLParser    if t.TYPE_CHECKING:      from ..builder._element import _Element      from ..gui import Gui      class _Renderer(Page, ABC):      def __init__(self, **kwargs) -> None:          """NOT DOCUMENTED          Initialize a new _Renderer with the indicated content.            Arguments:              content (str): The text content or the path to the file holding the text to be transformed.            If *content* is a path to a readable file, the file is read entirely as the text template.          """          from ..builder._element import _Element            super().__init__(**kwargs)          content: t.Optional[t.Union[str, _Element]] = kwargs.get("content", None)          if content is None:              raise ValueError("'content' argument is missing for class '_Renderer'")          self._content = ""          self._base_element: t.Optional[_Element] = None          self._filepath = ""          if isinstance(content, str):              self.__process_content(content)          elif isinstance(content, _Element):              self._base_element = content          else:              raise ValueError(                  f"'content' argument has incorrect type '{type(content).__name__}'. This must be a string or an Builder element."              )        def __process_content(self, content: str) -> None:          if path.exists(content) and path.isfile(content):              return self.__parse_file_content(content)          if self._frame is not None:              frame_dir_path = path.dirname(path.abspath(self._frame.f_code.co_filename))              content_path = path.join(frame_dir_path, content)              if path.exists(content_path) and path.isfile(content_path):                  return self.__parse_file_content(content_path)          self._content = content        def __parse_file_content(self, content):          with open(t.cast(str, content), "r") as f:              self._content = f.read()              # Save file path for error handling              self._filepath = content        def set_content(self, content: str) -> None:          """Set a new page content.            Reads the new page content and reinitializes the `Page^` instance to reflect the change.            !!! important              This function can only be used in an IPython notebook context.            Arguments:              content (str): The text content or the path to the file holding the text to be transformed.                  If *content* is a path to a readable file, the file is read entirely as the text                  template.            Exceptions:              RuntimeError: If this method is called outside an IPython notebook context.          """          if not _is_in_notebook():              raise RuntimeError("'set_content()' must be used in an IPython notebook context")          self.__process_content(content)        def _get_content_detail(self, gui: "Gui") -> str:          if self._filepath:              return f"in file '{self._filepath}'"          if varname := _varname_from_content(gui, self._content):              return f"in variable '{varname}'"          return ""        @abstractmethod      def render(self, gui: "Gui") -> str:          pass      class _EmptyPage(_Renderer):      def __init__(self) -> None:          super().__init__(content="<PageContent />")        def render(self, gui: "Gui") -> str:          return self._content      class Markdown(_Renderer):      """Page generator for *Markdown* text.        Taipy can use Markdown text to create pages that are the base of      user interfaces.        You can find details on the Taipy Markdown-specific syntax and how to add      Taipy Visual Elements in the [section on HTML](../gui/pages/index.md#using-markdown)      of the User Manual.      """        def __init__(self, content: str, **kwargs) -> None:          """Initialize a new `Markdown` page.            Arguments:              content (str): The text content or the path to the file holding the Markdown text                  to be transformed.
                  If _content_ is a path to a readable file, the file is read as the Markdown                  template content.          """          kwargs["content"] = content          super().__init__(**kwargs)        # Generate JSX from Markdown      def render(self, gui: "Gui") -> str:          return gui._markdown.convert(self._content)      class Html(_Renderer):      """Page generator for *HTML* text.        Taipy can use HTML code to create pages that are the base of      user interfaces.        You can find details on HTML-specific constructs and how to add      Taipy Visual Elements in the [section on HTML](../gui/pages/index.md#using-html)      of the User Manual.      """        def __init__(self, content: str, **kwargs) -> None:          """Initialize a new `Html` page.            Arguments:              content (str): The text content or the path to the file holding the HTML text to                  be transformed.
                  If *content* is a path to a readable file, the file is read as the HTML                  template content.          """          kwargs["content"] = content          super().__init__(**kwargs)          self.head = None        # Modify path routes      def modify_taipy_base_url(self, base_url):          self._content = self._content.replace("{{taipy_base_url}}", f"{base_url}")        # Generate JSX from HTML      def render(self, gui: "Gui") -> str:          parser = _TaipyHTMLParser(gui)          parser.feed_data(self._content)          self.head = parser.head          return parser.get_jsx()


import re  import typing as t  from datetime import datetime    from ..types import PropertyType  from .builder import _Builder    if t.TYPE_CHECKING:      from ..extension.library import ElementLibrary      from ..gui import Gui      class _Factory:      DEFAULT_CONTROL = "text"        _START_SUFFIX = ".start"      _END_SUFFIX = ".end"        __TAIPY_NAME_SPACE = "taipy."        __CONTROL_DEFAULT_PROP_NAME = {          "button": "label",          "chart": "data",          "content": "value",          "date": "date",          "date_range": "dates",          "dialog": "open",          "expandable": "title",          "file_download": "content",          "file_selector": "content",          "image": "content",          "indicator": "display",          "input": "value",          "layout": "columns",          "menu": "lov",          "navbar": "value",          "number": "value",          "pane": "open",          "part": "class_name",          "selector": "value",          "slider": "value",          "status": "value",          "table": "data",          "text": "value",          "toggle": "value",          "tree": "value",      }        _TEXT_ATTRIBUTES = ["format", "id", "hover_text", "raw"]        __TEXT_ANCHORS = ["bottom", "top", "left", "right"]      __TEXT_ANCHOR_NONE = "none"        __LIBRARIES: t.Dict[str, t.List["ElementLibrary"]] = {}        __CONTROL_BUILDERS = {          "button": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="Button",              attributes=attrs,          )          .set_value_and_default(with_update=False)          .set_attributes(              [                  ("id",),                  ("on_action", PropertyType.function),                  ("active", PropertyType.dynamic_boolean, True),                  ("hover_text", PropertyType.dynamic_string),              ]          ),          "chart": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="Chart",              attributes=attrs,          )          .set_value_and_default(with_default=False, var_type=PropertyType.data)          .set_attributes(              [                  ("id",),                  ("title",),                  ("width", PropertyType.string_or_number),                  ("height", PropertyType.string_or_number),                  ("layout", PropertyType.dynamic_dict),                  ("plot_config", PropertyType.dict),                  ("on_range_change", PropertyType.function),                  ("active", PropertyType.dynamic_boolean, True),                  ("render", PropertyType.dynamic_boolean, True),                  ("hover_text", PropertyType.dynamic_string),                  ("on_change", PropertyType.function),                  ("template", PropertyType.dict),                  ("template[dark]", PropertyType.dict, gui._get_config("chart_dark_template", None)),                  ("template[light]", PropertyType.dict),              ]          )          ._get_chart_config("scatter", "lines+markers")          ._set_propagate(),          "content": lambda gui, control_type, attrs: _Builder(              gui=gui, control_type=control_type, element_name="PageContent", attributes=attrs          ),          "date": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="DateSelector",              attributes=attrs,              default_value=datetime.fromtimestamp(0),          )          .set_value_and_default(var_type=PropertyType.date)          .set_attributes(              [                  ("with_time", PropertyType.boolean),                  ("id",),                  ("active", PropertyType.dynamic_boolean, True),                  ("editable", PropertyType.dynamic_boolean, True),                  ("hover_text", PropertyType.dynamic_string),                  ("label",),                  ("on_change", PropertyType.function),                  ("format",),              ]          )          ._set_propagate(),          "date_range": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="DateRange",              attributes=attrs,          )          .set_value_and_default(var_type=PropertyType.date_range)          .set_attributes(              [                  ("with_time", PropertyType.boolean),                  ("id",),                  ("active", PropertyType.dynamic_boolean, True),                  ("editable", PropertyType.dynamic_boolean, True),                  ("hover_text", PropertyType.dynamic_string),                  ("label_start",),                  ("label_end",),                  ("on_change", PropertyType.function),                  ("format",),              ]          )          ._set_propagate(),          "dialog": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="Dialog",              attributes=attrs,          )          .set_value_and_default(var_type=PropertyType.dynamic_boolean)          ._set_partial()  # partial should be set before page          .set_attributes(              [                  ("id",),                  ("page",),                  ("title",),                  ("on_action", PropertyType.function),                  ("close_label", PropertyType.string),                  ("labels", PropertyType.string_list),                  ("active", PropertyType.dynamic_boolean, True),                  ("width", PropertyType.string_or_number),                  ("height", PropertyType.string_or_number),                  ("hover_text", PropertyType.dynamic_string),              ]          )          ._set_propagate(),          "expandable": lambda gui, control_type, attrs: _Builder(              gui=gui, control_type=control_type, element_name="Expandable", attributes=attrs, default_value=None          )          .set_value_and_default()          ._set_partial()  # partial should be set before page          .set_attributes(              [                  ("id",),                  ("page",),                  ("expanded", PropertyType.dynamic_boolean, True, True, False),                  ("hover_text", PropertyType.dynamic_string),                  ("on_change", PropertyType.function),              ]          ),          "file_download": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="FileDownload",              attributes=attrs,          )          .set_value_and_default(var_name="label", with_update=False)          ._set_content("content", image=False)          .set_attributes(              [                  ("id",),                  ("on_action", PropertyType.function),                  ("active", PropertyType.dynamic_boolean, True),                  ("render", PropertyType.dynamic_boolean, True),                  ("auto", PropertyType.boolean, False),                  ("bypass_preview", PropertyType.boolean, True),                  ("name",),                  ("hover_text", PropertyType.dynamic_string),              ]          ),          "file_selector": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="FileSelector",              attributes=attrs,          )          .set_value_and_default(var_name="label", with_update=False)          ._set_file_content()          .set_attributes(              [                  ("id",),                  ("on_action", PropertyType.function),                  ("active", PropertyType.dynamic_boolean, True),                  ("multiple", PropertyType.boolean, False),                  ("extensions",),                  ("drop_message",),                  ("hover_text", PropertyType.dynamic_string),              ]          ),          "image": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="Image",              attributes=attrs,          )          .set_value_and_default(var_name="label", with_update=False)          ._set_content("content")          .set_attributes(              [                  ("id",),                  ("on_action", PropertyType.function),                  ("active", PropertyType.dynamic_boolean, True),                  ("width",),                  ("height",),                  ("hover_text", PropertyType.dynamic_string),              ]          ),          "indicator": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="Indicator",              attributes=attrs,          )          .set_value_and_default(with_update=False, native_type=True)          .set_attributes(              [                  ("id",),                  ("min", PropertyType.number),                  ("max", PropertyType.number),                  ("value", PropertyType.dynamic_number),                  ("format",),                  ("orientation"),                  ("hover_text", PropertyType.dynamic_string),                  ("width",),                  ("height",),              ]          ),          "input": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="Input",              attributes=attrs,          )          ._set_input_type("text", True)          .set_value_and_default()          ._set_propagate()          .set_attributes(              [                  ("id",),                  ("active", PropertyType.dynamic_boolean, True),                  ("hover_text", PropertyType.dynamic_string),                  ("on_change", PropertyType.function),                  ("on_action", PropertyType.function),                  ("action_keys",),                  ("label",),                  ("change_delay", PropertyType.number, gui._get_config("change_delay", None)),                  ("multiline", PropertyType.boolean, False),                  ("lines_shown", PropertyType.number, 5),              ]          ),          "layout": lambda gui, control_type, attrs: _Builder(              gui=gui, control_type=control_type, element_name="Layout", attributes=attrs, default_value=None          )          .set_value_and_default(with_default=False)          .set_attributes(              [                  ("id",),                  ("columns[mobile]",),                  ("gap",),              ]          ),          "menu": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="MenuCtl",              attributes=attrs,          )          ._get_adapter("lov")  # need to be called before set_lov          ._set_lov()          .set_attributes(              [                  ("id",),                  ("active", PropertyType.dynamic_boolean, True),                  ("label"),                  ("width"),                  ("width[mobile]",),                  ("on_action", PropertyType.function),                  ("inactive_ids", PropertyType.dynamic_list),                  ("hover_text", PropertyType.dynamic_string),              ]          )          ._set_propagate(),          "navbar": lambda gui, control_type, attrs: _Builder(              gui=gui, control_type=control_type, element_name="NavBar", attributes=attrs, default_value=None          )          ._get_adapter("lov", multi_selection=False)  # need to be called before set_lov          ._set_lov()          .set_attributes(              [                  ("id",),                  ("active", PropertyType.dynamic_boolean, True),                  ("hover_text", PropertyType.dynamic_string),              ]          ),          "number": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="Input",              attributes=attrs,              default_value=0,          )          ._set_input_type("number")          .set_value_and_default(var_type=PropertyType.dynamic_number)          ._set_propagate()          .set_attributes(              [                  ("id",),                  ("active", PropertyType.dynamic_boolean, True),                  ("hover_text", PropertyType.dynamic_string),                  ("on_change", PropertyType.function),                  ("on_action", PropertyType.function),                  ("label",),                  ("change_delay", PropertyType.number, gui._get_config("change_delay", None)),              ]          ),          "pane": lambda gui, control_type, attrs: _Builder(              gui=gui, control_type=control_type, element_name="Pane", attributes=attrs, default_value=None          )          .set_value_and_default(var_type=PropertyType.dynamic_boolean)          ._set_partial()  # partial should be set before page          .set_attributes(              [                  ("id",),                  ("page",),                  ("anchor", PropertyType.string, "left"),                  ("on_close", PropertyType.function),                  ("persistent", PropertyType.boolean, False),                  ("active", PropertyType.dynamic_boolean, True),                  ("width", PropertyType.string_or_number, "30vw"),                  ("height", PropertyType.string_or_number, "30vh"),                  ("hover_text", PropertyType.dynamic_string),                  ("on_change", PropertyType.function),              ]          )          ._set_propagate(),          "part": lambda gui, control_type, attrs: _Builder(              gui=gui, control_type=control_type, element_name="Part", attributes=attrs, default_value=None          )          ._set_partial()  # partial should be set before page          .set_attributes(              [                  ("id",),                  ("page", PropertyType.dynamic_string),                  ("render", PropertyType.dynamic_boolean, True),                  ("height", PropertyType.dynamic_string),                  ("content", PropertyType.toHtmlContent),              ]          ),          "selector": lambda gui, control_type, attrs: _Builder(              gui=gui, control_type=control_type, element_name="Selector", attributes=attrs, default_value=None          )          .set_value_and_default(with_default=False, var_type=PropertyType.lov_value)          ._get_adapter("lov")  # need to be called before set_lov          ._set_lov()          .set_attributes(              [                  ("active", PropertyType.dynamic_boolean, True),                  ("dropdown", PropertyType.boolean, False),                  ("filter", PropertyType.boolean),                  ("height", PropertyType.string_or_number),                  ("hover_text", PropertyType.dynamic_string),                  ("id",),                  ("value_by_id", PropertyType.boolean),                  ("multiple", PropertyType.boolean),                  ("width", PropertyType.string_or_number),                  ("on_change", PropertyType.function),                  ("label",),              ]          )          ._set_propagate(),          "slider": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="Slider",              attributes=attrs,              default_value=0,          )          .set_value_and_default(native_type=True, var_type=PropertyType.slider_value)          .set_attributes(              [                  ("active", PropertyType.dynamic_boolean, True),                  ("height"),                  ("hover_text", PropertyType.dynamic_string),                  ("id",),                  ("value_by_id", PropertyType.boolean),                  ("max", PropertyType.number, 100),                  ("min", PropertyType.number, 0),                  ("orientation"),                  ("width", PropertyType.string, "300px"),                  ("on_change", PropertyType.function),                  ("continuous", PropertyType.boolean, True),                  ("lov", PropertyType.lov),                  ("change_delay", PropertyType.number, gui._get_config("change_delay", None)),              ]          )          ._set_labels()          ._set_string_with_check("text_anchor", _Factory.__TEXT_ANCHORS + [_Factory.__TEXT_ANCHOR_NONE], "bottom")          ._set_propagate(),          "status": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="Status",              attributes=attrs,          )          .set_value_and_default(with_update=False)          .set_attributes(              [                  ("id",),                  ("without_close", PropertyType.boolean, False),                  ("hover_text", PropertyType.dynamic_string),              ]          ),          "table": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="Table",              attributes=attrs,          )          .set_value_and_default(with_default=False, var_type=PropertyType.data)          ._get_dataframe_attributes()          .set_attributes(              [                  ("page_size", PropertyType.number, "100"),                  ("allow_all_rows", PropertyType.boolean),                  ("show_all", PropertyType.boolean),                  ("auto_loading", PropertyType.boolean),                  ("width", PropertyType.string_or_number, "100%"),                  ("height", PropertyType.string_or_number, "80vh"),                  ("id",),                  ("active", PropertyType.dynamic_boolean, True),                  ("editable", PropertyType.dynamic_boolean, True),                  ("on_edit", PropertyType.function),                  ("on_delete", PropertyType.function),                  ("on_add", PropertyType.function),                  ("on_action", PropertyType.function),                  ("nan_value",),                  ("filter", PropertyType.boolean),                  ("hover_text", PropertyType.dynamic_string),                  ("size",),              ]          )          ._set_propagate()          ._get_list_attribute("selected", PropertyType.number)          ._set_table_pagesize_options(),          "text": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="Field",              attributes=attrs,          )          .set_value_and_default(with_update=False)          ._set_dataType()          .set_attributes(              [                  ("format",),                  ("id",),                  ("hover_text", PropertyType.dynamic_string),                  ("raw", PropertyType.boolean, False),                  ("mode", PropertyType.string),              ]          ),          "toggle": lambda gui, control_type, attrs: _Builder(              gui=gui, control_type=control_type, element_name="Toggle", attributes=attrs, default_value=None          )          .set_value_and_default(with_default=False, var_type=PropertyType.lov_value)          ._get_adapter("lov", multi_selection=False)  # need to be called before set_lov          ._set_lov()          .set_attributes(              [                  ("active", PropertyType.dynamic_boolean, True),                  ("hover_text", PropertyType.dynamic_string),                  ("id",),                  ("label",),                  ("value_by_id", PropertyType.boolean),                  ("unselected_value", PropertyType.string, ""),                  ("allow_unselect", PropertyType.boolean),                  ("on_change", PropertyType.function),              ]          )          ._set_kind()          ._set_propagate(),          "tree": lambda gui, control_type, attrs: _Builder(              gui=gui,              control_type=control_type,              element_name="TreeView",              attributes=attrs,          )          .set_value_and_default(with_default=False, var_type=PropertyType.lov_value)          .set_attributes(              [                  ("active", PropertyType.dynamic_boolean, True),                  ("expanded", PropertyType.boolean_or_list, True),                  ("filter", PropertyType.boolean),                  ("hover_text", PropertyType.dynamic_string),                  ("height", PropertyType.string_or_number),                  ("id",),                  ("value_by_id", PropertyType.boolean),                  ("multiple", PropertyType.boolean),                  ("width", PropertyType.string_or_number),                  ("on_change", PropertyType.function),                  ("select_leafs_only", PropertyType.boolean),                  ("row_height", PropertyType.string),                  ("lov", PropertyType.lov),              ]          )          ._set_propagate(),      }        # TODO: process \" in property value      _PROPERTY_RE = re.compile(r"\s+([a-zA-Z][\.a-zA-Z_$0-9]*(?:\[(?:.*?)\])?)=\"((?:(?:(?<=\\)\")|[^\"])*)\"")        @staticmethod      def set_library(library: "ElementLibrary"):          from ..extension.library import Element, ElementLibrary            if isinstance(library, ElementLibrary) and isinstance(library.get_name(), str) and library.get_elements():              elements = library.get_elements()              for name, element in elements.items():                  if isinstance(element, Element):                      element.check(name)              fact_lib = _Factory.__LIBRARIES.get(library.get_name())              if fact_lib is None:                  _Factory.__LIBRARIES.update({library.get_name(): [library]})              else:                  fact_lib.append(library)        @staticmethod      def get_default_property_name(control_name: str) -> t.Optional[str]:          name = (              control_name[: -len(_Factory._START_SUFFIX)]              if control_name.endswith(_Factory._START_SUFFIX)              else control_name[: -len(_Factory._END_SUFFIX)]              if control_name.endswith(_Factory._END_SUFFIX)              else control_name          )          name = name[len(_Factory.__TAIPY_NAME_SPACE) :] if name.startswith(_Factory.__TAIPY_NAME_SPACE) else name          prop = _Factory.__CONTROL_DEFAULT_PROP_NAME.get(name)          if prop is None:              _, _, element = _Factory.__get_library_element(name)              if element:                  prop = element.default_attribute          return prop        @staticmethod      def __get_library_element(name: str):          parts = name.split(".")          if len(parts) > 1:              element_name = ".".join(parts[1:])              for lib in _Factory.__LIBRARIES.get(parts[0], []):                  elts = lib.get_elements()                  if isinstance(elts, dict):                      element = elts.get(element_name)                      if element:                          return lib, element_name, element          else:              element_name = name              for libs in list(_Factory.__LIBRARIES.values()):                  for lib in libs:                      elts = lib.get_elements()                      if isinstance(elts, dict):                          element = elts.get(element_name)                          if element:                              return lib, element_name, element          return None, None, None        @staticmethod      def call_builder(          gui: "Gui", name: str, all_properties: t.Optional[t.Dict[str, t.Any]] = None, is_html: t.Optional[bool] = False      ) -> t.Optional[t.Union[t.Any, t.Tuple[str, str]]]:          name = name[len(_Factory.__TAIPY_NAME_SPACE) :] if name.startswith(_Factory.__TAIPY_NAME_SPACE) else name          builder = _Factory.__CONTROL_BUILDERS.get(name)          built = None          if builder is None:              lib, element_name, element = _Factory.__get_library_element(name)              if lib:                  from ..extension.library import Element                    if isinstance(element, Element):                      return element._call_builder(element_name, gui, all_properties, lib, is_html)          else:              built = builder(gui, name, all_properties)          if isinstance(built, _Builder):              return built._build_to_string() if is_html else built.el          return None