You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
732 lines
28 KiB
Python
732 lines
28 KiB
Python
# coding:utf-8
|
|
#!/usr/bin/python
|
|
#
|
|
# Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
#
|
|
#
|
|
# -- This line is 75 characters -------------------------------------------
|
|
from __future__ import unicode_literals
|
|
|
|
"""
|
|
Module Description:
|
|
DccScriptingInterface\\azpy\\shared\\synthetic_env.py
|
|
|
|
Stands up a synthetic version of the environment in:
|
|
DccScriptingInterface\\Launchers\\windows\\Env.bat
|
|
|
|
DccScriptingInterface a.k.a. DCCsi
|
|
|
|
This module (softly) assumes that the cwd is the DCCsi
|
|
AND that you can get access to imports from azpy
|
|
|
|
The configures a synthetic version of the default DCCsi env,
|
|
which includes additional code access paths and some other settings.
|
|
|
|
It does not assume that the external environment is configured.
|
|
It provides best guess defaults for the environment (when they are not set.)
|
|
It will not overwrite the envars that are configured.
|
|
|
|
To do this, it uses the pattern:
|
|
_SOME_ENVAR = os.getenv('ENVAR_TAG', <default>)
|
|
|
|
The environment is conveniently packed into a dictionary,
|
|
this allows the dictionar to be imported into another module,
|
|
the import will resolve and standup the synthetic environment.
|
|
|
|
Configures several useful environment config settings and paths,
|
|
[key] : [value]
|
|
|
|
# this is the required base environment
|
|
LY_PROJECT : name of project (project directory)
|
|
LY_DEV : path to Lumberyard \dev root
|
|
LY_PROJECT_PATH : path to project dir
|
|
DCCSIG_PATH : path to the DCCsi Gem root
|
|
DCCSI_AZPY_PATH * : path to azpy Python API (code)
|
|
DCCSI_SDK_PATH : path to associated (non-api code) DCC SDK
|
|
|
|
# nice to haves in base env to define core support
|
|
DCCSI_GDEBUG : sets global debug prints
|
|
DCCSI_DEV_MODE : extends support like early debugger attachment
|
|
DCCSI_GDEBUGGER : default debugger (WING)
|
|
|
|
DCCsi has been (experimentally) tested with : PY27, PY37
|
|
- py27 for DCC tools like Maya
|
|
- py37 for Lumberyard
|
|
- it probably will work with 3.6 (substance)
|
|
|
|
:: Default version py37 has a launcher
|
|
(activates the env, starts py interpreter)
|
|
set DCCSI_PY_BASE=%DCCSI_PYTHON_INSTALL%\python.exe
|
|
|
|
:: shared location for 64bit python 3.7 BASE location
|
|
set DCCSI_PY_DCCSI=%DCCSI_LAUNCHERS_PATH%\Launch_pyBASE.bat
|
|
|
|
:: Override DCCSI_PY_DCCSI to set a defualt version for the DCCsi
|
|
|
|
:: ide and debugger plugs
|
|
:: for instance with WingIDE this defines using the default py interpreter
|
|
${DCCSI_PY_DEFAULT}
|
|
|
|
::Other python runtimes can be defined, for py27 we use this
|
|
:: shared location for 64bit DCCSI_PY_MAYA python 2.7 DEV location
|
|
set DCCSI_PY_MAYA=%MAYA_LOCATION%\bin\mayapy.exe
|
|
:: wingIDE can use more then one defined/managed interpreters
|
|
:: allowing you to _G_DEBUG code in multiple runtimes in one session
|
|
${DCCSI_PY_MAYA}
|
|
|
|
# related to the WING as the default DCCSI_GDEBUGGER
|
|
DCCSI_WING_VERSION_MAJOR : the major version of Wing IDE (default IDE)
|
|
DCCSI_WING_VERSION_MINOR : minor version #
|
|
WINGHOME : path for wing (for debug) integration
|
|
|
|
NOTES:
|
|
The default IDE and debugger is WING primarily because of author preference.
|
|
Other options are available to configure out-of-the-box (PyCharm)
|
|
"""
|
|
# -------------------------------------------------------------------------
|
|
# built in's
|
|
import os
|
|
import sys
|
|
import site
|
|
import re
|
|
#import inspect
|
|
import json
|
|
|
|
import logging as _logging
|
|
from collections import OrderedDict
|
|
|
|
# Lumberyard and Atom standalone should be launched in py3.7+
|
|
# because of use of pathlib (unless externally provided in py2.7)
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
os.environ['PYTHONINSPECT'] = 'True'
|
|
|
|
_MODULE_PATH = os.path.realpath(__file__) # To Do: what if frozen?
|
|
_DCCSIG_PATH = os.path.normpath(os.path.join(_MODULE_PATH, '../..'))
|
|
_DCCSIG_PATH = os.getenv('DCCSIG_PATH', _DCCSIG_PATH)
|
|
site.addsitedir(_DCCSIG_PATH)
|
|
print(_DCCSIG_PATH)
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Lumberyard extensions
|
|
from pathlib import Path
|
|
|
|
# set up global space, logging etc.
|
|
import azpy
|
|
from azpy.env_bool import env_bool
|
|
from azpy.constants import ENVAR_DCCSI_GDEBUG
|
|
from azpy.constants import ENVAR_DCCSI_DEV_MODE
|
|
|
|
_G_DEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False)
|
|
_DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False)
|
|
|
|
_PACKAGENAME = 'DCCsi.azpy.sunthetic_env'
|
|
|
|
_log_level = int(20)
|
|
if _G_DEBUG:
|
|
_log_level = int(10)
|
|
_LOGGER = azpy.initialize_logger(_PACKAGENAME,
|
|
log_to_file=True,
|
|
default_log_level=_log_level)
|
|
|
|
_LOGGER.debug('Starting up: {0}.'.format({_PACKAGENAME}))
|
|
_LOGGER.debug('_DCCSIG_PATH: {}'.format(_DCCSIG_PATH))
|
|
_LOGGER.debug('_G_DEBUG: {}'.format(_G_DEBUG))
|
|
_LOGGER.debug('_DCCSI_DEV_MODE: {}'.format(_DCCSI_DEV_MODE))
|
|
|
|
if _DCCSI_DEV_MODE:
|
|
from azpy.test.entry_test import connect_wing
|
|
foo = connect_wing()
|
|
|
|
# we can go ahead and just make sure the the DCCsi env is set
|
|
# config is SO generic this ensures we are importing a specific one
|
|
_spec_dccsi_config = importlib.util.spec_from_file_location("dccsi.config",
|
|
Path(_DCCSIG_PATH,
|
|
"config.py"))
|
|
_dccsi_config = importlib.util.module_from_spec(_spec_dccsi_config)
|
|
_spec_dccsi_config.loader.exec_module(_dccsi_config)
|
|
|
|
settings = _dccsi_config.get_config_settings()
|
|
# -------------------------------------------------------------------------
|
|
|
|
# Lumberyard extensions
|
|
from azpy.constants import *
|
|
from azpy.shared.common.core_utils import walk_up_dir
|
|
from azpy.shared.common.core_utils import get_stub_check_path
|
|
|
|
_DCCSI_PYTHON_LIB_PATH = os.getenv(ENVAR_DCCSI_PYTHON_LIB_PATH,
|
|
PATH_DCCSI_PYTHON_LIB_PATH)
|
|
_LOGGER.debug('Dccsi Lib Path: {0}'.format(_DCCSI_PYTHON_LIB_PATH))
|
|
|
|
if os.path.exists(_DCCSI_PYTHON_LIB_PATH):
|
|
site.addsitedir(_DCCSI_PYTHON_LIB_PATH) # add access
|
|
|
|
# -------------------------------------------------------------------------
|
|
# post-bootstrap global space
|
|
_G_DEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False)
|
|
_DCCSI_DEV_MODE = env_bool(ENVAR_DCCSI_DEV_MODE, False)
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
|
FRMT_LOG_LONG = ("[%(name)s][%(levelname)s] >> "
|
|
"%(message)s (%(asctime)s; %(filename)s:%(lineno)d)")
|
|
_PACKAGENAME = 'azpy.synthetic_env'
|
|
|
|
_logging.basicConfig(level=_logging.INFO,
|
|
format=FRMT_LOG_LONG,
|
|
datefmt='%m-%d %H:%M')
|
|
_LOGGER = _logging.getLogger(_PACKAGENAME)
|
|
|
|
_log_level = int(10)
|
|
console_handler = _logging.StreamHandler(sys.stdout)
|
|
console_handler.setLevel(_log_level)
|
|
formatter = _logging.Formatter(FRMT_LOG_LONG)
|
|
console_handler.setFormatter(formatter)
|
|
_LOGGER.addHandler(console_handler)
|
|
_LOGGER.setLevel(_log_level)
|
|
|
|
_LOGGER.debug('Initializing: {0}.'.format({_PACKAGENAME}))
|
|
|
|
# -------------------------------------------------------------------------
|
|
# This module is semi-standalone (no azpy YET) to avoid circular imports
|
|
# To Do: figure out how to bets NOPT dup this methods (there are also moudles)
|
|
# we want to run this potentially with no preformed env
|
|
# and thus we may not have full acess to the DCCsi and azpy package
|
|
# -------------------------------------------------------------------------
|
|
def get_current_project(dev_folder):
|
|
boostrap_filepath = Path(dev_folder, "bootstrap.cfg")
|
|
bootstrap = open(boostrap_filepath, "r")
|
|
game_project_regex = re.compile("^sys_game_folder\s*=\s*(.*)")
|
|
for line in bootstrap:
|
|
game_folder_match = game_project_regex.match(line)
|
|
if game_folder_match:
|
|
return game_folder_match.group(1)
|
|
return None
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
# TO DO: Move to a util package or module
|
|
def return_stub(stub='dccsi_stub'):
|
|
'''Take a file name (stub) and returns the directory of the file (stub)'''
|
|
_dir_to_last_file = None
|
|
if _dir_to_last_file is None:
|
|
path = Path(__file__).absolute()
|
|
while 1:
|
|
path, tail = Path(path).split()
|
|
if Path(path, stub).is_file():
|
|
break
|
|
if (len(tail) == 0):
|
|
path = ""
|
|
if _G_DEBUG:
|
|
_LOGGER.debug('~Not able to find the path to that file '
|
|
'(stub) in a walk-up from currnet path.')
|
|
break
|
|
_dir_to_last_file = path
|
|
|
|
return _dir_to_last_file
|
|
# -------------------------------------------------------------------------
|
|
|
|
# -------------------------------------------------------------------------
|
|
def get_stub_check_path(in_path, check_stub='engineroot.txt'):
|
|
'''
|
|
Returns the branch root directory of the dev\'engineroot.txt'
|
|
(... or you can pass it another known stub)
|
|
|
|
so we can safely build relative filepaths within that branch.
|
|
|
|
If the stub is not found, it returns None
|
|
'''
|
|
path = Path(in_path).absolute()
|
|
|
|
while 1:
|
|
test_path = Path(path, check_stub)
|
|
|
|
if test_path.is_file():
|
|
return Path(test_path)
|
|
|
|
else:
|
|
path, tail = (path.parent, path.name)
|
|
|
|
if (len(tail) == 0):
|
|
return None
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
# TO DO: Move to a util package or module
|
|
def resolve_envar_path(envar='LY_DEV',
|
|
start_path=__file__,
|
|
check_stub='engineroot.txt',
|
|
dir_name='dev',
|
|
return_posix_str=False):
|
|
"""This is meant to resolve a '\dev' path for LY
|
|
|
|
First we validate the start_path (or we can't walk)
|
|
|
|
Then we walk up the startPath looking for stub
|
|
engineroot.txt is the default file marker for lumberyard
|
|
|
|
That is a pretty safe indicator that we found the right '\dev'
|
|
|
|
Second it checks if the env var 'LY_DEV' is set, use that instead!
|
|
|
|
"""
|
|
|
|
fallback = None
|
|
|
|
# amke sure the start_path exists, otherwise we have nothing to walk up
|
|
try:
|
|
start_path = Path(start_path)
|
|
start_path.exists()
|
|
if start_path.is_dir():
|
|
fallback = start_path
|
|
elif start_path.is_file():
|
|
fallback = start_path.parent
|
|
except Exception as e:
|
|
_LOGGER.info('Does NOT exist, no valid path: {0}'.format(start_path))
|
|
raise EnvironmentError
|
|
|
|
# generate a fallback based on finding know stub
|
|
# known stub is probably more reliable then dir name
|
|
|
|
fallback_stub = get_stub_check_path(fallback, check_stub)
|
|
# there is alos a chance this comes back None
|
|
|
|
# cast from is_file to directory
|
|
if fallback_stub and fallback_stub.is_file():
|
|
fallback = fallback_stub.parent
|
|
|
|
# check if it's set in env and fetch, or set to fallback
|
|
envar_path = Path(os.getenv(envar, fallback))
|
|
try:
|
|
envar_path.exists()
|
|
envar_path.is_dir()
|
|
envar_path.name.lower == dir_name
|
|
except Exception as e:
|
|
_LOGGER.info('Not a lumbertard \dev path: {0}'.format(e))
|
|
raise EnvironmentError
|
|
|
|
# last resort see if you can walk up to the dir name
|
|
if not envar_path:
|
|
envar_path = walk_up_dir(start_path, dir_name)
|
|
|
|
if envar_path and Path(envar_path).exists():
|
|
# box module can't serialize WindowsPath objects
|
|
# so Path object being stashed in this dict need .resolve() or .as_posix()
|
|
if return_posix_str:
|
|
return Path(envar_path).as_posix()
|
|
else:
|
|
return Path(envar_path)
|
|
else:
|
|
return None
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
# setting up storage dict, only using a Box (super dict) instead
|
|
_SYNTH_ENV_DICT = OrderedDict()
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
|
# --- Build Defaults ------------------------------------------------------
|
|
def stash_env(_SYNTH_ENV_DICT = OrderedDict()):
|
|
"""This block attempts to fetch or derive best guess fallback"""
|
|
|
|
# basic default fall backs (in case no environment exists)
|
|
# this first set is just the expected base_env
|
|
|
|
_LOGGER.info(STR_CROSSBAR)
|
|
_LOGGER.info('~ stash_env(), setting module fallbacks')
|
|
|
|
# box module can't serialize WindowsPath objects
|
|
# so Path object being stashed in this dict need .resolve() or .as_posix()
|
|
_THIS_MODULE_PATH = Path(__file__).as_posix()
|
|
|
|
# company name from env or default
|
|
# TAG_DEFAULT_COMPANY = str('Amazon.Lumberyard')
|
|
_G_COMPANY_NAME = os.getenv(ENVAR_COMPANY,
|
|
TAG_DEFAULT_COMPANY)
|
|
|
|
# we want to pack these all into a easy access dict
|
|
_SYNTH_ENV_DICT[ENVAR_COMPANY] = _G_COMPANY_NAME
|
|
|
|
# <ly>\dev Lumberyard ROOT PATH
|
|
# someone decided to use this as a root stub (for similar reasons in C++?)
|
|
# STUB_LY_DEV = str('engineroot.txt')
|
|
# I don't own \dev so I didn't want to check in anything new there
|
|
_LY_DEV = resolve_envar_path(ENVAR_LY_DEV, # envar
|
|
_THIS_MODULE_PATH, # search path
|
|
STUB_LY_DEV, # stub
|
|
TAG_DIR_LY_DEV) # dir
|
|
|
|
_SYNTH_ENV_DICT[ENVAR_LY_DEV] = _LY_DEV.as_posix()
|
|
|
|
# project name is a string, it should be project dir name
|
|
# for siloed testing and a purely synthetc env (nothing previously set)
|
|
# the default should probably be the 'DccScriptingInterface' (DCCsi)
|
|
# we also have a 'MockProject' sanndbox/silo, but we want to reseve that
|
|
# for testing overrides of the default synthetic env
|
|
|
|
# we can do two things here,
|
|
# first we can try to fetch from the env os.getenv('LY_PROJECT')
|
|
# If comes back None, allows you to specify a default fallback
|
|
# changed to just make the fallback what is set in boostrap
|
|
# so now it's less of a fallnack and more correct if not
|
|
# explicitly set
|
|
_LY_PROJECT = os.getenv(ENVAR_LY_PROJECT)
|
|
_SYNTH_ENV_DICT[ENVAR_LY_PROJECT] = _LY_PROJECT
|
|
|
|
_LY_BUILD_DIR_NAME = os.getenv(ENVAR_LY_BUILD_DIR_NAME,
|
|
TAG_DIR_LY_BUILD)
|
|
_SYNTH_ENV_DICT[ENVAR_LY_BUILD_DIR_NAME] = _LY_BUILD_DIR_NAME
|
|
|
|
# pattern for the above is (and will be repeated)
|
|
# _SOME_ENVAR = resolve_envar_path('ENVAR',
|
|
# 'path\\to\\start\\search',
|
|
# 'knownStubFileName',
|
|
# 'knownDirName')
|
|
# checks env for ENVAR first,
|
|
# then walks up search path looking for stub (fallback 0),
|
|
# then walks up niavely looking for a dirName (fallback 1)
|
|
|
|
# other paths that don't have a stub to search for as a fallback
|
|
# can be stashed in this manner
|
|
|
|
# variable containers for all of the default/base env config dccsi entry
|
|
# setting most basic defaults, not using an module import dependancies
|
|
# we can't know where the user installed or set up any of these,
|
|
# so we guess based on how I set up the original dev environment
|
|
|
|
# -- envar --
|
|
_LY_BUILD_PATH = Path(os.getenv(ENVAR_LY_BUILD_PATH,
|
|
PATH_LY_BUILD_PATH))
|
|
_SYNTH_ENV_DICT[ENVAR_LY_BUILD_PATH] = _LY_BUILD_PATH.as_posix()
|
|
|
|
# -- envar --
|
|
_LY_BIN_PATH = Path(os.getenv(ENVAR_LY_BIN_PATH,
|
|
PATH_LY_BIN_PATH))
|
|
# some of these need hard checks
|
|
if not _LY_BIN_PATH.exists():
|
|
raise Exception('LY_BIN_PATH does NOT exist: {0}'.format(_LY_BIN_PATH))
|
|
else:
|
|
_SYNTH_ENV_DICT[ENVAR_LY_BIN_PATH] = _LY_BIN_PATH.as_posix()
|
|
# adding to sys.path apparently doesn't work for .dll locations like Qt
|
|
os.environ['PATH'] = _LY_BIN_PATH.as_posix() + os.pathsep + os.environ['PATH']
|
|
|
|
# -- envar --
|
|
# if that stub marker doesn't exist assume DCCsi path (fallback 1)
|
|
_LY_PROJECT_PATH = Path(os.getenv(ENVAR_LY_PROJECT_PATH,
|
|
Path(_LY_DEV, _LY_PROJECT)))
|
|
_SYNTH_ENV_DICT[ENVAR_LY_PROJECT_PATH] = _LY_PROJECT_PATH.as_posix()
|
|
|
|
# -- envar --
|
|
_DCCSIG_PATH = resolve_envar_path(ENVAR_DCCSIG_PATH, # envar
|
|
_THIS_MODULE_PATH, # search path
|
|
STUB_LY_ROOT_DCCSI, # stub name
|
|
TAG_DEFAULT_PROJECT) # dir
|
|
_SYNTH_ENV_DICT[ENVAR_DCCSIG_PATH] = _DCCSIG_PATH.as_posix()
|
|
|
|
# -- envar --
|
|
_AZPY_PATH = Path(os.getenv(ENVAR_DCCSI_AZPY_PATH,
|
|
Path(_DCCSIG_PATH, TAG_DIR_DCCSI_AZPY)))
|
|
_SYNTH_ENV_DICT[ENVAR_DCCSI_AZPY_PATH] = _AZPY_PATH.as_posix()
|
|
|
|
# -- envar --
|
|
_DCCSI_SDK_PATH = Path(os.getenv(ENVAR_DCCSI_SDK_PATH,
|
|
Path(_DCCSIG_PATH, TAG_DIR_DCCSI_SDK)))
|
|
_SYNTH_ENV_DICT[ENVAR_DCCSI_SDK_PATH] = _DCCSI_SDK_PATH.as_posix()
|
|
|
|
# -- envar --
|
|
# external dccsi site-packages
|
|
_DCCSI_PYTHON_LIB_PATH = Path(os.getenv(ENVAR_DCCSI_PYTHON_LIB_PATH,
|
|
PATH_DCCSI_PYTHON_LIB_PATH))
|
|
_SYNTH_ENV_DICT[ENVAR_DCCSI_PYTHON_LIB_PATH] = _DCCSI_PYTHON_LIB_PATH.as_posix()
|
|
|
|
# -- envar --
|
|
# extend to py36 (conda env) and interpreter (wrapped as a .bat file)
|
|
_DEFAULT_PY_PATH = Path(_DCCSIG_PATH, TAG_DEFAULT_PY)
|
|
_DEFAULT_PY_PATH = Path(os.getenv(ENVAR_DCCSI_PY_DEFAULT,
|
|
_DEFAULT_PY_PATH))
|
|
_SYNTH_ENV_DICT[ENVAR_DCCSI_PY_DEFAULT] = _DEFAULT_PY_PATH.as_posix()
|
|
|
|
# -- envar --
|
|
# wing ide vars
|
|
_WINGHOME_DEFAULT_PATH = Path(os.getenv(ENVAR_WINGHOME,
|
|
PATH_DEFAULT_WINGHOME))
|
|
_SYNTH_ENV_DICT[ENVAR_WINGHOME] = _WINGHOME_DEFAULT_PATH.as_posix()
|
|
|
|
# -- done --
|
|
return _SYNTH_ENV_DICT
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
def init_ly_pyside(env_dict=_SYNTH_ENV_DICT):
|
|
"""sets access to lumberyards Qt dlls and PySide"""
|
|
|
|
# -- envar --
|
|
_QTFORPYTHON_PATH = Path(os.getenv(ENVAR_QTFORPYTHON_PATH,
|
|
PATH_QTFORPYTHON_PATH))
|
|
# some of these need hard checks
|
|
if not _QTFORPYTHON_PATH.exists():
|
|
raise Exception('QTFORPYTHON_PATH does NOT exist: {0}'.format(_QTFORPYTHON_PATH))
|
|
else:
|
|
_SYNTH_ENV_DICT[ENVAR_QTFORPYTHON_PATH] = _QTFORPYTHON_PATH.as_posix()
|
|
# ^ some of these should be put on sys.path and/or PYTHONPATH or PATH
|
|
#os.environ['PATH'] = _QTFORPYTHON_PATH.as_posix() + os.pathsep + os.environ['PATH']
|
|
site.addsitedir(_QTFORPYTHON_PATH.as_posix()) # PYTHONPATH
|
|
|
|
# -- envar --
|
|
_QT_PLUGIN_PATH = Path(os.getenv(ENVAR_QT_PLUGIN_PATH,
|
|
PATH_QT_PLUGIN_PATH))
|
|
# some of these need hard checks
|
|
if not _QT_PLUGIN_PATH.exists():
|
|
raise Exception('QT_PLUGIN_PATH does NOT exist: {0}'.format(_QT_PLUGIN_PATH))
|
|
else:
|
|
_SYNTH_ENV_DICT[ENVAR_QT_PLUGIN_PATH] = _QT_PLUGIN_PATH.as_posix()
|
|
# https://stackoverflow.com/questions/214852/python-module-dlls
|
|
os.environ['PATH'] = _QT_PLUGIN_PATH.as_posix() + os.pathsep + os.environ['PATH']
|
|
|
|
|
|
|
|
QTFORPYTHON_PATH = Path.joinpath(LY_DEV,
|
|
'Gems',
|
|
'QtForPython',
|
|
'3rdParty',
|
|
'pyside2',
|
|
'windows',
|
|
'release').resolve()
|
|
os.environ["DYNACONF_QTFORPYTHON_PATH"] = str(QTFORPYTHON_PATH)
|
|
os.environ["QTFORPYTHON_PATH"] = str(QTFORPYTHON_PATH)
|
|
sys.path.insert(1, str(QTFORPYTHON_PATH))
|
|
site.addsitedir(str(QTFORPYTHON_PATH))
|
|
|
|
LY_BIN_PATH = Path.joinpath(LY_DEV,
|
|
'windows_vs2019',
|
|
'bin',
|
|
'profile').resolve()
|
|
os.environ["DYNACONF_LY_BIN_PATH"] = str(LY_BIN_PATH)
|
|
os.environ["LY_BIN_PATH"] = str(LY_BIN_PATH)
|
|
site.addsitedir(str(LY_BIN_PATH))
|
|
sys.path.insert(1, str(LY_BIN_PATH))
|
|
|
|
QT_PLUGIN_PATH = Path.joinpath(LY_BIN_PATH,
|
|
'EditorPlugins').resolve()
|
|
os.environ["DYNACONF_QT_PLUGIN_PATH"] = str(QT_PLUGIN_PATH)
|
|
os.environ["QT_PLUGIN_PATH"] = str(QT_PLUGIN_PATH)
|
|
site.addsitedir(str(QT_PLUGIN_PATH))
|
|
sys.path.insert(1, str(QT_PLUGIN_PATH))
|
|
|
|
QT_QPA_PLATFORM_PLUGIN_PATH = Path.joinpath(QT_PLUGIN_PATH,
|
|
'platforms').resolve()
|
|
os.environ["DYNACONF_QT_QPA_PLATFORM_PLUGIN_PATH"] = str(QT_QPA_PLATFORM_PLUGIN_PATH)
|
|
os.environ["QT_QPA_PLATFORM_PLUGIN_PATH"] = str(QT_QPA_PLATFORM_PLUGIN_PATH)
|
|
site.addsitedir(str(QT_QPA_PLATFORM_PLUGIN_PATH))
|
|
sys.path.insert(1, str(QT_QPA_PLATFORM_PLUGIN_PATH))
|
|
|
|
# add Qt binaries to the Windows path to handle findings DLL file dependencies
|
|
if sys.platform.startswith('win'):
|
|
path = os.environ['PATH']
|
|
newPath = ''
|
|
newPath += str(LY_BIN_PATH) + os.pathsep
|
|
newPath += str(Path.joinpath(QTFORPYTHON_PATH,
|
|
'shiboken2').resolve()) + os.pathsep
|
|
newPath += str(Path.joinpath(QTFORPYTHON_PATH,
|
|
'PySide2').resolve()) + os.pathsep
|
|
newPath += path
|
|
os.environ['PATH']=newPath
|
|
_LOGGER.debug('PySide2 bootstrapped PATH for Windows.')
|
|
|
|
try:
|
|
import PySide2
|
|
_LOGGER.debug('DCCsi, config.py: SUCCESS: import PySide2')
|
|
_LOGGER.debug(PySide2)
|
|
status = True
|
|
except ImportError as e:
|
|
_LOGGER.debug('DCCsi, config.py: FAILURE: import PySide2')
|
|
status = False
|
|
raise(e)
|
|
|
|
try:
|
|
import shiboken2
|
|
_LOGGER.debug('DCCsi, config.py: SUCCESS: import shiboken2')
|
|
_LOGGER.debug(shiboken2)
|
|
status = True
|
|
except ImportError as e:
|
|
_LOGGER.debug('DCCsi, config.py: FAILURE: import shiboken2')
|
|
status = False
|
|
raise(e)
|
|
|
|
return status
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
# py 2 and 3 compatible iter
|
|
def get_items(dict_object):
|
|
for key in dict_object:
|
|
yield key, dict_object[key]
|
|
|
|
def set_env(dict_object):
|
|
for key, value in get_items(dict_object):
|
|
try:
|
|
os.environ[key] = value
|
|
except EnvironmentError as e:
|
|
_LOGGER.error('ERROR: {e}')
|
|
return dict_object
|
|
|
|
# will trigger on any import
|
|
# suggested use: from synthetic_env import _SYNTH_ENV_DICT
|
|
#_SYNTH_ENV_DICT = set_env(_SYNTH_ENV_DICT)
|
|
|
|
# -------------------------------------------------------------------------
|
|
def test_Qt():
|
|
try:
|
|
import PySide2
|
|
print('PySide2: {0}'.format(Path(PySide2.__file__).as_posix()))
|
|
# builtins.ImportError: DLL load failed: The specified procedure could not be found.
|
|
from PySide2 import QtCore
|
|
from PySide2 import QtWidgets
|
|
except IOError as e:
|
|
print('ERROR: {0}'.format(e))
|
|
raise e
|
|
|
|
try:
|
|
qapp = QtWidgets.QApplication([])
|
|
except:
|
|
# already exists
|
|
qapp = QtWidgets.QApplication.instance()
|
|
|
|
try:
|
|
buttonFlags = QtWidgets.QMessageBox.information(QtWidgets.QApplication.activeWindow(), 'title', 'ok')
|
|
qapp.instance().quit
|
|
qapp.exit()
|
|
except Exception as e:
|
|
print('ERROR: {0}'.format(e))
|
|
raise e
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
|
# -------------------------------------------------------------------------
|
|
def main(argv, env_dict_object, debug=False, devmode=False):
|
|
import getopt
|
|
try:
|
|
opts, args = getopt.getopt(argv, "hvt:", ["verbose=", "test="])
|
|
except getopt.GetoptError:
|
|
# not logging, print to cmd line console
|
|
print('synthetic_env.py -v <print_dict> -t <run_test>')
|
|
sys.exit(2)
|
|
|
|
for opt, arg in opts:
|
|
if opt == '-h':
|
|
print('synthetic_env.py -v <print_dict> -t <run test>')
|
|
sys.exit()
|
|
|
|
elif opt in ("-t", "--test"):
|
|
debug = True
|
|
devmode = True
|
|
test()
|
|
|
|
elif opt in ("-v", "--verbose"):
|
|
try:
|
|
from box import Box
|
|
except ImportError as e:
|
|
print('ERROR: {0}'.format(e))
|
|
raise e
|
|
try:
|
|
env_dict_object = Box(env_dict_object)
|
|
print(str(env_dict_object.to_json(sort_keys=False,
|
|
indent=4)))
|
|
except Exception as e:
|
|
print('ERROR: {0}'.format(e))
|
|
raise e
|
|
# -------------------------------------------------------------------------
|
|
|
|
|
|
###########################################################################
|
|
# Main Code Block, runs this script as main (testing)
|
|
# -------------------------------------------------------------------------
|
|
if __name__ == '__main__':
|
|
# run simple tests?
|
|
_G_DEBUG = True
|
|
_DCCSI_DEV_MODE = True
|
|
|
|
if _DCCSI_DEV_MODE:
|
|
try:
|
|
import azpy.test.entry_test
|
|
print('SUCCESS: import azpy.test.entry_test')
|
|
azpy.test.entry_test.main(verbose=True, connect_debugger=True)
|
|
except ImportError as e:
|
|
print('ERROR: {0}'.format(e))
|
|
raise e
|
|
|
|
# init, stash and then activate
|
|
_SYNTH_ENV_DICT = OrderedDict()
|
|
_SYNTH_ENV_DICT = stash_env(_SYNTH_ENV_DICT)
|
|
_SYNTH_ENV_DICT = set_env(_SYNTH_ENV_DICT)
|
|
|
|
main(sys.argv[1:], _SYNTH_ENV_DICT, _G_DEBUG, _DCCSI_DEV_MODE)
|
|
|
|
if _G_DEBUG:
|
|
|
|
tempBoxJsonFilePath = Path(_SYNTH_ENV_DICT['DCCSIG_PATH'], '.temp')
|
|
tempBoxJsonFilePath = Path(tempBoxJsonFilePath, 'boxDumpTest.json')
|
|
_LOGGER.info(f'tempBoxJsonFilePath: {tempBoxJsonFilePath}')
|
|
|
|
try:
|
|
tempBoxJsonFilePath.mkdir(parents=True, exist_ok=True)
|
|
tempBoxJsonFilePath.touch(mode=0o777, exist_ok=True)
|
|
except Exception as e:
|
|
_LOGGER.info(e)
|
|
|
|
_LOGGER.info('~ writting with Box.to_json')
|
|
try:
|
|
from box import Box
|
|
_SYNTH_ENV_DICT = Box(_SYNTH_ENV_DICT)
|
|
_LOGGER.info(type(_SYNTH_ENV_DICT))
|
|
except Exception as e:
|
|
_LOGGER.info(e)
|
|
|
|
# -- BOX STORE ------
|
|
_LOGGER.info(str(_SYNTH_ENV_DICT.to_json(sort_keys=False,
|
|
indent=4)))
|
|
try:
|
|
#_SYNTH_ENV_DICT.to_json(filename=None, encoding='utf-8', errors='strict')
|
|
#from os import fspath
|
|
#tempBoxJsonFilePath = fspath(tempBoxJsonFilePath)
|
|
_SYNTH_ENV_DICT.to_json(filename=tempBoxJsonFilePath.as_posix(),
|
|
sort_keys=False,
|
|
indent=4)
|
|
_LOGGER.info('~ Box.to_json SUCCESS')
|
|
except Exception as e:
|
|
_LOGGER.info(e)
|
|
# if this raises an exception related to WindowsPath
|
|
# that a path obj was stashed, use .as_posix() when stashing
|
|
raise e
|
|
|
|
_LOGGER.info('listing envar keys: {0}'.format(_SYNTH_ENV_DICT.keys()))
|
|
|
|
# -- BOX READ ------
|
|
_LOGGER.info('~ read Box.from_json')
|
|
|
|
parseJsonBox = Box.from_json(filename=tempBoxJsonFilePath,
|
|
encoding="utf-8",
|
|
errors="strict",
|
|
object_pairs_hook=OrderedDict)
|
|
|
|
_LOGGER.info('~ pretty print parsed Box.from_json')
|
|
|
|
_LOGGER.info(json.dumps(parseJsonBox, indent=4, sort_keys=False, ensure_ascii=False))
|
|
|
|
# also run the Qt/PySide2 test
|
|
test_Qt()
|
|
|
|
del _LOGGER
|