diff options
Diffstat (limited to 'venv/lib/python3.8/site-packages/dash/resources.py')
-rw-r--r-- | venv/lib/python3.8/site-packages/dash/resources.py | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/venv/lib/python3.8/site-packages/dash/resources.py b/venv/lib/python3.8/site-packages/dash/resources.py new file mode 100644 index 0000000..8aad614 --- /dev/null +++ b/venv/lib/python3.8/site-packages/dash/resources.py @@ -0,0 +1,167 @@ +import json +import warnings +import os + +import typing as _t +import typing_extensions as _tx + + +from .development.base_component import ComponentRegistry +from . import exceptions + + +# ResourceType has `async` key, use the init form to be able to provide it. +ResourceType = _tx.TypedDict( + "ResourceType", + { + "namespace": str, + "async": _t.Union[bool, _t.Literal["eager", "lazy"]], + "dynamic": bool, + "relative_package_path": str, + "external_url": str, + "dev_package_path": str, + "absolute_path": str, + "asset_path": str, + "external_only": bool, + "filepath": str, + "dev_only": bool, + }, + total=False, +) + + +# pylint: disable=too-few-public-methods +class ResourceConfig: + def __init__(self, serve_locally, eager_loading): + self.eager_loading = eager_loading + self.serve_locally = serve_locally + + +class Resources: + def __init__(self, resource_name: str, config: ResourceConfig): + self._resources: _t.List[ResourceType] = [] + self.resource_name = resource_name + self.config = config + + def append_resource(self, resource: ResourceType): + self._resources.append(resource) + + # pylint: disable=too-many-branches + def _filter_resources( + self, all_resources: _t.List[ResourceType], dev_bundles=False + ): + filtered_resources = [] + for s in all_resources: + filtered_resource = {} + valid_resource = True + if "dynamic" in s: + filtered_resource["dynamic"] = s["dynamic"] + if "async" in s: + if "dynamic" in s: + raise exceptions.ResourceException( + f""" + Can't have both 'dynamic' and 'async'. + {json.dumps(filtered_resource)} + """ + ) + + # Async assigns a value dynamically to 'dynamic' + # based on the value of 'async' and config.eager_loading + # + # True -> dynamic if the server is not eager, False otherwise + # 'lazy' -> always dynamic + # 'eager' -> dynamic if server is not eager + # (to prevent ever loading it) + filtered_resource["dynamic"] = ( + not self.config.eager_loading + if s["async"] is True + else (s["async"] == "eager" and not self.config.eager_loading) + or s["async"] == "lazy" + ) + if "namespace" in s: + filtered_resource["namespace"] = s["namespace"] + + if "external_url" in s and ( + s.get("external_only") or not self.config.serve_locally + ): + filtered_resource["external_url"] = s["external_url"] + elif "dev_package_path" in s and (dev_bundles or s.get("dev_only")): + if dev_bundles: + filtered_resource["relative_package_path"] = s["dev_package_path"] + else: + valid_resource = False + elif "relative_package_path" in s: + filtered_resource["relative_package_path"] = s["relative_package_path"] + elif "absolute_path" in s: + filtered_resource["absolute_path"] = s["absolute_path"] + elif "asset_path" in s: + info = os.stat(s["filepath"]) # type: ignore + filtered_resource["asset_path"] = s["asset_path"] + filtered_resource["ts"] = info.st_mtime + elif self.config.serve_locally: + warnings.warn( + ( + "You have set your config to `serve_locally=True` but " + f"A local version of {s.get('external_url', '')} is not available.\n" # type: ignore + "If you added this file with " + "`app.scripts.append_script` " + "or `app.css.append_css`, use `external_scripts` " + "or `external_stylesheets` instead.\n" + "See https://dash.plotly.com/external-resources" + ) + ) + continue + else: + raise exceptions.ResourceException( + f""" + {json.dumps(filtered_resource)} does not have a + relative_package_path, absolute_path, or an external_url. + """ + ) + + if valid_resource: + filtered_resources.append(filtered_resource) + + return filtered_resources + + def get_all_resources(self, dev_bundles=False): + lib_resources = ComponentRegistry.get_resources(self.resource_name) + all_resources = lib_resources + self._resources + + return self._filter_resources(all_resources, dev_bundles) + + def get_library_resources(self, libraries, dev_bundles=False): + lib_resources = ComponentRegistry.get_resources(self.resource_name, libraries) + all_resources = lib_resources + self._resources + + return self._filter_resources(all_resources, dev_bundles) + + +class Css: + def __init__(self, serve_locally: bool): + self.config = ResourceConfig(serve_locally, True) + self._resources = Resources("_css_dist", self.config) + + def append_css(self, stylesheet: ResourceType): + self._resources.append_resource(stylesheet) + + def get_all_css(self): + return self._resources.get_all_resources() + + def get_library_css(self, libraries: _t.List[str]): + return self._resources.get_library_resources(libraries) + + +class Scripts: + def __init__(self, serve_locally, eager): + self.config = ResourceConfig(serve_locally, eager) + self._resources = Resources("_js_dist", self.config) + + def append_script(self, script): + self._resources.append_resource(script) + + def get_all_scripts(self, dev_bundles=False): + return self._resources.get_all_resources(dev_bundles) + + def get_library_scripts(self, libraries, dev_bundles=False): + return self._resources.get_library_resources(libraries, dev_bundles) |