Skip to content

Commit

Permalink
support glob declaration in resource descriptions (#2192)
Browse files Browse the repository at this point in the history
* support glob declaration in resource descriptions

* use Path.glob to be 3.9 compatible

---------

Co-authored-by: Fred Lefévère-Laoide <[email protected]>
  • Loading branch information
FredLL-Avaiga and Fred Lefévère-Laoide authored Nov 1, 2024
1 parent 3527d06 commit 5b48479
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 19 deletions.
28 changes: 22 additions & 6 deletions taipy/gui/extension/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from abc import ABC, abstractmethod
from inspect import isclass
from pathlib import Path
from urllib.parse import urlencode
from urllib.parse import urlencode, urlparse

from .._renderers.builder import _Builder
from .._warnings import _warn
Expand Down Expand Up @@ -115,7 +115,7 @@ def __init__(
default_property (str): The name of the default property for this element.
properties (Dict[str, ElementProperty]): The dictionary containing the properties of this element, where the keys are the property names and the values are instances of ElementProperty.
inner_properties (Optional[List[ElementProperty]]): The optional list of inner properties for this element.<br/>
Default values are set/binded automatically.
Default values are set/bound automatically.
react_component (Optional[str]): The name of the component to be created on the front-end.<br/>
If not specified, it is set to a camel case version of the element's name
("one_name" is transformed to "OneName").
Expand Down Expand Up @@ -324,9 +324,27 @@ def get_js_module_name(self) -> str:
"""
return _to_camel_case(self.get_name(), True)

def __get_class_folder(self):
if not hasattr(self, "_class_folder"):
module_obj = sys.modules.get(self.__class__.__module__)
base = (Path(".") if module_obj is None else Path(module_obj.__file__).parent).resolve() # type: ignore
self._class_folder = base if base.exists() else Path(".").resolve()
return self._class_folder

def _do_get_relative_paths(self, paths: t.List[str]) -> t.List[str]:
ret = set()
for path in paths or []:
if bool(urlparse(path).netloc):
ret.add(path)
elif file_paths := self.__get_class_folder().glob(path):
ret.update([file_path.relative_to(self.__get_class_folder()).as_posix() for file_path in file_paths])
elif path:
ret.add(path)
return list(ret)

def get_scripts(self) -> t.List[str]:
"""
Return the list of the mandatory script file pathnames.
Return the list of the mandatory script file path names.
If a script file pathname is an absolute URL it will be used as is.<br/>
If it's not it will be passed to `(ElementLibrary.)get_resource()^` to retrieve a local
Expand Down Expand Up @@ -363,9 +381,7 @@ def get_resource(self, name: str) -> Path:
Arguments:
name (str): The name of the resource for which a local Path should be returned.
""" # noqa: E501
module_obj = sys.modules.get(self.__class__.__module__)
base = (Path(".") if module_obj is None else Path(module_obj.__file__).parent).resolve() # type: ignore
base = base if base.exists() else Path(".").resolve()
base = self.__get_class_folder()
file = (base / name).resolve()
if str(file).startswith(str(base)) and file.exists():
return file
Expand Down
15 changes: 5 additions & 10 deletions taipy/gui/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -1332,12 +1332,8 @@ def __send_ws_download(self, content: str, name: str, on_action: str) -> None:
)

def __send_ws_alert(
self, type: str,
message: str,
system_notification: bool,
duration: int,
notification_id: t.Optional[str] = None
) -> None:
self, type: str, message: str, system_notification: bool, duration: int, notification_id: t.Optional[str] = None
) -> None:
payload = {
"type": _WsType.ALERT.value,
"atype": type,
Expand Down Expand Up @@ -2278,10 +2274,9 @@ def _close_notification(
message="", # No need for a message when closing
system_notification=False, # System notification not needed for closing
duration=0, # No duration since it's an immediate close
notification_id=notification_id
notification_id=notification_id,
)


def _hold_actions(
self,
callback: t.Optional[t.Union[str, t.Callable]] = None,
Expand Down Expand Up @@ -2661,13 +2656,13 @@ def __register_blueprint(self):
s if bool(urlparse(s).netloc) else f"{Gui._EXTENSION_ROOT}/{name}/{s}{lib.get_query(s)}"
for name, libs in Gui.__extensions.items()
for lib in libs
for s in (lib.get_scripts() or [])
for s in (lib._do_get_relative_paths(lib.get_scripts()))
]
styles = [
s if bool(urlparse(s).netloc) else f"{Gui._EXTENSION_ROOT}/{name}/{s}{lib.get_query(s)}"
for name, libs in Gui.__extensions.items()
for lib in libs
for s in (lib.get_styles() or [])
for s in (lib._do_get_relative_paths(lib.get_styles()))
]
if self._get_config("stylekit", True):
styles.append("stylekit/stylekit.css")
Expand Down
6 changes: 3 additions & 3 deletions taipy/gui_core/_GuiCoreLib.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class _GuiCore(ElementLibrary):
__DATANODE_SELECTOR_SORT_VAR = "__tpgc_dn_sort"
__DATANODE_SELECTOR_ERROR_VAR = "__tpgc_dn_error"

__elts = {
__elements = {
"scenario_selector": Element(
"value",
{
Expand Down Expand Up @@ -314,10 +314,10 @@ def get_name(self) -> str:
return _GuiCore.__LIB_NAME

def get_elements(self) -> t.Dict[str, Element]:
return _GuiCore.__elts
return _GuiCore.__elements

def get_scripts(self) -> t.List[str]:
return ["lib/taipy-gui-core.js"]
return ["lib/*.js"]

def on_init(self, gui: Gui) -> t.Optional[t.Tuple[str, t.Any]]:
self.ctx = _GuiCoreContext(gui)
Expand Down

0 comments on commit 5b48479

Please sign in to comment.