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."  # noqa: E501              )              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."  # noqa: E501              )              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    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."  # noqa: E501              )              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  # noqa: F811            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."  # noqa: E501              )        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 typing as t    from .._warnings import _warn  from ..gui_types import NumberTypes  from ..utils import _RE_PD_TYPE, _get_date_col_str_name, _MapDict      def _add_to_dict_and_get(dico: t.Dict[str, t.Any], key: str, value: t.Any) -> t.Any:      if key not in dico.keys():          dico[key] = value      return dico[key]      def _get_tuple_val(attr: tuple, index: int, default_val: t.Any) -> t.Any:      return attr[index] if len(attr) > index else default_val      def _get_columns_dict_from_list(      col_list: t.Union[t.List[str], t.Tuple[str]], col_types_keys: t.List[str], value: t.Any  ):      col_dict = {}      idx = 0      for col in col_list:          if col in col_types_keys:              col_dict[col] = {"index": idx}              idx += 1          elif col:              _warn(                  f'Error column "{col}" is not present in the Dataframe "{value.head(0) if hasattr(value, "head") else value}".'  # noqa: E501              )      return col_dict      def _get_columns_dict(  # noqa: C901      value: t.Any,      columns: t.Union[str, t.List[str], t.Tuple[str], t.Dict[str, t.Any], _MapDict],      col_types: t.Optional[t.Dict[str, str]] = None,      date_format: t.Optional[str] = None,      number_format: t.Optional[str] = None,      opt_columns: t.Optional[t.Set[str]] = None,  ):      if col_types is None:          return None      col_dict: t.Optional[dict] = None      if isinstance(columns, str):          col_dict = _get_columns_dict_from_list([s.strip() for s in columns.split(";")], col_types_keys, value)      elif isinstance(columns, (list, tuple)):          col_dict = _get_columns_dict_from_list(columns, col_types_keys, value)      elif isinstance(columns, _MapDict):          col_dict = columns._dict.copy()      elif isinstance(columns, dict):          col_dict = columns.copy()      if not isinstance(col_dict, dict):          _warn("Error: columns attributes should be a string, a list, a tuple or a dict.")          col_dict = {}      nb_cols = len(col_dict)      if nb_cols == 0:          for col in col_types_keys:              col_dict[col] = {"index": nb_cols}              nb_cols += 1      else:          col_dict = {str(k): v for k, v in col_dict.items()}          if opt_columns:              for col in opt_columns:                  if col in col_types_keys and col not in col_dict:                      col_dict[col] = {"index": nb_cols}                      nb_cols += 1      idx = 0      for col, ctype in col_types.items():          col = str(col)          if col in col_dict:              re_type = _RE_PD_TYPE.match(ctype)              grps = re_type.groups() if re_type else ()              ctype = grps[0] if grps else ctype              col_dict[col]["type"] = ctype              col_dict[col]["dfid"] = col              if len(grps) > 4 and grps[4]:                  col_dict[col]["tz"] = grps[4]              idx = _add_to_dict_and_get(col_dict[col], "index", idx) + 1              if ctype == "datetime":                  if date_format:                      _add_to_dict_and_get(col_dict[col], "format", date_format)                  col_dict[_get_date_col_str_name(col_types.keys(), col)] = col_dict.pop(col)  # type: ignore              elif number_format and ctype in NumberTypes:                  _add_to_dict_and_get(col_dict[col], "format", number_format)      return col_dict


#  # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with  # the License. You may obtain a copy of the License at  #  #        http://www.apache.org/licenses/LICENSE-2.0  #  # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on  # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the  # specific language governing permissions and limitations under the License.  from __future__ import annotations    from datetime import date, datetime, time  from json import JSONEncoder  from pathlib import Path    from flask.json.provider import DefaultJSONProvider    from .._warnings import _warn  from ..icon import Icon  from ..utils import _date_to_string, _MapDict, _TaipyBase      def _default(o):      if isinstance(o, Icon):          return o._to_dict()      if isinstance(o, _MapDict):          return o._dict      if isinstance(o, _TaipyBase):          return o.get()      if isinstance(o, (datetime, date, time)):          return _date_to_string(o)      if isinstance(o, Path):          return str(o)      try:          raise TypeError(f"Object of type {o.__class__.__name__} is not JSON serializable")      except Exception as e:          _warn("Exception in JSONEncoder", e)          return None      class _TaipyJsonEncoder(JSONEncoder):      def default(self, o):          return _default(o)      class _TaipyJsonProvider(DefaultJSONProvider):      default = staticmethod(_default)  # type: ignore      sort_keys = False


from markdown.treeprocessors import Treeprocessor    from ..builder import _Builder      class _Postprocessor(Treeprocessor):      @staticmethod      def extend(md, gui, priority):          instance = _Postprocessor(md)          md.treeprocessors.register(instance, "taipy", priority)          instance._gui = gui        def run(self, root):          MD_PARA_CLASSNAME = "md-para"          for p in root.iter():              if p.tag == "p":                  classes = p.get("class")                  classes = f"{MD_PARA_CLASSNAME} {classes}" if classes else MD_PARA_CLASSNAME                  p.set("class", classes)                  p.tag = "div"              if p != root:                  p.set("key", _Builder._get_key(p.tag))          return root


from markdown.inlinepatterns import InlineProcessor    from .factory import _MarkdownFactory      class _ControlPattern(InlineProcessor):      __PATTERN = _MarkdownFactory._TAIPY_START + r"([a-zA-Z][\.a-zA-Z_$0-9]*)(.*?)" + _MarkdownFactory._TAIPY_END        @staticmethod      def extend(md, gui, priority):          instance = _ControlPattern(_ControlPattern.__PATTERN, md)          md.inlinePatterns.register(instance, "taipy", priority)          instance._gui = gui        def handleMatch(self, m, data):          return _MarkdownFactory.create_element(self._gui, m.group(1), m.group(2)), m.start(0), m.end(0)


