Skip to content

Commit

Permalink
Merge pull request #284 from Hubs-Foundation/isolate-selenium
Browse files Browse the repository at this point in the history
Isolate dependencies from other add-ons
  • Loading branch information
keianhzo authored Jun 5, 2024
2 parents db89b26 + ebd6e0a commit 95cea92
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 108 deletions.
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 @@ -249,7 +249,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 @@ -280,7 +280,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 @@ -312,7 +312,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 @@ -388,7 +388,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 @@ -463,7 +463,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 @@ -869,7 +869,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

0 comments on commit 95cea92

Please sign in to comment.