Skip to content

Commit

Permalink
Fix JacquesLucke#138: avoid creating duplicate link for addon
Browse files Browse the repository at this point in the history
- Capitalize global variables
- Add type hints
  • Loading branch information
Mateusz-Grzelinski committed Jul 22, 2024
1 parent ac5a461 commit e6f2f34
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 30 deletions.
14 changes: 10 additions & 4 deletions pythonFiles/include/blender_vscode/communication.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@
import requests
import threading
from functools import partial
from typing import TYPE_CHECKING
from .utils import run_in_main_thread
from .environment import blender_path, scripts_folder
from .environment import BLENDER_PATH, SCRIPTS_FOLDER

EDITOR_ADDRESS = None
OWN_SERVER_PORT = None
DEBUGPY_PORT = None


# Get proper type hinting without impacting runtime
if TYPE_CHECKING:
from .load_addons import PathMapping


def setup(address, path_mappings):
global EDITOR_ADDRESS, OWN_SERVER_PORT, DEBUGPY_PORT
EDITOR_ADDRESS = address
Expand Down Expand Up @@ -105,14 +111,14 @@ def request_handler_wrapper(data):
###############################


def send_connection_information(path_mappings):
def send_connection_information(path_mappings: "PathMapping"):
send_dict_as_json(
{
"type": "setup",
"blenderPort": OWN_SERVER_PORT,
"debugpyPort": DEBUGPY_PORT,
"blenderPath": str(blender_path),
"scriptsFolder": str(scripts_folder),
"blenderPath": str(BLENDER_PATH),
"scriptsFolder": str(SCRIPTS_FOLDER),
"addonPathMappings": path_mappings,
}
)
Expand Down
16 changes: 8 additions & 8 deletions pythonFiles/include/blender_vscode/environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
from pathlib import Path
import platform

python_path = Path(sys.executable)
blender_path = Path(bpy.app.binary_path)
blender_directory = blender_path.parent
PYTHON_PATH = Path(sys.executable)
BLENDER_PATH = Path(bpy.app.binary_path)
blender_directory = BLENDER_PATH.parent

# Test for MacOS app bundles
if platform.system() == "Darwin":
use_own_python = blender_directory.parent in python_path.parents
USE_OWN_PYTHON = blender_directory.parent in PYTHON_PATH.parents
else:
use_own_python = blender_directory in python_path.parents
USE_OWN_PYTHON = blender_directory in PYTHON_PATH.parents

version = bpy.app.version
scripts_folder = blender_path.parent / f"{version[0]}.{version[1]}" / "scripts"
addon_directories = tuple(map(Path, addon_utils.paths()))
_version = bpy.app.version
SCRIPTS_FOLDER = BLENDER_PATH.parent / f"{_version[0]}.{_version[1]}" / "scripts"
ADDON_DIRECTORIES = tuple(map(Path, addon_utils.paths()))
12 changes: 6 additions & 6 deletions pythonFiles/include/blender_vscode/installation.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
import subprocess
from pathlib import Path
from . import handle_fatal_error
from .environment import python_path, use_own_python
from .environment import PYTHON_PATH, USE_OWN_PYTHON

cwd_for_subprocesses = python_path.parent
cwd_for_subprocesses = PYTHON_PATH.parent


def ensure_packages_are_installed(package_names, allow_modify_external_python):
if packages_are_installed(package_names):
return

if not use_own_python and not allow_modify_external_python:
if not USE_OWN_PYTHON and not allow_modify_external_python:
handle_cannot_install_packages(package_names)

install_packages(package_names)
Expand All @@ -40,7 +40,7 @@ def ensure_package_is_installed(name):

def install_package(name):
target = get_package_install_directory()
subprocess.run([str(python_path), "-m", "pip", "install", name, "--target", target], cwd=cwd_for_subprocesses)
subprocess.run([str(PYTHON_PATH), "-m", "pip", "install", name, "--target", target], cwd=cwd_for_subprocesses)