import re    from markdown.blockprocessors import BlockProcessor    from .factory import _MarkdownFactory      class _StartBlockProcessor(BlockProcessor):      __RE_FENCE_START = re.compile(          _MarkdownFactory._TAIPY_START + r"([a-zA-Z][\.a-zA-Z_$0-9]*)\.start(.*?)" + _MarkdownFactory._TAIPY_END      )  # start line      __RE_OTHER_FENCE = re.compile(          _MarkdownFactory._TAIPY_START + r"([a-zA-Z][\.a-zA-Z_$0-9]*)\.(start|end)(.*?)" + _MarkdownFactory._TAIPY_END      )  # start or end tag        @staticmethod      def extend(md, gui, priority):          instance = _StartBlockProcessor(md.parser)          md.parser.blockprocessors.register(instance, "taipy", priority)          instance._gui = gui        def test(self, parent, block):          return re.match(_StartBlockProcessor.__RE_FENCE_START, block)        def run(self, parent, blocks):          original_block = blocks[0]          original_match = re.search(_StartBlockProcessor.__RE_FENCE_START, original_block)          blocks[0] = re.sub(_StartBlockProcessor.__RE_FENCE_START, "", blocks[0], 1)          tag = original_match.group(1)          queue = [tag]          # Find block with ending fence          for block_num, block in enumerate(blocks):              matches = re.findall(_StartBlockProcessor.__RE_OTHER_FENCE, block)              for match in matches:                  if queue[-1] == match[0] and match[1] == "end":                      queue.pop()                  elif match[1] == "start":                      queue.append(match[0])              if not queue:                  # remove end fence                  blocks[block_num] = re.sub(                      _MarkdownFactory._TAIPY_START + tag + r"\.end(.*?)" + _MarkdownFactory._TAIPY_END,                      "",                      block,                      1,                  )                  # render fenced area inside a new div                  e = _MarkdownFactory.create_element(self._gui, original_match.group(1), original_match.group(2))                  parent.append(e)                  # parse inside blocks                  self.parser.parseBlocks(e, blocks[: block_num + 1])                  # remove used blocks                  del blocks[: block_num + 1]                  return True  # or could have had no return statement          # No closing marker!  Restore and do nothing          blocks[0] = original_block          return False  # equivalent to our test() routine returning False


from typing import Any    from markdown.extensions import Extension    from .blocproc import _StartBlockProcessor  from .control import _ControlPattern  from .postproc import _Postprocessor  from .preproc import _Preprocessor      class _TaipyMarkdownExtension(Extension):      config = {"gui": ["", "Gui object for extension"]}        def extendMarkdown(self, md):          from ...gui import Gui            gui = self.config["gui"][0]          if not isinstance(gui, Gui):              raise RuntimeError("Gui instance is not bound to Markdown Extension")          md.registerExtension(self)          _Preprocessor.extend(md, gui, 210)          _ControlPattern.extend(md, gui, 205)          _StartBlockProcessor.extend(md, gui, 175)          _Postprocessor.extend(md, gui, 200)


import typing as t    from ..factory import _Factory      class _MarkdownFactory(_Factory):      # Taipy Markdown tags      _TAIPY_START = "TaIpY:"      _TAIPY_END = ":tAiPy"        _TAIPY_BLOCK_TAGS = ["layout", "part", "expandable", "dialog", "pane"]        @staticmethod      def create_element(gui, control_type: str, all_properties: str) -> t.Union[t.Any, str]:          # Create properties dict from all_properties          property_pairs = _Factory._PROPERTY_RE.findall(all_properties)          properties = {property[0]: property[1] for property in property_pairs}          builder_md = _Factory.call_builder(gui, control_type, properties)          if builder_md is None:              return f"<|INVALID SYNTAX - Control is '{control_type}'|>"          return builder_md


from .parser import _TaipyHTMLParser


import typing as t    from ..factory import _Factory      class _HtmlFactory(_Factory):      @staticmethod      def create_element(gui, namespace: str, control_type: str, all_properties: t.Dict[str, str]) -> t.Tuple[str, str]:          builder_html = _Factory.call_builder(gui, f"{namespace}.{control_type}", all_properties, True)          if builder_html is None:              return f"
INVALID SYNTAX - Control is '{namespace}:{control_type}'
", "div"          return builder_html  # type: ignore


import re  import typing as t  from html.parser import HTMLParser    from ..._warnings import _warn  from .factory import _HtmlFactory      class _TaipyHTMLParser(HTMLParser):      __TAIPY_NAMESPACE_RE = re.compile(r"([a-zA-Z\_]+):([a-zA-Z\_]*)")        def __init__(self, gui):          super().__init__()          self._gui = gui          self.body = ""          self.head = []          self.taipy_tag = None          self.tag_mapping = {}          self.is_body = True          self.head_tag = None          self._line_count = 0          self._tag_queue = []        # @override      def handle_starttag(self, tag, props) -> None:          self._tag_queue.append((tag, self._line_count))          if tag == "html":              return          if self.head_tag is not None:              self.head.append(self.head_tag)              self.head_tag = None          if self.taipy_tag is not None:              self.parse_taipy_tag()          if tag == "head":              self.is_body = False          elif tag == "body":              self.is_body = True          elif m := self.__TAIPY_NAMESPACE_RE.match(tag):              self.taipy_tag = _TaipyTag(m.group(1), m.group(2), props)          elif not self.is_body:              head_props = {prop[0]: prop[1] for prop in props}              self.head_tag = {"tag": tag, "props": head_props, "content": ""}          else:              self.append_data(str(self.get_starttag_text()))        # @override      def handle_data(self, data: str) -> None:          data = data.strip()          if data and self.taipy_tag is not None and self.taipy_tag.set_value(data):              self.parse_taipy_tag()          elif not self.is_body and self.head_tag is not None:              self.head_tag["content"] = data          else:              self.append_data(data)        # @override      def handle_endtag(self, tag) -> None:          if not self._tag_queue:              _warn(f"Closing '{tag}' at line {self._line_count} is missing an opening tag.")          else:              opening_tag, opening_tag_line = self._tag_queue.pop()              if opening_tag != tag:                  _warn(                      f"Opening tag '{opening_tag}' at line {opening_tag_line} has no matching closing tag '{tag}' at line {self._line_count}."  # noqa: E501                  )          if tag in ["head", "body", "html"]:              return          if self.taipy_tag is not None:              self.parse_taipy_tag()          if not self.is_body:              self.head.append(self.head_tag)              self.head_tag = None          elif tag in self.tag_mapping:              self.append_data(f"</{self.tag_mapping[tag]}>")          else:              self.append_data(f"</{tag}>")        def append_data(self, data: str) -> None:          if self.is_body:              self.body += data        def parse_taipy_tag(self) -> None:          tp_string, tp_element_name = self.taipy_tag.parse(self._gui)          self.append_data(tp_string)          self.tag_mapping[f"{self.taipy_tag.namespace}:{self.taipy_tag.control_type}"] = tp_element_name          self.taipy_tag = None        def get_jsx(self) -> str:          return self.body        def feed_data(self, data: str):          data_lines = data.split("\n")          for line, data_line in enumerate(data_lines):              self._line_count = line + 1              self.feed(data_line)          while self._tag_queue:              opening_tag, opening_tag_line = self._tag_queue.pop()              _warn(f"Opening tag '{opening_tag}' at line {opening_tag_line} has no matching closing tag.")      class _TaipyTag(object):      def __init__(self, namespace: str, tag_name: str, properties: t.List[t.Tuple[str, str]]) -> None:          self.namespace = namespace          self.control_type = tag_name          self.properties = {prop[0]: prop[1] for prop in properties}          self.has_set_value = False        def set_value(self, value: str) -> bool:          if self.has_set_value:              return False          property_name = _HtmlFactory.get_default_property_name(f"{self.namespace}.{self.control_type}")          # Set property only if it is not already defined          if property_name and property_name not in self.properties.keys():              self.properties[property_name] = value          self.has_set_value = True          return True        def parse(self, gui) -> t.Tuple[str, str]:          for k, v in self.properties.items():              self.properties[k] = v if v is not None else "true"          # allow usage of 'class' property in html taipy tag          if "class" in self.properties and "class_name" not in self.properties:              self.properties["class_name"] = self.properties["class"]          return _HtmlFactory.create_element(gui, self.namespace, self.control_type, self.properties)


