| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- # 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
- #
- # -------------------------------------------------------------------------
- """! @brief
- <DCCsi>/azpy/shared/utils/__init__.py
- This module moves some utility methods out of __init__ files so we can reuse
- and reduce boiler plate code copied across modules.
- """
- # --------------------------------------------------------------------------
- # standard imports
- import sys
- import errno
- import os
- import site
- import os.path
- from pathlib import Path
- import logging as _logging
- # -------------------------------------------------------------------------
- # There are many __init__ files throughout the dccsi that need to be refactored
- # and updated to share this module for common utils.
- # -------------------------------------------------------------------------
- # Global Scope
- _MODULENAME = 'azpy.shared.utils.init'
- _LOGGER = _logging.getLogger(_MODULENAME)
- _LOGGER.debug('Initializing: {}.'.format({_MODULENAME}))
- __all__ = ['makedirs',
- 'FileExistsError',
- 'initialize_logger',
- 'test_imports']
- # to refactor things into this module, some of this was brought along
- # and this could be streamlined in a future refactor pass to slim down
- # we need to set up basic access to the DCCsi
- _MODULE_PATH = os.path.realpath(__file__) # To Do: what if frozen?
- _PATH_DCCSIG = os.path.normpath(os.path.join(_MODULE_PATH, '../..'))
- _PATH_DCCSIG = os.getenv('PATH_DCCSIG', _PATH_DCCSIG)
- site.addsitedir(_PATH_DCCSIG)
- import azpy.constants as constants
- # For now, use dccsi as the default project location6
- # This could be improved by deriving the project from o3de and/or managed settings
- _PATH_O3DE_PROJECT = Path(os.getenv(constants.ENVAR_PATH_O3DE_PROJECT, _PATH_DCCSIG))
- _LOGGER.debug('Default PATH_O3DE_PROJECT" {}'.format(_PATH_O3DE_PROJECT.resolve()))
- from azpy.config_utils import ENVAR_DCCSI_GDEBUG
- from azpy.env_bool import env_bool
- _DCCSI_GDEBUG = env_bool(ENVAR_DCCSI_GDEBUG, False)
- # 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(PATH_O3DE_PROJECT=_PATH_O3DE_PROJECT.resolve(),
- TAG_DCCSI_NICKNAME=TAG_DCCSI_NICKNAME))
- # -------------------------------------------------------------------------
- # -------------------------------------------------------------------------
- # This method could be updated for py3+ to use pathlib
- 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
- # -------------------------------------------------------------------------
- # -------------------------------------------------------------------------
- # This method we intend to replace with a logging class/module in the future
- def initialize_logger(name,
- log_to_file=False,
- default_log_level=_logging.NOTSET,
- propagate=False):
- """Start a azpy logger"""
- _logger = _logging.getLogger(name)
- _logger.propagate = propagate
- 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))
- if not _DCCSI_LOG_PATH.exists():
- try:
- os.makedirs(_DCCSI_LOG_PATH.as_posix())
- 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
- # -------------------------------------------------------------------------
- # -------------------------------------------------------------------------
- def test_imports(_all=__all__, _pkg=_MODULENAME, _logger=_LOGGER):
- # If in dev mode this will test imports of __all__
- _logger.debug("~ Import triggered from: {}".format(_pkg))
- import importlib
- for mod_str in _all:
- try:
- # this is py2.7 compatible
- # in py3.5+, we can use importlib.util instead
- importlib.import_module('.{}'.format(mod_str), _pkg)
- _logger.info("~ Imported module: {0}.{1}".format(_pkg, mod_str))
- except Exception as e:
- _logger.warning('~ {}'.format(e))
- _logger.warning("~ {0}.{1} :: ImportFail".format(_pkg, mod_str))
- return False
- return True
- # -------------------------------------------------------------------------
|