Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Isolate dependencies from other add-ons #284

Merged
merged 5 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,8 @@ CMakeCache.txt
Makefile
lib

#Selenium
__hubs_selenium_profile
# Selenium
__hubs_selenium_profile

# Dependencies
addons/io_hubs_addon/.__deps__
2 changes: 0 additions & 2 deletions addons/io_hubs_addon/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from .utils import create_prefs_dir
from .utils import get_user_python_path
import sys
import bpy
from .io import gltf_exporter, gltf_importer, panels
Expand All @@ -22,7 +21,6 @@
"category": "Generic"
}

sys.path.insert(0, get_user_python_path())

create_prefs_dir()

Expand Down
14 changes: 7 additions & 7 deletions addons/io_hubs_addon/debugger.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from bpy.types import Context

from .preferences import EXPORT_TMP_FILE_NAME, EXPORT_TMP_SCREENSHOT_FILE_NAME
from .utils import isModuleAvailable, save_prefs, find_area, image_type_to_file_ext
from .utils import is_module_available, save_prefs, find_area, image_type_to_file_ext
from .icons import get_hubs_icons
from .hubs_session import HubsSession, PARAMS_TO_STRING
from . import api
Expand Down Expand Up @@ -238,7 +238,7 @@ class HUBS_PT_ToolsSceneDebuggerCreatePanel(bpy.types.Panel):

@classmethod
def poll(cls, context: Context):
return isModuleAvailable("selenium")
return is_module_available("selenium")

def draw(self, context: Context):
prefs = context.window_manager.hubs_scene_debugger_prefs
Expand Down Expand Up @@ -270,7 +270,7 @@ class HUBS_PT_ToolsSceneDebuggerOpenPanel(bpy.types.Panel):

@classmethod
def poll(cls, context: Context):
return isModuleAvailable("selenium")
return is_module_available("selenium")

def draw(self, context: Context):
box = self.layout.box()
Expand Down Expand Up @@ -303,7 +303,7 @@ class HUBS_PT_ToolsSceneDebuggerUpdatePanel(bpy.types.Panel):

@classmethod
def poll(cls, context: Context):
return isModuleAvailable("selenium")
return is_module_available("selenium")

def draw(self, context: Context):
box = self.layout.box()
Expand Down Expand Up @@ -379,7 +379,7 @@ class HUBS_PT_ToolsSceneSessionPanel(bpy.types.Panel):
def draw(self, context):
main_box = self.layout.box()

if isModuleAvailable("selenium"):
if is_module_available("selenium"):
row = main_box.row(align=True)
row.alignment = "CENTER"
col = row.column()
Expand Down Expand Up @@ -454,7 +454,7 @@ class HUBS_PT_ToolsSceneDebuggerPanel(bpy.types.Panel):

@classmethod
def poll(cls, context: Context):
return isModuleAvailable("selenium")
return is_module_available("selenium")

def draw(self, context):
params_icons = {}
Expand Down Expand Up @@ -860,7 +860,7 @@ class HUBS_PT_ToolsSceneDebuggerPublishScenePanel(bpy.types.Panel):

@classmethod
def poll(cls, context: Context):
return isModuleAvailable("selenium")
return is_module_available("selenium")

def draw(self, context: Context):
if not hubs_session.is_alive() or not hubs_session.user_logged_in:
Expand Down
11 changes: 11 additions & 0 deletions addons/io_hubs_addon/dependencies/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from ..utils import load_dependency

selenium = None


def get_selenium():
global selenium
if selenium is None:
selenium = load_dependency("selenium.webdriver")

return selenium
19 changes: 10 additions & 9 deletions addons/io_hubs_addon/hubs_session.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import bpy
from .preferences import get_addon_pref, EXPORT_TMP_FILE_NAME
from .utils import isModuleAvailable, get_browser_profile_directory
from .utils import is_module_available, get_browser_profile_directory