"""The setup script."""    import json  import os    from setuptools import find_namespace_packages, find_packages, setup    with open("README.md", "rb") as readme_file:      readme = readme_file.read().decode("UTF-8")    with open(f"src{os.sep}taipy{os.sep}templates{os.sep}version.json") as version_file:      version = json.load(version_file)      version_string = f'{version.get("major", 0)}.{version.get("minor", 0)}.{version.get("patch", 0)}'      if vext := version.get("ext"):          version_string = f"{version_string}.{vext}"    test_requirements = ["pytest>=3.8"]    setup(      author="Avaiga",      author_email="dev@taipy.io",      python_requires=">=3.8",      classifiers=[          "Intended Audience :: Developers",          "License :: OSI Approved :: Apache Software License",          "Natural Language :: English",          "Programming Language :: Python :: 3",          "Programming Language :: Python :: 3.8",          "Programming Language :: Python :: 3.9",          "Programming Language :: Python :: 3.10",          "Programming Language :: Python :: 3.11",      ],      description="An open-source package holding Taipy application templates.",      license="Apache License 2.0",      long_description=readme,      long_description_content_type="text/markdown",      keywords="taipy-templates",      name="taipy-templates",      package_dir={"": "src"},      packages=find_namespace_packages(where="src") + find_packages(include=["taipy"]),      include_package_data=True,      test_suite="tests",      url="https://github.com/avaiga/taipy-templates",      version=version_string,      zip_safe=False,  )


from config.config import configure  from pages import job_page, scenario_page  from pages.root import content, root, selected_data_node, selected_scenario    import taipy as tp  from taipy import Core, Gui      def on_init(state):      ...      def on_change(state, var, val):      if var == "selected_data_node" and val:          state["scenario"].manage_data_node_partial(state)      pages = {      "/": root,      "scenario": scenario_page,      "jobs": job_page,  }      if __name__ == "__main__":      # Instantiate, configure and run the Core      core = Core()      default_scenario_cfg = configure()      core.run()        # ##################################################################################################################      # PLACEHOLDER: Initialize your data application here                                                               #      #                                                                                #      # Example:                                                                                #      if len(tp.get_scenarios()) == 0:          tp.create_scenario(default_scenario_cfg, name="Default Scenario")      # Comment, remove or replace the previous lines with your own use case                                             #      # ##################################################################################################################        # Instantiate, configure and run the GUI      gui = Gui(pages=pages)      data_node_partial = gui.add_partial("")      gui.run(title="{{cookiecutter.__application_title}}", margin="0em")


from algos import clean_data    from taipy import Config, Frequency, Scope      def configure():      # ##################################################################################################################      # PLACEHOLDER: Add your scenario configurations here                                                               #      #                                                                                #      # Example:                                                                                #      initial_dataset_cfg = Config.configure_csv_data_node("initial_dataset", scope=Scope.CYCLE)      replacement_type_cfg = Config.configure_data_node("replacement_type", default_data="NO VALUE")      cleaned_dataset_cfg = Config.configure_csv_data_node("cleaned_dataset")      clean_data_cfg = Config.configure_task(          "clean_data",          function=clean_data,          input=[initial_dataset_cfg, replacement_type_cfg],          output=cleaned_dataset_cfg,      )      scenario_cfg = Config.configure_scenario(          "scenario_configuration", task_configs=[clean_data_cfg], frequency=Frequency.DAILY      )      return scenario_cfg      # Comment, remove or replace the previous lines with your own use case                                             #      # ##################################################################################################################


from taipy import Config      def configure():      Config.load("config/config.toml")      return Config.scenarios["scenario_configuration"]


def clean_data(df, replacement_type):      df = df.fillna(replacement_type)      return df


from .algos import clean_data


from .job_page import job_page  from .scenario_page import scenario_page


from taipy.gui import Markdown    selected_scenario = None  selected_data_node = None  content = ""    root = Markdown("pages/root.md")


from .job_page import job_page


from taipy.gui import Markdown    job_page = Markdown("pages/job_page/job_page.md")


from taipy.gui import Markdown, notify    from .data_node_management import manage_partial      def notify_on_submission(state, submitable, details):      if details["submission_status"] == "COMPLETED":          notify(state, "success", "Submision completed!")      elif details["submission_status"] == "FAILED":          notify(state, "error", "Submission failed!")      else:          notify(state, "info", "In progress...")      def manage_data_node_partial(state):      manage_partial(state)      scenario_page = Markdown("pages/scenario_page/scenario_page.md")


