mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
193 lines
7.4 KiB
Python
193 lines
7.4 KiB
Python
"""Setup Bonsai Development Environment.
|
|
|
|
Script links existing Bonsai installation to the provided IfcOpenShell repository.
|
|
|
|
If you're on Windows/Mac, using Blender 4.5, Bonsai is installed from unstable repo (raw_githubusercontent_com)
|
|
and this script is already part of IfcOpenShell repo you want to link, then you can just run it and it will just work.
|
|
|
|
Otherwise, see the SETTINGS section below to validate script settings to ensure it fits your evnironment.
|
|
|
|
Example usage:
|
|
|
|
python /xxx/yyy/dev_environment.py
|
|
python dev_environment.py
|
|
|
|
"""
|
|
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import urllib.request
|
|
from pathlib import Path
|
|
from typing import Union
|
|
|
|
available_platforms = ("win32", "darwin", "linux")
|
|
if sys.platform not in available_platforms:
|
|
print(f"Currently only available on {', '.join(available_platforms)}. Not available on {sys.platform}.")
|
|
exit(1)
|
|
|
|
# ---------------------------
|
|
# SETTINGS.
|
|
# ---------------------------
|
|
# REPO_PATH: Path to your local IfcOpenShell repository.
|
|
# By default, this script will automatically detect the repository path based on its own location,
|
|
# so you usually do NOT need to set this manually.
|
|
# If you want to specify it explicitly, set it to the full absolute path, e.g.:
|
|
# > REPO_PATH = r"C:\Path\To\Your\IfcOpenShell\Repository"
|
|
REPO_PATH = r""
|
|
|
|
# BLENDER_PATH: Path to Blender's configuration folder.
|
|
# Usually don't need to change, just ensure Blender version matches.
|
|
if sys.platform == "win32":
|
|
BLENDER_PATH = Path.home() / "AppData/Roaming/Blender Foundation/Blender/4.5"
|
|
elif sys.platform == "darwin":
|
|
BLENDER_PATH = Path.home() / "Library/Application Support/Blender/4.5"
|
|
elif sys.platform == "linux":
|
|
BLENDER_PATH = Path.home() / ".config/blender/4.5"
|
|
else:
|
|
assert False
|
|
|
|
|
|
BONSAI_PATH_CANDIDATES = (
|
|
# Installed from Bonsai Unstalble Repo.
|
|
BLENDER_PATH / r"extensions/raw_githubusercontent_com/bonsai",
|
|
# Installed via offline installation.
|
|
BLENDER_PATH / r"extensions/user_default/bonsai",
|
|
# Installed from Blender's official extensions platform.
|
|
BLENDER_PATH / r"extensions/blender_org/bonsai",
|
|
)
|
|
|
|
|
|
# Determine BONSAI_PATH from existing options.
|
|
def find_bonsai_path() -> Union[Path, None]:
|
|
for path in BONSAI_PATH_CANDIDATES:
|
|
if path.exists():
|
|
return path
|
|
|
|
# BONSAI_PATH: Path to 'bonsai' extension folder inside BLENDER_PATH.
|
|
# Typically resolved automatically, paths priority can be found in `find_bonsai_path`.
|
|
#
|
|
# Should be changed by user only if their installation path doesn't match any of the defaults
|
|
# or if they need different paths priority order.
|
|
BONSAI_PATH = find_bonsai_path()
|
|
|
|
|
|
# ---------------------------
|
|
|
|
# Never changed by user.
|
|
PACKAGE_PATH = BLENDER_PATH / r"extensions/.local/lib/python3.11/site-packages"
|
|
|
|
def main() -> None:
|
|
global REPO_PATH
|
|
|
|
if not REPO_PATH:
|
|
script_path = Path(__file__)
|
|
print(f"REPO_PATH is not set, deducing it from {script_path.name} location...")
|
|
repo_bonsai_path = script_path.parent.parent.parent
|
|
assert repo_bonsai_path.name == "bonsai"
|
|
REPO_PATH = repo_bonsai_path.parent.parent
|
|
|
|
print("-" * 10)
|
|
print("Script settings:")
|
|
print("(all paths are confirmed to be existing)")
|
|
print(f"REPO_PATH={REPO_PATH}")
|
|
print(f"BLENDER_PATH={BLENDER_PATH}")
|
|
print(f"BONSAI_PATH={BONSAI_PATH}")
|
|
print("-" * 10)
|
|
|
|
assert REPO_PATH.exists(), f"Path '{REPO_PATH=!s}' doesn't exist, ensure variable is set correctly."
|
|
assert BLENDER_PATH.exists(), f"Path '{BLENDER_PATH=!s}' doesn't exist, ensure variable is set correctly."
|
|
assert PACKAGE_PATH.exists(), f"Path '{PACKAGE_PATH=!s}' doesn't exist, ensure variable is set correctly."
|
|
assert BONSAI_PATH is not None, (
|
|
"Couldn't find BONSAI_PATH in any of the paths candidates. "
|
|
"Example paths: {}".format("\n".join(str(p) for p in BONSAI_PATH_CANDIDATES))
|
|
)
|
|
|
|
input("Confirm the settings above and press Enter to continue or Ctrl-C to cancel...")
|
|
|
|
# Handle symlinks
|
|
# (they could be disabled by default on Windows).
|
|
subprocess.check_call(("git", "config", "--local", "core.symlinks", "true"), cwd=REPO_PATH)
|
|
symlinks_glob = "src/bonsai/bonsai/bim/data/templates/projects/*.ifc"
|
|
# Delete and checkout is the only way to ensure files are added as symlinks.
|
|
for path in REPO_PATH.glob(symlinks_glob):
|
|
path.unlink()
|
|
subprocess.check_call(("git", "checkout", "--", symlinks_glob), cwd=REPO_PATH)
|
|
|
|
print("Copying compiled dependencies to the repo...")
|
|
dest = REPO_PATH / "src" / "ifcopenshell-python" / "ifcopenshell"
|
|
for path in PACKAGE_PATH.glob("ifcopenshell/*_wrapper*"):
|
|
if path.suffix.lower() == ".pyi":
|
|
continue
|
|
dest_ = dest / path.name
|
|
print(f"Copying {path} -> {dest_}")
|
|
try:
|
|
shutil.copy(path, dest_)
|
|
except shutil.SameFileError:
|
|
pass
|
|
|
|
print("Symlinking extension to the git repo...")
|
|
# fmt: off
|
|
symlinks = (
|
|
(BONSAI_PATH / "__init__.py", REPO_PATH / "src/bonsai/bonsai/__init__.py"),
|
|
(PACKAGE_PATH / "bonsai", REPO_PATH / "src/bonsai/bonsai"),
|
|
(PACKAGE_PATH / "ifcopenshell", REPO_PATH / "src/ifcopenshell-python/ifcopenshell"),
|
|
(PACKAGE_PATH / "ifccsv.py", REPO_PATH / "src/ifccsv/ifccsv.py"),
|
|
(PACKAGE_PATH / "ifcdiff.py", REPO_PATH / "src/ifcdiff/ifcdiff.py"),
|
|
(PACKAGE_PATH / "bsdd.py", REPO_PATH / "src/bsdd/bsdd.py"),
|
|
(PACKAGE_PATH / "bcf", REPO_PATH / "src/bcf/bcf"),
|
|
(PACKAGE_PATH / "ifc4d", REPO_PATH / "src/ifc4d/ifc4d"),
|
|
(PACKAGE_PATH / "ifc5d", REPO_PATH / "src/ifc5d/ifc5d"),
|
|
(PACKAGE_PATH / "ifccityjson", REPO_PATH / "src/ifccityjson/ifccityjson"),
|
|
(PACKAGE_PATH / "ifcclash", REPO_PATH / "src/ifcclash/ifcclash"),
|
|
(PACKAGE_PATH / "ifcpatch", REPO_PATH / "src/ifcpatch/ifcpatch"),
|
|
(PACKAGE_PATH / "ifctester", REPO_PATH / "src/ifctester/ifctester"),
|
|
(PACKAGE_PATH / "ifcfm", REPO_PATH / "src/ifcfm/ifcfm"),
|
|
)
|
|
# fmt: on
|
|
|
|
for path, dest in symlinks:
|
|
print(f"Linking {path} -> {dest}.")
|
|
if path.is_dir():
|
|
if path.is_symlink():
|
|
path.unlink()
|
|
else:
|
|
shutil.rmtree(path)
|
|
# Check `is_symlink` in case if it's a broken symlink.
|
|
elif path.is_file() or path.is_symlink():
|
|
path.unlink()
|
|
else:
|
|
pass
|
|
path.symlink_to(dest, dest.is_dir())
|
|
|
|
print("Download third party dependencies...")
|
|
BONSAI_DATA = PACKAGE_PATH / "bonsai" / "bim" / "data"
|
|
downloads = (
|
|
(
|
|
"https://raw.githubusercontent.com/jsGanttImproved/jsgantt-improved/master/dist/jsgantt.js",
|
|
BONSAI_DATA / "gantt" / "jsgantt.js",
|
|
),
|
|
(
|
|
"https://raw.githubusercontent.com/jsGanttImproved/jsgantt-improved/master/dist/jsgantt.css",
|
|
BONSAI_DATA / "gantt" / "jsgantt.css",
|
|
),
|
|
(
|
|
"https://github.com/BrickSchema/Brick/releases/download/nightly/Brick.ttl",
|
|
BONSAI_DATA / "brick" / "Brick.ttl",
|
|
),
|
|
(
|
|
"https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js",
|
|
BONSAI_DATA / "webui" / "static" / "js" / "jquery.min.js",
|
|
),
|
|
)
|
|
|
|
for url, filepath in downloads:
|
|
print(f"Downloading {url} -> {filepath}")
|
|
urllib.request.urlretrieve(url, filepath)
|
|
|
|
input("Dev environment is all set. 🎉🎉\nPress Enter to continue..." "")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|