if not module_can_be_imported(name):
handle_fatal_error(f"could not install {name}")
Expand All @@ -49,11 +49,11 @@ def install_package(name):
def install_pip():
# try ensurepip before get-pip.py
if module_can_be_imported("ensurepip"):
subprocess.run([str(python_path), "-m", "ensurepip", "--upgrade"], cwd=cwd_for_subprocesses)
subprocess.run([str(PYTHON_PATH), "-m", "ensurepip", "--upgrade"], cwd=cwd_for_subprocesses)
return
# pip can not necessarily be imported into Blender after this
get_pip_path = Path(__file__).parent / "external" / "get-pip.py"
subprocess.run([str(python_path), str(get_pip_path)], cwd=cwd_for_subprocesses)
subprocess.run([str(PYTHON_PATH), str(get_pip_path)], cwd=cwd_for_subprocesses)


def get_package_install_directory():
Expand Down
30 changes: 19 additions & 11 deletions pythonFiles/include/blender_vscode/load_addons.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,36 +2,40 @@
import sys
import traceback
from pathlib import Path
from typing import TypedDict, List, Union

import bpy

from . import AddonInfo
from .communication import send_dict_as_json
from .environment import addon_directories
from .environment import ADDON_DIRECTORIES
from .utils import is_addon_legacy


def setup_addon_links(addons_to_load: list[AddonInfo]):
class PathMapping(TypedDict):
src: str
load: str

path_mappings = []

def setup_addon_links(addons_to_load: list[AddonInfo]) -> List[PathMapping]:
path_mappings: List[PathMapping] = []

for addon_info in addons_to_load:
user_addon_directory = get_user_addon_directory(Path(addon_info.load_dir))
print(f"USER ADDON: {user_addon_directory}")

if not os.path.exists(user_addon_directory):
os.makedirs(user_addon_directory)

if is_addon_legacy(Path(addon_info.load_dir)) and not str(user_addon_directory) in sys.path:
if is_addon_legacy(Path(addon_info.load_dir)) and str(user_addon_directory) not in sys.path:
os.makedirs(user_addon_directory, exist_ok=True)
sys.path.append(str(user_addon_directory))

if is_in_any_addon_directory(addon_info.load_dir):
# this should be improved https://github.com/JacquesLucke/blender_vscode/issues/168
load_path = addon_info.load_dir
else:
load_path = os.path.join(user_addon_directory, addon_info.module_name)
create_link_in_user_addon_directory(addon_info.load_dir, load_path)

path_mappings.append({"src": str(addon_info.load_dir), "load": str(load_path)})
path_mappings.append(PathMapping(src=str(addon_info.load_dir), load=str(load_path)))

return path_mappings

Expand Down Expand Up @@ -60,7 +64,7 @@ def load(addons_to_load: list[AddonInfo]):
send_dict_as_json({"type": "enableFailure", "addonPath": str(addon_info.load_dir)})


def create_link_in_user_addon_directory(directory, link_path):
def create_link_in_user_addon_directory(directory: Union[str, os.PathLike], link_path: Union[str, os.PathLike]):
if os.path.exists(link_path):
os.remove(link_path)

Expand All @@ -72,8 +76,12 @@ def create_link_in_user_addon_directory(directory, link_path):
os.symlink(str(directory), str(link_path), target_is_directory=True)


def is_in_any_addon_directory(module_path):
for path in addon_directories:
def is_in_any_addon_directory(module_path: Path):
for repo in bpy.context.preferences.extensions.repos:
repo: bpy.types.UserExtensionRepo
if repo.enabled and repo.directory == module_path.parent:
return True
for path in ADDON_DIRECTORIES:
if path == module_path.parent:
return True
return False
2 changes: 1 addition & 1 deletion pythonFiles/include/blender_vscode/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import traceback


def is_addon_legacy(addon_dir: Path):
def is_addon_legacy(addon_dir: Path) -> bool:
"""Return whether an addon uses the legacy bl_info behavior, or the new blender_manifest behavior"""
if bpy.app.version < (4, 2, 0):
return True
Expand Down

0 comments on commit e6f2f34

Please sign in to comment.