from .scenario_page import scenario_page


# build partial content for a specific data node  def build_dn_partial(dn, dn_label):      partial_content = "<|part|render={selected_scenario}|\n\n"        # ##################################################################################################################      # PLACEHOLDER: data node specific content before automatic content                                                 #      #                                                                                #      # Example:                                                                                #      if dn_label == "replacement_type":          partial_content += "All missing values will be replaced by the data node value."      # Comment, remove or replace the previous lines with your own use case                                             #      # ##################################################################################################################        # Automatic data node content      partial_content += (          "<|{selected_scenario.data_nodes['" + dn.config_id + "']}|data_node|scenario={" "selected_scenario}|>\n\n "      )        # ##################################################################################################################      # PLACEHOLDER: data node specific content after automatic content                                                  #      #                                                                                #      # Example:                                                                                #      if dn_label == "initial_dataset":          partial_content += (              "Select your CSV file: <|{selected_data_node.path}|file_selector|extensions=.csv|on_action"              "={lambda s: s.refresh('selected_scenario')}|>\n\n "          )      # Comment, remove or replace the previous lines with your own use case                                             #      # ##################################################################################################################        partial_content += "|>\n\n"      return partial_content      def manage_partial(state):      dn = state.selected_data_node      dn_label = dn.get_simple_label()      partial_content = build_dn_partial(dn, dn_label)      state.data_node_partial.update_content(state, partial_content)


import os    import taipy    # Add taipy version to requirements.txt  with open(os.path.join(os.getcwd(), "requirements.txt"), "a") as requirement_file:      requirement_file.write(f"taipy=={taipy.version._get_version()}\n")    # Use TOML config file or not  use_toml_config = "{{ cookiecutter.__use_toml_config }}".upper()  if use_toml_config == "YES" or use_toml_config == "Y":      os.remove(os.path.join(os.getcwd(), "config", "config.py"))      os.rename(          os.path.join(os.getcwd(), "config", "config_with_toml.py"), os.path.join(os.getcwd(), "config", "config.py")      )  else:      os.remove(os.path.join(os.getcwd(), "config", "config_with_toml.py"))      os.remove(os.path.join(os.getcwd(), "config", "config.toml"))    main_file_name = "{{cookiecutter.__main_file}}.py"  print(      f"New Taipy application has been created at {os.path.join(os.getcwd())}"      f"\n\nTo start the application, change directory to the newly created folder:"      f"\n\tcd {os.path.join(os.getcwd())}"      f"\nand run the application as follows:"      f"\n\ttaipy run {main_file_name}"  )


#  # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with  # the License. You may obtain a copy of the License at  #  #        http://www.apache.org/licenses/LICENSE-2.0  #  # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on  # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the  # specific language governing permissions and limitations under the License.


