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.
o3de/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/azpy/synthetic_env.py

731 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
O3DE_PROJECT : name of project (project directory)
O3DE_DEV : path to Lumberyard \dev root
O3DE_PROJECT_PATH : path to project dir
DCCSIG_PATH : path to the DCCsi Gem root
DCCSI_TOOLS_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=%O3DE_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 _DCCSI_GDEBUG 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 importlib.util
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)
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# O3DE extensions
from pathlib import Path
# set up global space, logging etc.
import azpy.env_bool as env_bool
from azpy.constants import ENVAR_DCCSI_GDEBUG
from azpy.constants import ENVAR_DCCSI_DEV_MODE
from azpy.constants import FRMT_LOG_LONG
_DCCSI_GDEBUG = env_bool.env_bool(ENVAR_DCCSI_GDEBUG, False)
_DCCSI_DEV_MODE = env_bool.env_bool(ENVAR_DCCSI_DEV_MODE, False)
_PACKAGENAME = 'DCCsi.azpy.synthetic_env'
# set up module logging
for handler in _logging.root.handlers[:]:
_logging.root.removeHandler(handler)
_LOGGER = _logging.getLogger(_PACKAGENAME)
_logging.basicConfig(format=FRMT_LOG_LONG)
_LOGGER.debug('Initializing: {0}.'.format({_PACKAGENAME}))
_LOGGER.debug('_DCCSIG_PATH: {}'.format(_DCCSIG_PATH))
_LOGGER.debug('_DCCSI_GDEBUG: {}'.format(_DCCSI_GDEBUG))
_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
_DCCSI_GDEBUG = 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 _DCCSI_GDEBUG:
_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='O3DE_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 'O3DE_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_O3DE_DEV = str('engineroot.txt')
# I don't own \dev so I didn't want to check in anything new there
_O3DE_DEV = resolve_envar_path(ENVAR_O3DE_DEV, # envar
_THIS_MODULE_PATH, # search path
STUB_O3DE_DEV, # stub
TAG_DIR_O3DE_DEV) # dir
_SYNTH_ENV_DICT[ENVAR_O3DE_DEV] = _O3DE_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('O3DE_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
_O3DE_PROJECT = os.getenv(ENVAR_O3DE_PROJECT)
_SYNTH_ENV_DICT[ENVAR_O3DE_PROJECT] = _O3DE_PROJECT
_O3DE_BUILD_DIR_NAME = os.getenv(ENVAR_O3DE_BUILD_DIR_NAME,
TAG_DIR_O3DE_BUILD_FOLDER)
_SYNTH_ENV_DICT[ENVAR_O3DE_BUILD_DIR_NAME] = _O3DE_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 --
_O3DE_BUILD_PATH = Path(os.getenv(ENVAR_O3DE_BUILD_PATH,
PATH_O3DE_BUILD_PATH))
_SYNTH_ENV_DICT[ENVAR_O3DE_BUILD_PATH] = _O3DE_BUILD_PATH.as_posix()
# -- envar --
_O3DE_BIN_PATH = Path(os.getenv(ENVAR_O3DE_BIN_PATH,
PATH_O3DE_BIN_PATH))
# some of these need hard checks
if not _O3DE_BIN_PATH.exists():
raise Exception('O3DE_BIN_PATH does NOT exist: {0}'.format(_O3DE_BIN_PATH))
else:
_SYNTH_ENV_DICT[ENVAR_O3DE_BIN_PATH] = _O3DE_BIN_PATH.as_posix()
# adding to sys.path apparently doesn't work for .dll locations like Qt
os.environ['PATH'] = _O3DE_BIN_PATH.as_posix() + os.pathsep + os.environ['PATH']
# -- envar --
# if that stub marker doesn't exist assume DCCsi path (fallback 1)
_O3DE_PROJECT_PATH = Path(os.getenv(ENVAR_O3DE_PROJECT_PATH,
Path(_O3DE_DEV, _O3DE_PROJECT)))
_SYNTH_ENV_DICT[ENVAR_O3DE_PROJECT_PATH] = _O3DE_PROJECT_PATH.as_posix()
# -- envar --
_DCCSIG_PATH = resolve_envar_path(ENVAR_DCCSIG_PATH, # envar
_THIS_MODULE_PATH, # search path
STUB_O3DE_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_TOOLS_PATH = Path(os.getenv(ENVAR_DCCSI_TOOLS_PATH,
Path(_DCCSIG_PATH, TAG_DIR_DCCSI_TOOLS)))
_SYNTH_ENV_DICT[ENVAR_DCCSI_TOOLS_PATH] = _DCCSI_TOOLS_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(O3DE_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))
O3DE_BIN_PATH = Path.joinpath(O3DE_DEV,
'windows_vs2019',
'bin',
'profile').resolve()
os.environ["DYNACONF_O3DE_BIN_PATH"] = str(O3DE_BIN_PATH)
os.environ["O3DE_BIN_PATH"] = str(O3DE_BIN_PATH)
site.addsitedir(str(O3DE_BIN_PATH))
sys.path.insert(1, str(O3DE_BIN_PATH))
QT_PLUGIN_PATH = Path.joinpath(O3DE_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(O3DE_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
_LOGGER.info('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:
_LOGGER.error('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:
_LOGGER.error('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 as e:
# not logging, print to cmd line console
_LOGGER.error('synthetic_env.py -v <print_dict> -t <run_test>')
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
_LOGGER.info('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:
_LOGGER.error('ERROR: {0}'.format(e))
raise e
try:
env_dict_object = Box(env_dict_object)
_LOGGER.info(str(env_dict_object.to_json(sort_keys=False,
indent=4)))
except Exception as e:
_LOGGER.error('ERROR: {0}'.format(e))
raise e
# -------------------------------------------------------------------------
###########################################################################
# Main Code Block, runs this script as main (testing)
# -------------------------------------------------------------------------
if __name__ == '__main__':
# run simple tests?
_DCCSI_GDEBUG = True
_DCCSI_DEV_MODE = True
if _DCCSI_DEV_MODE:
try:
import azpy.test.entry_test
_LOGGER.info('SUCCESS: import azpy.test.entry_test')
azpy.test.entry_test.main(verbose=True, connect_debugger=True)
except ImportError as e:
_LOGGER.error('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, _DCCSI_GDEBUG, _DCCSI_DEV_MODE)
if _DCCSI_GDEBUG:
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