diff options
author | sotech117 <michael_foiani@brown.edu> | 2025-07-31 17:27:24 -0400 |
---|---|---|
committer | sotech117 <michael_foiani@brown.edu> | 2025-07-31 17:27:24 -0400 |
commit | 5bf22fc7e3c392c8bd44315ca2d06d7dca7d084e (patch) | |
tree | 8dacb0f195df1c0788d36dd0064f6bbaa3143ede /venv/lib/python3.8/site-packages/dash/development/build_process.py | |
parent | b832d364da8c2efe09e3f75828caf73c50d01ce3 (diff) |
add code for analysis of data
Diffstat (limited to 'venv/lib/python3.8/site-packages/dash/development/build_process.py')
-rw-r--r-- | venv/lib/python3.8/site-packages/dash/development/build_process.py | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/venv/lib/python3.8/site-packages/dash/development/build_process.py b/venv/lib/python3.8/site-packages/dash/development/build_process.py new file mode 100644 index 0000000..be65553 --- /dev/null +++ b/venv/lib/python3.8/site-packages/dash/development/build_process.py @@ -0,0 +1,189 @@ +import os +import sys +import json +import string +import shutil +import logging +import coloredlogs +import fire +import requests + +from .._utils import run_command_with_process, compute_hash, job + +logger = logging.getLogger(__name__) +coloredlogs.install( + fmt="%(asctime)s,%(msecs)03d %(levelname)s - %(message)s", datefmt="%H:%M:%S" +) + + +class BuildProcess: + def __init__(self, main, deps_info): + self.logger = logger + self.main = main + self.build_folder = self._concat(self.main, "build") + self.deps_info = deps_info + self.npm_modules = self._concat(self.main, "node_modules") + self.package_lock = self._concat(self.main, "package-lock.json") + self.package = self._concat(self.main, "package.json") + self._parse_package(path=self.package) + self.asset_paths = (self.deps_folder, self.npm_modules) + + def _parse_package(self, path): + with open(path, "r", encoding="utf-8") as fp: + package = json.load(fp) + self.version = package["version"] + self.name = package["name"] + self.deps_folder = self._concat(self.main, os.pardir, "deps") + self.deps = package["dependencies"] + + @staticmethod + def _concat(*paths): + return os.path.realpath(os.path.sep.join((path for path in paths if path))) + + @staticmethod + def _clean_path(path): + if os.path.exists(path): + logger.warning("🚨 %s already exists, remove it!", path) + try: + if os.path.isfile(path): + os.remove(path) + if os.path.isdir(path): + shutil.rmtree(path) + except OSError: + sys.exit(1) + else: + logger.warning("🚨 %s doesn't exist, no action taken", path) + + @job("clean all the previous assets generated by build tool") + def clean(self): + for path in self.asset_paths: + self._clean_path(path) + + @job("run `npm ci`") + def npm(self): + """Job to install npm packages.""" + os.chdir(self.main) + run_command_with_process("npm ci") + + @job("build the renderer in dev mode") + def watch(self): + os.chdir(self.main) + os.system("npm run build:dev") + + @job("run the whole building process in sequence") + def build(self, build=None): + self.clean() + self.npm() + self.bundles(build) + self.digest() + + @job("compute the hash digest for assets") + def digest(self): + if not os.path.exists(self.deps_folder): + try: + os.makedirs(self.deps_folder) + except OSError: + logger.exception("🚨 having issues manipulating %s", self.deps_folder) + sys.exit(1) + + payload = {self.name: self.version} + + for folder in (self.deps_folder, self.build_folder): + copies = tuple( + _ + for _ in os.listdir(folder) + if os.path.splitext(_)[-1] in {".js", ".map"} + ) + logger.info("bundles in %s %s", folder, copies) + + for copy in copies: + payload[f"SHA256 ({copy})"] = compute_hash(self._concat(folder, copy)) + + with open(self._concat(self.main, "digest.json"), "w", encoding="utf-8") as fp: + json.dump(payload, fp, sort_keys=True, indent=4, separators=(",", ":")) + logger.info( + "bundle digest in digest.json:\n%s", + json.dumps(payload, sort_keys=True, indent=4), + ) + + @job("copy and generate the bundles") + def bundles(self, build=None): # pylint:disable=too-many-locals + if not os.path.exists(self.deps_folder): + try: + os.makedirs(self.deps_folder) + except OSError: + logger.exception("🚨 having issues manipulating %s", self.deps_folder) + sys.exit(1) + + self._parse_package(self.package_lock) + + getattr(self, "_bundles_extra", lambda: None)() + + versions = { + "version": self.version, + "package": self.name.replace(" ", "_").replace("-", "_"), + } + + for scope, name, subfolder, filename, extras in self.deps_info: + version = self.deps["/".join(filter(None, [scope, name]))]["version"] + name_squashed = name.replace("-", "").replace(".", "") + versions[name_squashed] = version + + logger.info("copy npm dependency => %s", filename) + ext = "min.js" if "min" in filename.split(".") else "js" + target = f"{name}@{version}.{ext}" + + shutil.copyfile( + self._concat(self.npm_modules, scope, name, subfolder, filename), + self._concat(self.deps_folder, target), + ) + + if extras: + extras_str = '", "'.join(extras) + versions[f"extra_{name_squashed}_versions"] = f'"{extras_str}"' + + for extra_version in extras: + url = f"https://unpkg.com/{name}@{extra_version}/umd/{filename}" + res = requests.get(url) + extra_target = f"{name}@{extra_version}.{ext}" + extra_path = self._concat(self.deps_folder, extra_target) + with open(extra_path, "wb") as fp: + fp.write(res.content) + + _script = "build:dev" if build == "local" else "build:js" + logger.info("run `npm run %s`", _script) + os.chdir(self.main) + run_command_with_process(f"npm run {_script}") + + logger.info("generate the `__init__.py` from template and versions") + with open(self._concat(self.main, "init.template"), encoding="utf-8") as fp: + t = string.Template(fp.read()) + + renderer_init = self._concat(self.deps_folder, os.pardir, "_dash_renderer.py") + with open(renderer_init, "w", encoding="utf-8") as fp: + fp.write(t.safe_substitute(versions)) + + +class Renderer(BuildProcess): + def __init__(self): + """dash-renderer's path is binding with the dash folder hierarchy.""" + extras = [ + "18.2.0", + "16.14.0", + ] # versions to include beyond what's in package.json + super().__init__( + self._concat(os.path.dirname(__file__), os.pardir, "dash-renderer"), + ( + ("@babel", "polyfill", "dist", "polyfill.min.js", None), + (None, "react", "umd", "react.production.min.js", extras), + (None, "react", "umd", "react.development.js", extras), + (None, "react-dom", "umd", "react-dom.production.min.js", extras), + (None, "react-dom", "umd", "react-dom.development.js", extras), + (None, "prop-types", None, "prop-types.min.js", None), + (None, "prop-types", None, "prop-types.js", None), + ), + ) + + +def renderer(): + fire.Fire(Renderer) |