import subprocess  import sys      def _run_template(main_path, time_out=30):      """Run the templates on a subprocess and get stdout after timeout"""      with subprocess.Popen([sys.executable, main_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc:          try:              stdout, stderr = proc.communicate(timeout=time_out)          except subprocess.TimeoutExpired:              proc.kill()              stdout, stderr = proc.communicate()        # Print the error if there is any (for debugging)      if stderr := str(stderr, "utf-8"):          print(stderr)        return stdout


import os    from cookiecutter.main import cookiecutter    from .utils import _run_template      def test_scenario_management_with_toml_config(tmpdir):      cookiecutter(          template="src/taipy/templates/scenario-management",          output_dir=tmpdir,          no_input=True,          extra_context={              "Application root folder name": "foo_app",              "Application main Python file": "main.py",              "Application title": "bar",              "Does the application use TOML Config?": "yes",          },      )        assert os.listdir(tmpdir) == ["foo_app"]      assert (          os.listdir(os.path.join(tmpdir, "foo_app")).sort()          == ["requirements.txt", "main.py", "algos", "config", "pages"].sort()      )        # Assert post_gen_project hook is successful      with open(os.path.join(tmpdir, "foo_app", "requirements.txt")) as requirements_file:          assert "taipy==" in requirements_file.read()      assert (          os.listdir(os.path.join(tmpdir, "foo_app", "config")).sort()          == ["__init__.py", "config.py", "config.toml"].sort()      )      with open(os.path.join(tmpdir, "foo_app", "config", "config.py")) as config_file:          assert 'Config.load("config/config.toml")' in config_file.read()        oldpwd = os.getcwd()      os.chdir(os.path.join(tmpdir, "foo_app"))      stdout = _run_template("main.py")      os.chdir(oldpwd)        # Assert the message when the application is run successfully is in the stdout      assert "[Taipy][INFO] Configuration 'config/config.toml' successfully loaded." in str(stdout, "utf-8")      assert "[Taipy][INFO]  * Server starting on" in str(stdout, "utf-8")      def test_scenario_management_without_toml_config(tmpdir):      cookiecutter(          template="src/taipy/templates/scenario-management",          output_dir=tmpdir,          no_input=True,          extra_context={              "Application root folder name": "foo_app",              "Application main Python file": "main.py",              "Application title": "bar",              "Does the application use TOML Config?": "no",          },      )        assert os.listdir(tmpdir) == ["foo_app"]      assert (          os.listdir(os.path.join(tmpdir, "foo_app")).sort()          == ["requirements.txt", "main.py", "algos", "config", "pages"].sort()      )        # Assert post_gen_project hook is successful      with open(os.path.join(tmpdir, "foo_app", "requirements.txt")) as requirements_file:          assert "taipy==" in requirements_file.read()      assert os.listdir(os.path.join(tmpdir, "foo_app", "config")).sort() == ["__init__.py", "config.py"].sort()      with open(os.path.join(tmpdir, "foo_app", "config", "config.py")) as config_file:          config_content = config_file.read()          assert 'Config.load("config/config.toml")' not in config_content          assert all([x in config_content for x in ["Config.configure_csv_data_node", "Config.configure_task"]])        oldpwd = os.getcwd()      os.chdir(os.path.join(tmpdir, "foo_app"))      stdout = _run_template("main.py")      os.chdir(oldpwd)        # Assert the message when the application is run successfully is in the stdout      assert "[Taipy][INFO]  * Server starting on" in str(stdout, "utf-8")


"""  Contain the application's configuration including the scenario configurations.    The configuration is run by the Core service.  """    from algorithms import *    from taipy import Config    # #############################################################################  # PLACEHOLDER: Put your application's configurations here                     #  #                                                                             #  # Example:                                                                    #  # scenario_config = Config.configure_scenario("placeholder_scenario", [])     #  # Comment, remove or replace the previous lines with your own use case        #  # #############################################################################


from .config import *


"""  This file is designed to contain the various Python functions used to configure tasks.    The functions will be imported by the __init__.py file in this folder.  """    # ##################################################################################################################  # PLACEHOLDER: Put your Python functions here                                                                      #  #                                                                                #  # Example:                                                                                #  # def place_holder_algorithm():                                                                                #  #     pass                                                                                #  # Comment, remove or replace the previous lines with your own use case                                             #  # ##################################################################################################################


from algorithms import *


from .root import root_page


"""  The root page of the application.  Page content is imported from the root.md file.    Please refer to https://docs.taipy.io/en/latest/manuals/gui/pages for more details.  """    from taipy.gui import Markdown    root_page = Markdown("pages/root.md")


"""  A page of the application.  Page content is imported from the page_example.md file.    Please refer to https://docs.taipy.io/en/latest/manuals/gui/pages for more details.  """    from taipy.gui import Markdown    page_example = Markdown("pages/page_example/page_example.md")


import sys    pages = "{{ cookiecutter.__pages }}".split(" ")  # Remove empty string from pages list  pages = [page for page in pages if page != ""]    for page in pages:      if not page.isidentifier():          sys.exit(f'Page name "{page}" is not a valid Python identifier. Please choose another name.')


from ._GuiCoreLib import _GuiCore      def _init_gui_core():      from taipy.gui import Gui        Gui.add_library(_GuiCore())      _init_gui_core()


from ._init import *


import json  import os      def _get_version():      with open(f"{os.path.dirname(os.path.abspath(__file__))}{os.sep}version.json") as version_file:          version = json.load(version_file)          version_string = f'{version.get("major", 0)}.{version.get("minor", 0)}.{version.get("patch", 0)}'          if vext := version.get("ext"):              version_string = f"{version_string}.{vext}"      return version_string


from .rest import Rest


#  # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with  # the License. You may obtain a copy of the License at  #  #        http://www.apache.org/licenses/LICENSE-2.0  #  # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on  # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the  # specific language governing permissions and limitations under the License.  from taipy.config import Config    from .app import create_app as _create_app      class Rest:      """      Runnable Rest application serving REST APIs on top of Taipy Core functionalities.      """        def __init__(self):          """          Initialize a REST API server.            A Flask application is instantiated and configured using three parameters from the global          config.              - Config.global_config.testing (bool): Run the application on testing mode.              - Config.global_config.env (Optional[str]): The application environment.              - Config.global_config.secret_key (Optional[str]): Application server secret key.            However, editing these parameters is only recommended for advanced users. Indeed, the default behavior of the          REST server without any required configuration satisfies all the standard and basic needs.          """          self._app = _create_app(              Config.global_config.testing or False, Config.global_config.env, Config.global_config.secret_key          )        def run(self, **kwargs):          """          Start a REST API server. This method is blocking.            Parameters:              **kwargs : Options to provide to the application server.          """          self._app.run(**kwargs)


"""# Taipy Rest    The Taipy Rest package exposes the Runnable `Rest^` service to provide REST APIs on top of Taipy Core. (more details  on Taipy Core functionalities in the [user manual](../../../manuals/core/)).    Once the `Rest^` service runs, users can call REST APIs to create, read, update, submit and remove Taipy entities  (including cycles, scenarios, sequences, tasks, jobs, and data nodes). It is handy when it comes to integrating a  Taipy application in a more complex IT ecosystem.    Please refer to [REST API](../../reference_rest/) page to get the exhaustive list of available APIs."""    from ._init import *  from .version import _get_version    __version__ = _get_version()


"""Extensions registry    All extensions here are used as singletons and  initialized in application factory  """    from .commons.apispec import APISpecExt    apispec = APISpecExt()


#  # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with  # the License. You may obtain a copy of the License at  #  #        http://www.apache.org/licenses/LICENSE-2.0  #  # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on  # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the  # specific language governing permissions and limitations under the License.  import json  import os    from setuptools import find_namespace_packages, find_packages, setup    with open("README.md") as readme_file:      readme = readme_file.read()    with open(f"src{os.sep}taipy{os.sep}rest{os.sep}version.json") as version_file:      version = json.load(version_file)      version_string = f'{version.get("major", 0)}.{version.get("minor", 0)}.{version.get("patch", 0)}'      if vext := version.get("ext"):          version_string = f"{version_string}.{vext}"    setup(      author="Avaiga",      name="taipy-rest",      keywords="taipy-rest",      python_requires=">=3.8",      version=version_string,      author_email="dev@taipy.io",      packages=find_namespace_packages(where="src") + find_packages(include=["taipy", "taipy.rest"]),      package_dir={"": "src"},      include_package_data=True,      long_description=readme,      long_description_content_type="text/markdown",      description="Library to expose taipy-core REST APIs.",      license="Apache License 2.0",      classifiers=[          "Intended Audience :: Developers",          "License :: OSI Approved :: Apache Software License",          "Natural Language :: English",          "Programming Language :: Python :: 3",          "Programming Language :: Python :: 3.8",          "Programming Language :: Python :: 3.9",          "Programming Language :: Python :: 3.10",          "Programming Language :: Python :: 3.11",      ],      install_requires=[          "flask>=3.0.0,<3.1",          "flask-restful>=0.3.9,<0.4",          "passlib>=1.7.4,<1.8",          "marshmallow>=3.20.1,<3.30",          "apispec[yaml]>=6.3,<7.0",          "apispec-webframeworks>=0.5.2,<0.6",          "taipy-core@git+https://git@github.com/Avaiga/taipy-core.git@develop",      ],  )


import os    from flask import Flask    from . import api  from .commons.encoder import _CustomEncoder  from .extensions import apispec      def create_app(testing=False, flask_env=None, secret_key=None):      """Application factory, used to create application"""      app = Flask(__name__)      app.config.update(          ENV=os.getenv("FLASK_ENV", flask_env),          TESTING=os.getenv("TESTING", testing),          SECRET_KEY=os.getenv("SECRET_KEY", secret_key),      )      app.url_map.strict_slashes = False      app.config["RESTFUL_JSON"] = {"cls": _CustomEncoder}        configure_apispec(app)      register_blueprints(app)      with app.app_context():          api.views.register_views()        return app      def configure_apispec(app):      """Configure APISpec for swagger support"""      apispec.init_app(app)        apispec.spec.components.schema(          "PaginatedResult",          {              "properties": {                  "total": {"type": "integer"},                  "pages": {"type": "integer"},                  "next": {"type": "string"},                  "prev": {"type": "string"},              }          },      )      def register_blueprints(app):      """Register all blueprints for application"""      app.register_blueprint(api.views.blueprint)


from taipy.core.cycle._cycle_converter import _CycleConverter  from taipy.core.data._data_converter import _DataNodeConverter  from taipy.core.scenario._scenario_converter import _ScenarioConverter  from taipy.core.sequence._sequence_converter import _SequenceConverter  from taipy.core.task._task_converter import _TaskConverter    entity_to_models = {      "scenario": _ScenarioConverter._entity_to_model,      "sequence": _SequenceConverter._entity_to_model,      "task": _TaskConverter._entity_to_model,      "data": _DataNodeConverter._entity_to_model,      "cycle": _CycleConverter._entity_to_model,  }      def _to_model(repository, entity, **kwargs):      return entity_to_models[repository](entity)


from apispec import APISpec  from apispec.exceptions import APISpecError  from apispec.ext.marshmallow import MarshmallowPlugin  from apispec_webframeworks.flask import FlaskPlugin  from flask import Blueprint, jsonify, render_template      class FlaskRestfulPlugin(FlaskPlugin):      """Small plugin override to handle flask-restful resources"""        @staticmethod      def _rule_for_view(view, app=None):          view_funcs = app.view_functions          endpoint = None            for ept, view_func in view_funcs.items():              if hasattr(view_func, "view_class"):                  view_func = view_func.view_class                if view_func == view:                  endpoint = ept            if not endpoint:              raise APISpecError("Could not find endpoint for view {0}".format(view))            # WARNING: Assume 1 rule per view function for now          rule = app.url_map._rules_by_endpoint[endpoint][0]          return rule      class APISpecExt:      """Very simple and small extension to use apispec with this API as a flask extension"""        def __init__(self, app=None, **kwargs):          self.spec = None            if app is not None:              self.init_app(app, **kwargs)        def init_app(self, app, **kwargs):          app.config.setdefault("APISPEC_TITLE", "Taipy Rest")          app.config.setdefault("APISPEC_VERSION", "1.0.0")          app.config.setdefault("OPENAPI_VERSION", "3.0.2")          app.config.setdefault("SWAGGER_JSON_URL", "/swagger.json")          app.config.setdefault("SWAGGER_UI_URL", "/swagger-ui")          app.config.setdefault("OPENAPI_YAML_URL", "/openapi.yaml")          app.config.setdefault("REDOC_UI_URL", "/redoc-ui")          app.config.setdefault("SWAGGER_URL_PREFIX", None)            self.spec = APISpec(              title=app.config["APISPEC_TITLE"],              version=app.config["APISPEC_VERSION"],              openapi_version=app.config["OPENAPI_VERSION"],              plugins=[MarshmallowPlugin(), FlaskRestfulPlugin()],              **kwargs          )            blueprint = Blueprint(              "swagger",              __name__,              template_folder="./templates",              url_prefix=app.config["SWAGGER_URL_PREFIX"],          )            blueprint.add_url_rule(app.config["SWAGGER_JSON_URL"], "swagger_json", self.swagger_json)          blueprint.add_url_rule(app.config["SWAGGER_UI_URL"], "swagger_ui", self.swagger_ui)          blueprint.add_url_rule(app.config["OPENAPI_YAML_URL"], "openapi_yaml", self.openapi_yaml)          blueprint.add_url_rule(app.config["REDOC_UI_URL"], "redoc_ui", self.redoc_ui)            app.register_blueprint(blueprint)        def swagger_json(self):          return jsonify(self.spec.to_dict())        def swagger_ui(self):          return render_template("swagger.j2")        def openapi_yaml(self):          # Manually inject ReDoc's Authentication legend, then remove it          self.spec.tag(              {                  "name": "authentication",                  "x-displayName": "Authentication",                  "description": "<SecurityDefinitions />",              }          )          redoc_spec = self.spec.to_yaml()          self.spec._tags.pop(0)          return redoc_spec        def redoc_ui(self):          return render_template("redoc.j2")


import json  from datetime import datetime  from enum import Enum  from typing import Any, Union    Json = Union[dict, list, str, int, float, bool, None]      class _CustomEncoder(json.JSONEncoder):      def default(self, o: Any) -> Json:          if isinstance(o, Enum):              result = o.value          elif isinstance(o, datetime):              result = {"__type__": "Datetime", "__value__": o.isoformat()}          else:              result = json.JSONEncoder.default(self, o)          return result


"""Simple helper to paginate query  """  from flask import request, url_for    DEFAULT_PAGE_SIZE = 50  DEFAULT_PAGE_NUMBER = 1      def extract_pagination(page=None, per_page=None, **request_args):      page = int(page) if page is not None else DEFAULT_PAGE_NUMBER      per_page = int(per_page) if per_page is not None else DEFAULT_PAGE_SIZE      return page, per_page, request_args      def paginate(query, schema):      page, per_page, other_request_args = extract_pagination(**request.args)      page_obj = query.paginate(page=page, per_page=per_page)      next_ = url_for(          request.endpoint,          page=page_obj.next_num if page_obj.has_next else page_obj.page,          per_page=per_page,          **other_request_args,          **request.view_args      )      prev = url_for(          request.endpoint,          page=page_obj.prev_num if page_obj.has_prev else page_obj.page,          per_page=per_page,          **other_request_args,          **request.view_args      )        return {          "total": page_obj.total,          "pages": page_obj.pages,          "next": next_,          "prev": prev,          "results": schema.dump(page_obj.items),      }


from . import error_handler, views    __all__ = ["views", "error_handler"]


from flask import jsonify  from marshmallow import ValidationError    from taipy.core.exceptions.exceptions import (      NonExistingCycle,      NonExistingDataNode,      NonExistingDataNodeConfig,      NonExistingJob,      NonExistingScenario,      NonExistingScenarioConfig,      NonExistingSequence,      NonExistingSequenceConfig,      NonExistingTask,      NonExistingTaskConfig,  )    from .exceptions.exceptions import ConfigIdMissingException, ScenarioIdMissingException, SequenceNameMissingException  from .views import blueprint      def _create_404(e):      return {"message": e.message}, 404      @blueprint.errorhandler(ValidationError)  def handle_marshmallow_error(e):      """Return json error for marshmallow validation errors.        This will avoid having to try/catch ValidationErrors in all endpoints, returning      correct JSON response with associated HTTP 400 Status (https://tools.ietf.org/html/rfc7231#section-6.5.1)      """      return jsonify(e.messages), 400      @blueprint.errorhandler(ConfigIdMissingException)  def handle_config_id_missing_exception(e):      return jsonify({"message": e.message}), 400      @blueprint.errorhandler(ScenarioIdMissingException)  def handle_scenario_id_missing_exception(e):      return jsonify({"message": e.message}), 400      @blueprint.errorhandler(SequenceNameMissingException)  def handle_sequence_name_missing_exception(e):      return jsonify({"message": e.message}), 400      @blueprint.errorhandler(NonExistingDataNode)  def handle_data_node_not_found(e):      return _create_404(e)      @blueprint.errorhandler(NonExistingDataNodeConfig)  def handle_data_node_config_not_found(e):      return _create_404(e)      @blueprint.errorhandler(NonExistingCycle)  def handle_cycle_not_found(e):      return _create_404(e)      @blueprint.errorhandler(NonExistingJob)  def handle_job_not_found(e):      return _create_404(e)      @blueprint.errorhandler(NonExistingSequence)  def handle_sequence_not_found(e):      return _create_404(e)      @blueprint.errorhandler(NonExistingSequenceConfig)  def handle_sequence_config_not_found(e):      return _create_404(e)      @blueprint.errorhandler(NonExistingScenario)  def handle_scenario_not_found(e):      return _create_404(e)      @blueprint.errorhandler(NonExistingScenarioConfig)  def handle_scenario_config_not_found(e):      return _create_404(e)      @blueprint.errorhandler(NonExistingTask)  def handle_task_not_found(e):      return _create_404(e)      @blueprint.errorhandler(NonExistingTaskConfig)  def handle_task_config_not_found(e):      return _create_404(e)


from flask import Blueprint, current_app  from flask_restful import Api    from taipy.core.common._utils import _load_fct  from taipy.logger._taipy_logger import _TaipyLogger    from ..extensions import apispec  from .middlewares._middleware import _using_enterprise  from .resources import (      CycleList,      CycleResource,      DataNodeList,      DataNodeReader,      DataNodeResource,      DataNodeWriter,      JobExecutor,      JobList,      JobResource,      ScenarioExecutor,      ScenarioList,      ScenarioResource,      SequenceExecutor,      SequenceList,      SequenceResource,      TaskExecutor,      TaskList,      TaskResource,  )  from .schemas import CycleSchema, DataNodeSchema, JobSchema, ScenarioSchema, SequenceSchema, TaskSchema    _logger = _TaipyLogger._get_logger()      blueprint = Blueprint("api", __name__, url_prefix="/api/v1")    api = Api(blueprint)    api.add_resource(      DataNodeResource,      "/datanodes/<string:datanode_id>/",      endpoint="datanode_by_id",      resource_class_kwargs={"logger": _logger},  )    api.add_resource(      DataNodeReader,      "/datanodes/<string:datanode_id>/read/",      endpoint="datanode_reader",      resource_class_kwargs={"logger": _logger},  )    api.add_resource(      DataNodeWriter,      "/datanodes/<string:datanode_id>/write/",      endpoint="datanode_writer",      resource_class_kwargs={"logger": _logger},  )    api.add_resource(      DataNodeList,      "/datanodes/",      endpoint="datanodes",      resource_class_kwargs={"logger": _logger},  )    api.add_resource(      TaskResource,      "/tasks/<string:task_id>/",      endpoint="task_by_id",      resource_class_kwargs={"logger": _logger},  )    api.add_resource(TaskList, "/tasks/", endpoint="tasks", resource_class_kwargs={"logger": _logger})  api.add_resource(      TaskExecutor,      "/tasks/submit/<string:task_id>/",      endpoint="task_submit",      resource_class_kwargs={"logger": _logger},  )    api.add_resource(      SequenceResource,      "/sequences/<string:sequence_id>/",      endpoint="sequence_by_id",      resource_class_kwargs={"logger": _logger},  )  api.add_resource(      SequenceList,      "/sequences/",      endpoint="sequences",      resource_class_kwargs={"logger": _logger},  )  api.add_resource(      SequenceExecutor,      "/sequences/submit/<string:sequence_id>/",      endpoint="sequence_submit",      resource_class_kwargs={"logger": _logger},  )    api.add_resource(      ScenarioResource,      "/scenarios/<string:scenario_id>/",      endpoint="scenario_by_id",      resource_class_kwargs={"logger": _logger},  )  api.add_resource(      ScenarioList,      "/scenarios/",      endpoint="scenarios",      resource_class_kwargs={"logger": _logger},  )  api.add_resource(      ScenarioExecutor,      "/scenarios/submit/<string:scenario_id>/",      endpoint="scenario_submit",      resource_class_kwargs={"logger": _logger},  )    api.add_resource(      CycleResource,      "/cycles/<string:cycle_id>/",      endpoint="cycle_by_id",      resource_class_kwargs={"logger": _logger},  )  api.add_resource(      CycleList,      "/cycles/",      endpoint="cycles",      resource_class_kwargs={"logger": _logger},  )    api.add_resource(      JobResource,      "/jobs/<string:job_id>/",      endpoint="job_by_id",      resource_class_kwargs={"logger": _logger},  )  api.add_resource(JobList, "/jobs/", endpoint="jobs", resource_class_kwargs={"logger": _logger})  api.add_resource(      JobExecutor,      "/jobs/cancel/<string:job_id>/",      endpoint="job_cancel",      resource_class_kwargs={"logger": _logger},  )      def load_enterprise_resources(api: Api):      """      Load enterprise resources.      """        if not _using_enterprise():          return      load_resources = _load_fct("taipy.enterprise.rest.api.views", "_load_resources")      load_resources(api)      load_enterprise_resources(api)      def register_views():      apispec.spec.components.schema("DataNodeSchema", schema=DataNodeSchema)      apispec.spec.path(view=DataNodeResource, app=current_app)      apispec.spec.path(view=DataNodeList, app=current_app)      apispec.spec.path(view=DataNodeReader, app=current_app)      apispec.spec.path(view=DataNodeWriter, app=current_app)        apispec.spec.components.schema("TaskSchema", schema=TaskSchema)      apispec.spec.path(view=TaskResource, app=current_app)      apispec.spec.path(view=TaskList, app=current_app)      apispec.spec.path(view=TaskExecutor, app=current_app)        apispec.spec.components.schema("SequenceSchema", schema=SequenceSchema)      apispec.spec.path(view=SequenceResource, app=current_app)      apispec.spec.path(view=SequenceList, app=current_app)      apispec.spec.path(view=SequenceExecutor, app=current_app)        apispec.spec.components.schema("ScenarioSchema", schema=ScenarioSchema)      apispec.spec.path(view=ScenarioResource, app=current_app)      apispec.spec.path(view=ScenarioList, app=current_app)      apispec.spec.path(view=ScenarioExecutor, app=current_app)        apispec.spec.components.schema("CycleSchema", schema=CycleSchema)      apispec.spec.path(view=CycleResource, app=current_app)      apispec.spec.path(view=CycleList, app=current_app)        apispec.spec.components.schema("JobSchema", schema=JobSchema)      apispec.spec.path(view=JobResource, app=current_app)      apispec.spec.path(view=JobList, app=current_app)      apispec.spec.path(view=JobExecutor, app=current_app)        apispec.spec.components.schema(          "Any",          {              "description": "Any value",              "nullable": True,          },      )        if _using_enterprise():          _register_views = _load_fct("taipy.enterprise.rest.api.views", "_register_views")          _register_views(apispec)


from .cycle import CycleList, CycleResource  from .datanode import DataNodeList, DataNodeReader, DataNodeResource, DataNodeWriter  from .job import JobExecutor, JobList, JobResource  from .scenario import ScenarioExecutor, ScenarioList, ScenarioResource  from .sequence import SequenceExecutor, SequenceList, SequenceResource  from .task import TaskExecutor, TaskList, TaskResource    __all__ = [      "DataNodeResource",      "DataNodeList",      "DataNodeReader",      "DataNodeWriter",      "TaskList",      "TaskResource",      "TaskExecutor",      "SequenceList",      "SequenceResource",      "SequenceExecutor",      "ScenarioList",      "ScenarioResource",      "ScenarioExecutor",      "CycleResource",      "CycleList",      "JobResource",      "JobList",      "JobExecutor",  ]


#  # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with  # the License. You may obtain a copy of the License at  #  #        http://www.apache.org/licenses/LICENSE-2.0  #  # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on  # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the  # specific language governing permissions and limitations under the License.


from functools import wraps  from importlib import util    from taipy.core.common._utils import _load_fct      def _middleware(f):      @wraps(f)      def wrapper(*args, **kwargs):          if _using_enterprise():              return _enterprise_middleware()(f)(*args, **kwargs)          else:              return f(*args, **kwargs)        return wrapper      def _using_enterprise():      return util.find_spec("taipy.enterprise") is not None      def _enterprise_middleware():      return _load_fct("taipy.enterprise.rest.api.middlewares._middleware", "_middleware")


class ConfigIdMissingException(Exception):      def __init__(self):          self.message = "Config id is missing."      class ScenarioIdMissingException(Exception):      def __init__(self):          self.message = "Scenario id is missing."      class SequenceNameMissingException(Exception):      def __init__(self):          self.message = "Sequence name is missing."


from marshmallow import Schema, fields      class CycleSchema(Schema):      name = fields.String()      frequency = fields.String()      properties = fields.Dict()      creation_date = fields.String()      start_date = fields.String()      end_date = fields.String()      class CycleResponseSchema(CycleSchema):      id = fields.String()


from marshmallow import Schema, fields      class TaskSchema(Schema):      config_id = fields.String()      id = fields.String()      owner_id = fields.String()      parent_ids = fields.List(fields.String)      input_ids = fields.List(fields.String)      function_name = fields.String()      function_module = fields.String()      output_ids = fields.List(fields.String)      version = fields.String()


from marshmallow import Schema, fields      class CallableSchema(Schema):      fct_name = fields.String()      fct_module = fields.String()      class JobSchema(Schema):      id = fields.String()      task_id = fields.String()      status = fields.String()      force = fields.Boolean()      creation_date = fields.String()      subscribers = fields.Nested(CallableSchema)      stacktrace = fields.List(fields.String)


from marshmallow import Schema, fields      class SequenceSchema(Schema):      owner_id = fields.String()      parent_ids = fields.List(fields.String)      tasks = fields.List(fields.String)      version = fields.String()      properties = fields.Dict()      class SequenceResponseSchema(SequenceSchema):      id = fields.String()      subscribers = fields.List(fields.Dict)


from .cycle import CycleResponseSchema, CycleSchema  from .datanode import (      CSVDataNodeConfigSchema,      DataNodeConfigSchema,      DataNodeFilterSchema,      DataNodeSchema,      ExcelDataNodeConfigSchema,      GenericDataNodeConfigSchema,      InMemoryDataNodeConfigSchema,      JSONDataNodeConfigSchema,      MongoCollectionDataNodeConfigSchema,      PickleDataNodeConfigSchema,      SQLDataNodeConfigSchema,      SQLTableDataNodeConfigSchema,  )  from .job import JobSchema  from .scenario import ScenarioResponseSchema, ScenarioSchema  from .sequence import SequenceResponseSchema, SequenceSchema  from .task import TaskSchema    __all__ = [      "DataNodeSchema",      "DataNodeFilterSchema",      "TaskSchema",      "SequenceSchema",      "SequenceResponseSchema",      "ScenarioSchema",      "ScenarioResponseSchema",      "CycleSchema",      "CycleResponseSchema",      "JobSchema",  ]