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/__init__.py

263 lines
9.5 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 -------------------------------------------
__copyright__ = "Copyright 2021, Amazon"
__credits__ = ["Jonny Galloway", "Ben Black"]
__license__ = "EULA"
__version__ = "0.0.1"
__status__ = "Prototype"
# --------------------------------------------------------------------------
# standard imports
import sys
import errno
import os
import os.path
import site
import re
import logging as _logging
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# global scope
_PACKAGENAME = 'azpy'
__all__ = ['config_utils',
'constants',
'env_bool',
'return_stub',
'core',
'dcc',
'dev',
'test']
# we need to set up basic access to the DCCsi
_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)
# azpy
import azpy.return_stub as return_stub
import azpy.env_bool as env_bool
import azpy.constants as constants
import azpy.config_utils as config_utils
_DCCSI_GDEBUG = env_bool.env_bool(constants.ENVAR_DCCSI_GDEBUG, False)
_DCCSI_DEV_MODE = env_bool.env_bool(constants.ENVAR_DCCSI_DEV_MODE, False)
_DCCSI_LOGLEVEL = int(env_bool.env_bool(constants.ENVAR_DCCSI_LOGLEVEL, int(20)))
if _DCCSI_GDEBUG:
_DCCSI_LOGLEVEL = int(10)
# for py2.7 (Maya) we provide this, so we must assume some bootstrapping
# has occured, see DccScriptingInterface\\config.py (_DCCSI_PYTHON_LIB_PATH)
try:
import pathlib
except:
import pathlib2 as pathlib
from pathlib import Path
if _DCCSI_GDEBUG:
print('[DCCsi][AZPY] DEBUG BREADCRUMB, pathlib is: {}'.format(pathlib))
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# set up module logging
#for handler in _logging.root.handlers[:]:
#_logging.root.removeHandler(handler)
_logging.basicConfig(format=constants.FRMT_LOG_LONG, level=_DCCSI_LOGLEVEL)
_LOGGER = _logging.getLogger(_PACKAGENAME)
_LOGGER.debug('Initializing: {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# get/set the project name
_O3DE_DEV = Path(os.getenv(constants.ENVAR_O3DE_DEV,
config_utils.get_stub_check_path(in_path=os.getcwd(),
check_stub='engine.json')))
_LOGGER.debug('_O3DE_DEV" {}'.format(_O3DE_DEV.resolve()))
_O3DE_PROJECT_PATH = Path(os.getenv(constants.ENVAR_O3DE_PROJECT_PATH,
config_utils.get_o3de_project_path()))
_LOGGER.debug('_O3DE_PROJECT_PATH" {}'.format(_O3DE_PROJECT_PATH.resolve()))
# get/set the project name
if _O3DE_PROJECT_PATH:
_O3DE_PROJECT = str(os.getenv(constants.ENVAR_O3DE_PROJECT,
_O3DE_PROJECT_PATH.name))
else:
_O3DE_PROJECT='o3de'
# project cache log dir path
from azpy.constants import TAG_DCCSI_NICKNAME
from azpy.constants import PATH_DCCSI_LOG_PATH
_DCCSI_LOG_PATH = Path(PATH_DCCSI_LOG_PATH.format(O3DE_PROJECT_PATH=_O3DE_PROJECT_PATH.resolve(),
TAG_DCCSI_NICKNAME=TAG_DCCSI_NICKNAME))
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def makedirs(folder, *args, **kwargs):
"""a makedirs for py2.7 support"""
try:
return os.makedirs(folder, exist_ok=True, *args, **kwargs)
except TypeError:
# Unexpected arguments encountered
pass
try:
# Should work is TypeError was caused by exist_ok, eg., Py2
return os.makedirs(folder, *args, **kwargs)
except OSError as e:
if e.errno != errno.EEXIST:
raise
if os.path.isfile(folder):
# folder is a file, raise OSError just like os.makedirs() in Py3
raise
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
class FileExistsError(Exception):
"""Implements a stand-in Exception for py2.7"""
def __init__(self, message, errors):
# Call the base class constructor with the parameters it needs
super(FileExistsError, self).__init__(message)
# Now for your custom code...
self.errors = errors
if sys.version_info.major < 3:
FileExistsError = FileExistsError
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def initialize_logger(name,
log_to_file=False,
default_log_level=_logging.NOTSET,
propogate=False):
"""Start a azpy logger"""
_logger = _logging.getLogger(name)
_logger.propagate = propogate
if not _logger.handlers:
_log_level = int(os.getenv('DCCSI_LOGLEVEL', default_log_level))
if _DCCSI_GDEBUG:
_log_level = int(10) # force when debugging
print('_log_level: {}'.format(_log_level))
if _log_level:
ch = _logging.StreamHandler(sys.stdout)
ch.setLevel(_log_level)
formatter = _logging.Formatter(constants.FRMT_LOG_LONG)
ch.setFormatter(formatter)
_logger.addHandler(ch)
_logger.setLevel(_log_level)
else:
_logger.addHandler(_logging.NullHandler())
# optionally add the log file handler (off by default)
if log_to_file:
_logger.info('DCCSI_LOG_PATH: {}'.format(_DCCSI_LOG_PATH))
try:
# exist_ok, isn't available in py2.7 pathlib
# because it doesn't exist for os.makedirs
# pathlib2 backport used instead (see above)
if sys.version_info.major >= 3:
_DCCSI_LOG_PATH.mkdir(parents=True, exist_ok=True)
else:
makedirs(str(_DCCSI_LOG_PATH.resolve())) # py2.7
except FileExistsError:
# except FileExistsError: doesn't exist in py2.7
_logger.debug("Folder is already there")
else:
_logger.debug("Folder was created")
_log_filepath = Path(_DCCSI_LOG_PATH, '{}.log'.format(name))
try:
_log_filepath.touch(mode=0o666, exist_ok=True)
except FileExistsError:
_logger.debug("Log file is already there: {}".format(_log_filepath))
else:
_logger.debug("Log file was created: {}".format(_log_filepath))
if _log_filepath.exists():
file_formatter = _logging.Formatter(constants.FRMT_LOG_LONG)
file_handler = _logging.FileHandler(str(_log_filepath))
file_handler.setLevel(_logging.DEBUG)
file_handler.setFormatter(file_formatter)
_logger.addHandler(file_handler)
return _logger
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
# some simple logger tests
# evoke the filehandlers and test writting to the log file
if _DCCSI_GDEBUG:
_LOGGER.info('Forced Info! for {0}.'.format({_PACKAGENAME}))
_LOGGER.error('Forced ERROR! for {0}.'.format({_PACKAGENAME}))
# debug breadcrumbs to check this module and used paths
_LOGGER.debug('MODULE_PATH: {}'.format(_MODULE_PATH))
_LOGGER.debug('O3DE_DEV_PATH: {}'.format(_O3DE_DEV))
_LOGGER.debug('DCCSI_PATH: {}'.format(_DCCSIG_PATH))
_LOGGER.debug('O3DE_PROJECT_TAG: {}'.format(_O3DE_PROJECT))
_LOGGER.debug('DCCSI_LOG_PATH: {}'.format(_DCCSI_LOG_PATH))
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def test_imports(_all=__all__,
_pkg=_PACKAGENAME,
_logger=_LOGGER):
# If in dev mode this will test imports of __all__
_logger.debug("~ Import triggered from: {0}".format(_pkg))
import importlib
for pkgStr in _all:
try:
# this is py2.7 compatible
# in py3.5+, we can use importlib.util instead
importlib.import_module('.' + pkgStr, _pkg)
_logger.debug("~ Imported module: {0}".format(pkgStr))
except Exception as e:
_logger.warning('~ {0}'.format(e))
_logger.warning("~ {0} :: ImportFail".format(pkgStr))
return False
return True
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
if _DCCSI_DEV_MODE:
# If in dev mode this will test imports of __all__
_LOGGER.debug('Testing Imports: {0}'.format(_PACKAGENAME))
test_imports(__all__)
# -------------------------------------------------------------------------
del _LOGGER
###########################################################################
# Main Code Block, runs this script as main (testing)
# -------------------------------------------------------------------------
if __name__ == '__main__':
_DCCSI_GDEBUG = True
_DCCSI_DEV_MODE = True
if _DCCSI_GDEBUG:
print(_DCCSIG_PATH)
test_imports()