PARAMS_TO_STRING = {
"newLoader": {
Expand Down Expand Up @@ -121,26 +121,27 @@ def __create_instance(self, context):
file_path = get_browser_profile_directory(browser)
if not os.path.exists(file_path):
os.mkdir(file_path)

from .dependencies import get_selenium
selenium = get_selenium()
if browser == "Firefox":
from selenium import webdriver
options = webdriver.FirefoxOptions()
options = selenium.FirefoxOptions()
override_ff_path = get_addon_pref(
context).override_firefox_path
ff_path = get_addon_pref(context).firefox_path
if override_ff_path and ff_path:
options.binary_location = ff_path
# This should work but it doesn't https://github.com/SeleniumHQ/selenium/issues/11028 so using arguments instead
# firefox_profile = webdriver.FirefoxProfile(file_path)
# firefox_profile = selenium.FirefoxProfile(file_path)
# firefox_profile.accept_untrusted_certs = True
# firefox_profile.assume_untrusted_cert_issuer = True
# options.profile = firefox_profile
options.add_argument("-profile")
options.add_argument(file_path)
options.set_preference("javascript.options.shared_memory", True)
self._web_driver = webdriver.Firefox(options=options)
self._web_driver = selenium.Firefox(options=options)
else:
from selenium import webdriver
options = webdriver.ChromeOptions()
options = selenium.ChromeOptions()
options.add_argument('--enable-features=SharedArrayBuffer')
options.add_argument('--ignore-certificate-errors')
options.add_argument(
Expand All @@ -150,7 +151,7 @@ def __create_instance(self, context):
chrome_path = get_addon_pref(context).chrome_path
if override_chrome_path and chrome_path:
options.binary_location = chrome_path
self._web_driver = webdriver.Chrome(options=options)
self._web_driver = selenium.Chrome(options=options)

def update_session_state(self):
if self.is_alive():
Expand Down Expand Up @@ -201,7 +202,7 @@ def bring_to_front(self, context):

def is_alive(self):
try:
if not self._web_driver or not isModuleAvailable("selenium"):
if not self._web_driver or not is_module_available("selenium"):
return False
else:
return bool(self._web_driver.current_url)
Expand Down
101 changes: 30 additions & 71 deletions addons/io_hubs_addon/preferences.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import bpy
from bpy.types import AddonPreferences, Context
from bpy.props import IntProperty, StringProperty, EnumProperty, BoolProperty, CollectionProperty
from .utils import get_addon_package, isModuleAvailable, get_browser_profile_directory
from bpy.props import IntProperty, StringProperty, EnumProperty, BoolProperty, PointerProperty
from .utils import get_addon_package, is_module_available, get_browser_profile_directory
import platform
from os.path import join, dirname, realpath

Expand Down Expand Up @@ -36,10 +36,9 @@ class DepsProperty(bpy.types.PropertyGroup):
class InstallDepsOperator(bpy.types.Operator):
bl_idname = "pref.hubs_prefs_install_dep"
bl_label = "Install a python dependency through pip"
bl_property = "dep_names"
bl_options = {'REGISTER', 'UNDO'}

dep_names: CollectionProperty(type=DepsProperty)
dep_config: PointerProperty(type=DepsProperty)

def execute(self, context):
import subprocess
Expand All @@ -50,26 +49,32 @@ def execute(self, context):
if result.returncode < 0:
print(result.stderr)
bpy.ops.wm.hubs_report_viewer('INVOKE_DEFAULT', title="Hubs scene debugger report",
report_string='\n\n'.join(["Dependencies install has failed",
report_string='\n\n'.join(["Dependencies install has failed installing pip",
f'{result.stderr}']))
return {'CANCELLED'}

deps = []
for _, dep in self.dep_names.items():
if dep.version:
deps.append(f'{dep.name}=={dep.version}')
else:
deps.append(dep.name)
result = subprocess.run(
[sys.executable, '-m', 'pip', 'install', '--upgrade', 'pip'],
capture_output=False, text=True, input="y")
if result.returncode < 0:
print(result.stderr)
bpy.ops.wm.hubs_report_viewer('INVOKE_DEFAULT', title="Hubs scene debugger report",
report_string='\n\n'.join(["Dependencies install has failed upgrading pip",
f'{result.stderr}']))
return {'CANCELLED'}

from .utils import get_or_create_deps_path
dep = self.dep_config.name
if self.dep_config.version:
dep = f'{self.dep_config.name}=={self.dep_config.version}'

from .utils import get_user_python_path
result = subprocess.run(
[sys.executable, '-m', 'pip', 'install', *deps,
'-t', get_user_python_path()],
[sys.executable, '-m', 'pip', 'install', '--upgrade', dep,
'-t', get_or_create_deps_path(self.dep_config.name)],
capture_output=True, text=True, input="y")
failed = False
for _, dep in self.dep_names.items():
if not isModuleAvailable(dep.name):
failed = True
if not is_module_available(self.dep_config.name):
failed = True
if result.returncode != 0 or failed:
print(result.stderr)
bpy.ops.wm.hubs_report_viewer('INVOKE_DEFAULT', title="Hubs scene debugger report",
Expand All @@ -85,55 +90,15 @@ def execute(self, context):
class UninstallDepsOperator(bpy.types.Operator):
bl_idname = "pref.hubs_prefs_uninstall_dep"
bl_label = "Uninstall a python dependency through pip"
bl_property = "dep_names"
bl_options = {'REGISTER', 'UNDO'}

dep_names: CollectionProperty(type=DepsProperty)
force: BoolProperty(default=False)
dep_config: PointerProperty(type=DepsProperty)

def execute(self, context):
import subprocess
import sys

result = subprocess.run([sys.executable, '-m', 'ensurepip'],
capture_output=False, text=True, input="y")
if result.returncode < 0:
print(result.stderr)
bpy.ops.wm.hubs_report_viewer('INVOKE_DEFAULT', title="Hubs scene debugger report",
report_string='\n\n'.join(["Dependencies uninstall has failed",
f'{result.stderr}']))
return {'CANCELLED'}

for name, _ in self.dep_names.items():
del name

result = subprocess.run(
[sys.executable, '-m', 'pip', 'uninstall', *
[name for name, _ in self.dep_names.items()]],
capture_output=True, text=True, input="y")
from .utils import get_or_create_deps_path
import shutil
shutil.rmtree(get_or_create_deps_path(self.dep_config.name))

failed = False
for name, _ in self.dep_names.items():
if isModuleAvailable(name):
failed = True
if result.returncode != 0 or failed:
print(result.stderr)
bpy.ops.wm.hubs_report_viewer('INVOKE_DEFAULT', title="Hubs scene debugger report",
report_string='\n\n'.join(["Dependencies install has failed",
f'{result.stderr}']))
return {'CANCELLED'}

if self.force:
import os
from .utils import get_user_python_path
deps_paths = [os.path.join(get_user_python_path(), name)
for name, _ in self.dep_names.items()]
import shutil
for dep_path in deps_paths:
shutil.rmtree(dep_path)

bpy.ops.wm.hubs_report_viewer('INVOKE_DEFAULT', title="Hubs scene debugger report",
report_string="Dependencies uninstalled successfully")
return {'FINISHED'}


Expand Down Expand Up @@ -189,10 +154,6 @@ class HubsPreferences(AddonPreferences):
("Chrome", "Chrome", "Use Chrome as the viewer browser")],
default="Firefox")

force_uninstall: BoolProperty(
default=False, name="Force",
description="Force uninstall of the selenium dependencies by deleting the module directory")

override_firefox_path: BoolProperty(
name="Override Firefox executable path", description="Override Firefox executable path", default=False)
firefox_path: StringProperty(
Expand All @@ -209,7 +170,7 @@ def draw(self, context):
box.row().prop(self, "row_length")
box.row().prop(self, "recast_lib_path")

selenium_available = isModuleAvailable("selenium")
selenium_available = is_module_available("selenium")
modules_available = selenium_available
box = layout.box()
box.label(text="Scene debugger configuration")
Expand Down Expand Up @@ -264,16 +225,14 @@ def draw(self, context):
"Selenium module not found. These modules are required to run the viewer")
row = modules_box.row()
if modules_available:
row.prop(self, "force_uninstall")
op = row.operator(UninstallDepsOperator.bl_idname,
text="Uninstall dependencies (selenium)")
op.dep_names.add().name = "selenium"
op.dep_config.name = "selenium"
else:
op = row.operator(InstallDepsOperator.bl_idname,
text="Install dependencies (selenium)")
dep = op.dep_names.add()
dep.name = "selenium"
dep.version = "4.15.2"
op.dep_config.name = "selenium"
op.dep_config.version = "4.15.2"


def register():
Expand Down
Loading
Loading