Integrating github/staging through commit ab87ed9
This commit is contained in:
@@ -12,33 +12,31 @@ Utility class to resolve Lumberyard directory paths & file mappings.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
import warnings
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
from ly_test_tools.lumberyard.asset_processor import ASSET_PROCESSOR_PLATFORM_MAP
|
||||
from ly_test_tools.environment.file_system import find_ancestor_file
|
||||
|
||||
def _find_engine_root(initial_path):
|
||||
# type: (str) -> tuple
|
||||
# type: (str) -> str
|
||||
"""
|
||||
Attempts to find the root engine directory to set the values for engine_root and dev_path.
|
||||
Attempts to find the root engine directory to set the values for engine_root
|
||||
Assumes it exists at or above the provided "initial_path", and not in a separate directory tree
|
||||
ex. for the directory "C:\\root_dir\\dev\\":
|
||||
"C:\\root_dir\\" is the engine_root
|
||||
"C:\\root_dir\\dev\\" is the dev_path
|
||||
ex. for the directory "C:\\root_dir\\":
|
||||
If it contains an "engine.json" file then it is the engine root "C:\\root_dir\\"
|
||||
:param initial_path: The initial directory to search for root from
|
||||
:return: a tuple of 2 strings representing the engine_root and dev_path
|
||||
:return: a string representing the engine_root
|
||||
"""
|
||||
root_file = "engineroot.txt"
|
||||
root_file = "engine.json"
|
||||
current_dir = initial_path
|
||||
|
||||
# Look upward a handful of levels, before assuming a missing root directory
|
||||
# Assumes folder structure similar to: engine_root/dev/Tools/.../ly_test_tools/builtin
|
||||
for _ in range(15):
|
||||
if os.path.exists(os.path.join(current_dir, root_file)):
|
||||
# The parent of the directory containing the engineroot.txt is the root directory
|
||||
engine_root = os.path.abspath(os.path.join(current_dir, os.path.pardir))
|
||||
dev_path = current_dir
|
||||
return engine_root, dev_path
|
||||
engine_root = current_dir
|
||||
return engine_root
|
||||
# Using an explicit else to avoid aberrant behavior from following filesystem links
|
||||
else:
|
||||
current_dir = os.path.abspath(os.path.join(current_dir, os.path.pardir))
|
||||
@@ -46,6 +44,19 @@ def _find_engine_root(initial_path):
|
||||
raise OSError(f"Unable to find engine root directory. Verify root file '{root_file}' exists")
|
||||
|
||||
|
||||
def _find_project_json(engine_root, project):
|
||||
# type (None) -> str
|
||||
"""
|
||||
Find the project.json file for this project.
|
||||
:return: Full path to the project.json file
|
||||
"""
|
||||
project_json = find_ancestor_file('project.json')
|
||||
if not project_json:
|
||||
project_json = os.path.join(engine_root, project, 'project.json')
|
||||
|
||||
return project_json
|
||||
|
||||
|
||||
class AbstractResourceLocator(object):
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
@@ -53,13 +64,14 @@ class AbstractResourceLocator(object):
|
||||
# type: (str, str) -> AbstractResourceLocator
|
||||
"""
|
||||
:param build_directory: The path to the build directory (i.e. <engine_root>/dev/windows_vs2017/bin/profile)
|
||||
:param project: The game project (i.e. AutomatedTesting or StarterGame)
|
||||
:param project: The game project (i.e. AutomatedTesting)
|
||||
"""
|
||||
engine_root, dev_path = _find_engine_root(os.path.abspath(__file__))
|
||||
initial_search_path = str(pathlib.Path(__file__).resolve()) # __file__ is lowercase, this restores casing
|
||||
engine_root = _find_engine_root(initial_search_path)
|
||||
self._build_directory = build_directory
|
||||
|
||||
self._engine_root = engine_root
|
||||
self._dev_path = dev_path
|
||||
self._project_json = _find_project_json(engine_root, project)
|
||||
self._project = project
|
||||
self._cache_override = None
|
||||
self._db_override = None
|
||||
@@ -74,14 +86,6 @@ class AbstractResourceLocator(object):
|
||||
"""
|
||||
return self._engine_root
|
||||
|
||||
def dev(self):
|
||||
"""
|
||||
Returns the path to the dev directory
|
||||
ex. <engine_root>\\dev
|
||||
:return: dev_path
|
||||
"""
|
||||
return self._dev_path
|
||||
|
||||
def third_party(self):
|
||||
"""
|
||||
Return path to 3rdParty directory
|
||||
@@ -118,11 +122,18 @@ class AbstractResourceLocator(object):
|
||||
def project(self):
|
||||
"""
|
||||
Return path to the project directory
|
||||
ex. engine_root/dev/AutomatedTesting
|
||||
:return: path to <engine_root>/dev/Project
|
||||
ex. engine_root/dev/AutomatedTesting for included projects or some_dir/project for external projects.
|
||||
:return: path to the project directory
|
||||
"""
|
||||
return os.path.join(self.dev(), self._project)
|
||||
return os.path.dirname(self._project_json)
|
||||
|
||||
def project_settings(self):
|
||||
"""
|
||||
Return full path to the project.json file for this project.
|
||||
:return: Full path to the project.json file for this project.
|
||||
"""
|
||||
return self._project_json
|
||||
|
||||
def asset_processor(self):
|
||||
"""
|
||||
Return path for the AssetProcessor executable.
|
||||
@@ -210,7 +221,6 @@ class AbstractResourceLocator(object):
|
||||
"""
|
||||
return os.path.join(self.ap_log_dir(), 'JobLogs')
|
||||
|
||||
|
||||
def ap_batch_log(self):
|
||||
"""
|
||||
Return path to AssetProcessorBatch's log file using the project bin dir
|
||||
@@ -241,10 +251,10 @@ class AbstractResourceLocator(object):
|
||||
return os.path.join(self.build_directory(), 'CrySCompileServer')
|
||||
|
||||
def bootstrap_config_file(self):
|
||||
return os.path.join(self.dev(), 'bootstrap.cfg')
|
||||
return os.path.join(self.engine_root(), 'bootstrap.cfg')
|
||||
|
||||
def asset_processor_config_file(self):
|
||||
return os.path.join(self.dev(), 'AssetProcessorPlatformConfig.setreg')
|
||||
return os.path.join(self.engine_root(), 'AssetProcessorPlatformConfig.setreg')
|
||||
|
||||
def autoexec_file(self):
|
||||
return os.path.join(
|
||||
@@ -257,7 +267,7 @@ class AbstractResourceLocator(object):
|
||||
Return the path to the TestResults directory containing test artifacts.
|
||||
:return: path to TestResults dir
|
||||
"""
|
||||
return os.path.join(self.dev(), "TestResults")
|
||||
return os.path.join(self.engine_root(), "TestResults")
|
||||
|
||||
def devices_file(self):
|
||||
"""
|
||||
|
||||
@@ -36,7 +36,7 @@ class _MacResourceLocator(AbstractResourceLocator):
|
||||
ex. engine_root/dev/system_osx_osx_gl.cfg
|
||||
:return: path to the platform config file
|
||||
"""
|
||||
return os.path.join(self.dev(), CONFIG_FILE)
|
||||
return os.path.join(self.engine_root(), CONFIG_FILE)
|
||||
|
||||
def platform_cache(self):
|
||||
"""
|
||||
|
||||
@@ -42,7 +42,7 @@ class _WindowsResourceLocator(AbstractResourceLocator):
|
||||
ex. engine_root/dev/system_osx_osx_gl.cfg
|
||||
:return: path to the platform config file
|
||||
"""
|
||||
return os.path.join(self.dev(), CONFIG_FILE)
|
||||
return os.path.join(self.engine_root(), CONFIG_FILE)
|
||||
|
||||
def platform_cache(self):
|
||||
"""
|
||||
|
||||
@@ -62,33 +62,6 @@ def create_builtin_workspace(
|
||||
return instance
|
||||
|
||||
|
||||
def setup_bootstrap_project(workspace, project):
|
||||
"""
|
||||
Sets up the bootstrap.cfg file to be used for the given project
|
||||
|
||||
:param workspace: workspace to use
|
||||
:param project: Lumberyard project to set as target
|
||||
:return: None
|
||||
"""
|
||||
bootstrap_cfg = os.path.join(workspace.paths.dev(), "bootstrap.cfg")
|
||||
os.chmod(bootstrap_cfg, stat.S_IWRITE)
|
||||
lines = None
|
||||
with open(bootstrap_cfg) as f:
|
||||
lines = f.readlines()
|
||||
|
||||
found_gamefolder = False
|
||||
for i, line in enumerate(lines):
|
||||
if line.lstrip().startswith("project_path"):
|
||||
lines[i] = f"project_path={project}\n"
|
||||
found_gamefolder = True
|
||||
break
|
||||
|
||||
assert found_gamefolder, "'project_path' not found in bootstrap.cfg"
|
||||
|
||||
with open(bootstrap_cfg, "w") as f:
|
||||
f.writelines(lines)
|
||||
|
||||
|
||||
def setup_builtin_workspace(workspace, test_name, artifact_folder_count):
|
||||
# type: (internal_workspace.AbstractWorkspaceManager, str, int) -> internal_workspace.AbstractWorkspaceManager
|
||||
"""
|
||||
|
||||
@@ -420,3 +420,34 @@ def reduce_file_name_length(file_name, max_length):
|
||||
file_name = file_name[:-reduce_amount]
|
||||
|
||||
return file_name
|
||||
|
||||
|
||||
def find_ancestor_file(target_file_name, start_path=os.getcwd()):
|
||||
"""
|
||||
Find a file with the given name in the ancestor directories by walking up the starting path until the file is found.
|
||||
|
||||
:param target_file_name: Name of the file to find.
|
||||
:param start_path: Optional path to start looking for the file.
|
||||
:return: Path to the file or None if not found.
|
||||
"""
|
||||
current_path = os.path.normpath(start_path)
|
||||
candidate_path = os.path.join(current_path, target_file_name)
|
||||
|
||||
# Limit the number of directories to traverse, to avoid infinite loop in path cycles
|
||||
for _ in range(15):
|
||||
if not os.path.exists(candidate_path):
|
||||
parent_path = os.path.dirname(current_path)
|
||||
if parent_path == current_path:
|
||||
# Only true when we are at the directory root, can't keep searching
|
||||
break
|
||||
candidate_path = os.path.join(parent_path, target_file_name)
|
||||
current_path = parent_path
|
||||
else:
|
||||
# Found the file we wanted
|
||||
break
|
||||
|
||||
if not os.path.exists(candidate_path):
|
||||
logger.warning(f'The candidate path {candidate_path} does not exist.')
|
||||
return None
|
||||
|
||||
return candidate_path
|
||||
|
||||
@@ -122,7 +122,7 @@ class AndroidLauncher(Launcher):
|
||||
self._device_id = None
|
||||
self.launch_proc = None
|
||||
self.android_vfs_setreg_path = None
|
||||
self.package_name = get_package_name(os.path.join(self.workspace.paths.dev(),
|
||||
self.package_name = get_package_name(os.path.join(self.workspace.paths.engine_root(),
|
||||
self.workspace.project))
|
||||
self._device_id = self.get_device_config(config_file=self.workspace.paths.devices_file(),
|
||||
device_section='android',
|
||||
|
||||
@@ -165,7 +165,7 @@ class WinLauncher(Launcher):
|
||||
"""
|
||||
# Update settings via the settings registry to avoid modifying the bootstrap.cfg
|
||||
host_ip = '127.0.0.1'
|
||||
self.args.append(f'--regset="/Amazon/AzCore/Bootstrap/project_path={self.workspace.project}"')
|
||||
self.args.append(f'--regset="/Amazon/AzCore/Bootstrap/project_path={self.workspace.paths.project()}"')
|
||||
self.args.append(f'--regset="/Amazon/AzCore/Bootstrap/remote_ip={host_ip}"')
|
||||
self.args.append('--regset="/Amazon/AzCore/Bootstrap/wait_for_connect=1"')
|
||||
self.args.append(f'--regset="/Amazon/AzCore/Bootstrap/allowed_list={host_ip}"')
|
||||
|
||||
@@ -17,20 +17,14 @@ import logging
|
||||
import subprocess
|
||||
import socket
|
||||
import time
|
||||
import itertools
|
||||
from timeit import default_timer
|
||||
import pytest
|
||||
import platform
|
||||
import random
|
||||
import tempfile
|
||||
import shutil
|
||||
import stat
|
||||
from typing import Dict, List, Tuple, Optional, Callable
|
||||
from typing import List
|
||||
import psutil
|
||||
|
||||
import ly_test_tools
|
||||
import ly_test_tools.environment.waiter as waiter
|
||||
import ly_test_tools.environment.process_utils as process_utils
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import ly_test_tools.lumberyard.pipeline_utils as utils
|
||||
from ly_test_tools.lumberyard.ap_log_parser import APLogParser
|
||||
@@ -49,7 +43,7 @@ ASSET_PROCESSOR_PLATFORM_MAP = {
|
||||
'windows': 'pc',
|
||||
}
|
||||
|
||||
ASSET_PROCESSOR_SETTINGS_ROOT_KEY='/Amazon/AssetProcessor/Settings'
|
||||
ASSET_PROCESSOR_SETTINGS_ROOT_KEY = '/Amazon/AssetProcessor/Settings'
|
||||
|
||||
class AssetProcessorError(Exception):
|
||||
""" Indicates that the AssetProcessor raised an error """
|
||||
@@ -70,7 +64,7 @@ class AssetProcessor(object):
|
||||
self._ap_proc = None
|
||||
self._temp_asset_directory = None
|
||||
self._temp_asset_root = None
|
||||
self._project_path = self._workspace.project
|
||||
self._project_path = self._workspace.paths.project()
|
||||
self._override_scan_folders = []
|
||||
self._test_assets_source_folder = None
|
||||
self._cache_folder = None
|
||||
@@ -136,7 +130,6 @@ class AssetProcessor(object):
|
||||
|
||||
try:
|
||||
self._control_connection.sendall(message.encode())
|
||||
|
||||
logger.info(f"Sent input {message}")
|
||||
return True
|
||||
except IOError as e:
|
||||
@@ -485,8 +478,7 @@ class AssetProcessor(object):
|
||||
logger.warning(f"Cannot capture output when leaving AP connection open.")
|
||||
|
||||
logger.info(f"Launching AP with command: {command}")
|
||||
self._ap_proc = subprocess.Popen(command,
|
||||
cwd=ap_exe_path)
|
||||
self._ap_proc = subprocess.Popen(command, cwd=ap_exe_path)
|
||||
|
||||
if accept_input and not quitonidle:
|
||||
self.connect_control()
|
||||
@@ -668,10 +660,11 @@ class AssetProcessor(object):
|
||||
make_dir = os.path.join(self._temp_asset_root, copy_dir)
|
||||
if not os.path.isdir(make_dir):
|
||||
os.makedirs(make_dir)
|
||||
for copyfile_name in ['bootstrap.cfg', 'AssetProcessorPlatformConfig.setreg',
|
||||
for copyfile_name in ['bootstrap.cfg',
|
||||
'AssetProcessorPlatformConfig.setreg',
|
||||
os.path.join(self._workspace.project, "project.json"),
|
||||
os.path.join('Engine', 'exclude.filetag')]:
|
||||
shutil.copyfile(os.path.join(self._workspace.paths.dev(), copyfile_name),
|
||||
shutil.copyfile(os.path.join(self._workspace.paths.engine_root(), copyfile_name),
|
||||
os.path.join(self._temp_asset_root, copyfile_name))
|
||||
|
||||
def delete_temp_asset_root(self):
|
||||
@@ -756,7 +749,7 @@ class AssetProcessor(object):
|
||||
if not self._temp_asset_root:
|
||||
logger.warning(f"Can't create scan folder, no temporary asset workspace has been created")
|
||||
return
|
||||
scan_folder = os.path.join(self._temp_asset_root if self._temp_asset_root else self._workspace.paths.dev(),
|
||||
scan_folder = os.path.join(self._temp_asset_root if self._temp_asset_root else self._workspace.paths.engine_root(),
|
||||
folder_name)
|
||||
if not os.path.isdir(scan_folder):
|
||||
os.makedirs(scan_folder)
|
||||
@@ -901,7 +894,7 @@ class AssetProcessor(object):
|
||||
asset root if not supplied
|
||||
:return: None
|
||||
"""
|
||||
source_root = source_root or self._workspace.paths.dev()
|
||||
source_root = source_root or self._workspace.paths.engine_root()
|
||||
if not self._temp_asset_root:
|
||||
logger.warning(f"Can't add relative source asset, no temporary asset root created")
|
||||
return
|
||||
@@ -966,7 +959,7 @@ class AssetProcessor(object):
|
||||
supplied
|
||||
:return: path to project cache
|
||||
"""
|
||||
source_folder = os.path.join(self._workspace.paths.dev(), relative_source)
|
||||
source_folder = os.path.join(self._workspace.paths.engine_root(), relative_source)
|
||||
dest_relative = relative_dest or relative_source
|
||||
dest_folder = os.path.join(self._temp_asset_root, dest_relative)
|
||||
shutil.copytree(source_folder, dest_folder)
|
||||
|
||||
@@ -13,38 +13,14 @@ AssetProcessorPlatformConfig.setreg
|
||||
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import os.path as path
|
||||
from ly_test_tools.lumberyard.settings import RegistrySettings
|
||||
from ly_test_tools.lumberyard.asset_processor import ASSET_PROCESSOR_SETTINGS_ROOT_KEY
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
AssetProcessorConfig = "AssetProcessorPlatformConfig.setreg"
|
||||
|
||||
def load_asset_processor_platform_config(file_location):
|
||||
"""
|
||||
Loads the AssetProcessorPlatformConfig.setreg file removing any comments
|
||||
|
||||
:param file_location: The file path of AssetProcessorPlatformConfig.setreg
|
||||
"""
|
||||
json_dict = {}
|
||||
with open(file_location, 'r') as json_file:
|
||||
cleaned_lines = []
|
||||
for line in json_file.readlines():
|
||||
lineIndex = line.lstrip().startswith('//')
|
||||
cleaned_lines.append(line if lineIndex == -1 else line[:lineIndex])
|
||||
json_dict = json.loads(''.join(cleaned_lines))
|
||||
return json_dict
|
||||
|
||||
def save_asset_processor_platform_config(file_location, json_dict):
|
||||
"""
|
||||
Saves the json_dict to the AssetProcessorPlatformConfig.setreg file
|
||||
|
||||
:param file_location: The file path of AssetProcessorPlatformConfig.setreg
|
||||
"""
|
||||
with open(file_location, 'w') as json_file:
|
||||
json.dump(json_dict, json_file, indent=4)
|
||||
return json_dict
|
||||
|
||||
def platform_exists(config_setreg_path, platform):
|
||||
"""
|
||||
Checks to see if a specific Platform Key is in Platforms Section
|
||||
@@ -53,19 +29,15 @@ def platform_exists(config_setreg_path, platform):
|
||||
:param platform: Name of the Platform Key that you're checking exists
|
||||
:return: The boolean value of the existance of the platform
|
||||
"""
|
||||
|
||||
logger.debug("Checking for Platform '{0}' in Platforms Section of '{1}"
|
||||
.format(platform, AssetProcessorConfig))
|
||||
|
||||
file_location = path.join(config_setreg_path, AssetProcessorConfig)
|
||||
json_dict = load_asset_processor_platform_config(file_location)
|
||||
try:
|
||||
platformExist = platform in json_dict['Amazon']['AssetProcessor']['Settings']['Platforms']
|
||||
return platformExist
|
||||
except KeyError as err:
|
||||
logger.error(f'KeyError when attempting to query platform existance of {platform} in file {file_location}: {err}')
|
||||
|
||||
return False
|
||||
with RegistrySettings(file_location) as settings:
|
||||
platformExist = settings.get_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/Platforms/{platform}', False)
|
||||
|
||||
return platformExist
|
||||
|
||||
|
||||
def is_platform_enabled(config_setreg_path, platform):
|
||||
@@ -77,20 +49,15 @@ def is_platform_enabled(config_setreg_path, platform):
|
||||
See asset_processor.SUPPORTED_PLATFORMS for listed of supported platforms
|
||||
:return: The boolean value of the enabled state of the platform
|
||||
"""
|
||||
|
||||
logger.debug("Checking if Platform '{0}' is enabled in Platform Section of '{1}"
|
||||
.format(platform, AssetProcessorConfig))
|
||||
|
||||
file_location = path.join(config_setreg_path, AssetProcessorConfig)
|
||||
# load AssetProcessorPlatformConfig.setreg removing any comments
|
||||
json_dict = load_asset_processor_platform_config(file_location)
|
||||
try:
|
||||
enabled = json_dict['Amazon']['AssetProcessor']['Settings']['Platforms'][platform] == 'enabled'
|
||||
return enabled
|
||||
except KeyError as err:
|
||||
logger.error(f'KeyError when attempting to check if platform {platform} is enabled in file {file_location}: {err}')
|
||||
|
||||
return False
|
||||
with RegistrySettings(file_location) as settings:
|
||||
enabled = settings.get_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/Platforms/{platform}', None) == 'enabled'
|
||||
|
||||
return enabled
|
||||
|
||||
|
||||
def enable_platform(config_setreg_path, platform):
|
||||
@@ -103,15 +70,11 @@ def enable_platform(config_setreg_path, platform):
|
||||
:assert: Assert if the platform is not enabled
|
||||
:return: None
|
||||
"""
|
||||
|
||||
logger.debug("Enabling platform '{0}' in '{1}'".format(platform, AssetProcessorConfig))
|
||||
|
||||
file_location = path.join(config_setreg_path, AssetProcessorConfig)
|
||||
json_dict = load_asset_processor_platform_config(file_location)
|
||||
# Enable platform in settings registry
|
||||
json_dict.setdefault('Amazon', {}).setdefault('AssetProcessor', {}).setdefault('Settings',{}) \
|
||||
.setdefault('Platforms',{})[platform] = 'enabled'
|
||||
save_asset_processor_platform_config(file_location)
|
||||
with RegistrySettings(file_location) as settings:
|
||||
settings.set_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/Platforms/{platform}', 'enabled')
|
||||
|
||||
|
||||
def enable_all_platforms(config_setreg_path):
|
||||
@@ -121,7 +84,6 @@ def enable_all_platforms(config_setreg_path):
|
||||
:param config_setreg_path: The file path to the location of AssetProcessorPlatformConfig.setreg
|
||||
:return: None
|
||||
"""
|
||||
|
||||
logger.debug("Enabling all supported platforms in '{0}'.".format(AssetProcessorConfig))
|
||||
|
||||
for platform in SUPPORTED_PLATFORMS:
|
||||
@@ -140,15 +102,13 @@ def disable_platform(config_setreg_path, platform):
|
||||
:assert: Assert if the platform is not disabled
|
||||
:return: None
|
||||
"""
|
||||
|
||||
logger.debug("Disabling platform '{0}' in '{1}'".format(platform, AssetProcessorConfig))
|
||||
|
||||
file_location = path.join(config_setreg_path, AssetProcessorConfig)
|
||||
# Disable platform in settings registry
|
||||
json_dict = load_asset_processor_platform_config(file_location)
|
||||
json_dict.setdefault('Amazon', {}).setdefault('AssetProcessor', {}).setdefault('Settings',{}) \
|
||||
.setdefault('Platforms',{})[platform] = 'disabled'
|
||||
save_asset_processor_platform_config(file_location)
|
||||
file_location = path.join(config_setreg_path, AssetProcessorConfig)
|
||||
with RegistrySettings(file_location) as settings:
|
||||
settings.set_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/Platforms/{platform}', 'disabled')
|
||||
|
||||
|
||||
def disable_all_platforms(config_setreg_path):
|
||||
@@ -158,7 +118,6 @@ def disable_all_platforms(config_setreg_path):
|
||||
:param config_setreg_path: The file path to the location of AssetProcessorPlatformConfig.setreg
|
||||
:return: None
|
||||
"""
|
||||
|
||||
logger.debug("Disabling all platforms in '{0}'".format(AssetProcessorConfig))
|
||||
|
||||
for platform in SUPPORTED_PLATFORMS:
|
||||
@@ -174,18 +133,15 @@ def enable_scanfolder_engine(config_setreg_path):
|
||||
:param config_setreg_path: The file path to the location of AssetProcessorPlatformConfig.setreg
|
||||
:return: None
|
||||
"""
|
||||
|
||||
file_location = path.join(config_setreg_path, AssetProcessorConfig)
|
||||
section = 'ScanFolder Engine'
|
||||
|
||||
logger.debug("Enabling Asset Processor scanning of the Engine folder")
|
||||
|
||||
json_dict = load_asset_processor_platform_config(file_location)
|
||||
json_dict.setdefault('Amazon', {}).setdefault('AssetProcessor', {}).setdefault('Settings',{}) \
|
||||
.setdefault(section,{})['watch'] = '@ENGINEROOT@/Engine'
|
||||
json_dict['Amazon']['AssetProcessor']['Settings'][section]['recursive'] = '1'
|
||||
json_dict['Amazon']['AssetProcessor']['Settings'][section]['order'] = '20000'
|
||||
save_asset_processor_platform_config(file_location)
|
||||
with RegistrySettings(file_location) as settings:
|
||||
settings.set_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{section}/watch', '@ENGINEROOT@/Engine')
|
||||
settings.set_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{section}/recursive', '1')
|
||||
settings.set_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{section}/order', '20000')
|
||||
|
||||
|
||||
def disable_scanfolder_engine(config_setreg_path):
|
||||
@@ -195,18 +151,12 @@ def disable_scanfolder_engine(config_setreg_path):
|
||||
:param config_setreg_path: The file path to the location of AssetProcessorPlatformConfig.setreg
|
||||
:return: None
|
||||
"""
|
||||
|
||||
file_location = path.join(config_setreg_path, AssetProcessorConfig)
|
||||
section = 'ScanFolder Engine'
|
||||
|
||||
logger.debug("Disabling Asset Processor scanning of the Engine folder")
|
||||
|
||||
json_dict = load_asset_processor_platform_config(file_location)
|
||||
try:
|
||||
del json_dict['Amazon']['AssetProcessor']['Settings'][section]
|
||||
save_asset_processor_platform_config(file_location)
|
||||
except KeyError as err:
|
||||
logger.debug(f'No-op: f{section} key does not exist in file {file_location}')
|
||||
with RegistrySettings(file_location) as settings:
|
||||
settings.remove_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{section}')
|
||||
|
||||
|
||||
def enable_scanfolder_editor(config_setreg_path):
|
||||
@@ -216,21 +166,17 @@ def enable_scanfolder_editor(config_setreg_path):
|
||||
:param config_setreg_path: The file path to the location of AssetProcessorPlatformConfig.setreg
|
||||
:return: None
|
||||
"""
|
||||
|
||||
file_location = path.join(config_setreg_path, AssetProcessorConfig)
|
||||
section = 'ScanFolder Editor'
|
||||
|
||||
|
||||
logger.debug("Enabling Asset Processor scanning of the Editor folder")
|
||||
|
||||
json_dict = load_asset_processor_platform_config(file_location)
|
||||
json_dict.setdefault('Amazon', {}).setdefault('AssetProcessor', {}).setdefault('Settings',{}) \
|
||||
.setdefault(section,{})['watch'] = '@ENGINEROOT@/Editor'
|
||||
json_dict['Amazon']['AssetProcessor']['Settings'][section]['output'] = 'editor'
|
||||
json_dict['Amazon']['AssetProcessor']['Settings'][section]['recursive'] = '1'
|
||||
json_dict['Amazon']['AssetProcessor']['Settings'][section]['order'] = '30000'
|
||||
json_dict['Amazon']['AssetProcessor']['Settings'][section]['include'] = 'tools,renderer'
|
||||
save_asset_processor_platform_config(file_location)
|
||||
with RegistrySettings(file_location) as settings:
|
||||
settings.set_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{section}/watch', '@ENGINEROOT@/Editor')
|
||||
settings.set_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{section}/output', 'editor')
|
||||
settings.set_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{section}/recursive', '1')
|
||||
settings.set_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{section}/order', '30000')
|
||||
settings.set_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{section}/include', 'tools,renderer')
|
||||
|
||||
|
||||
def disable_scanfolder_editor(config_setreg_path):
|
||||
@@ -240,17 +186,13 @@ def disable_scanfolder_editor(config_setreg_path):
|
||||
:param config_setreg_path: The file path to the location of AssetProcessorPlatformConfig.setreg
|
||||
:return: None
|
||||
"""
|
||||
|
||||
file_location = path.join(config_setreg_path, AssetProcessorConfig)
|
||||
section = 'ScanFolder Editor'
|
||||
|
||||
logger.debug("Disabling Asset Processor scanning of the Editor folder")
|
||||
|
||||
try:
|
||||
del json_dict['Amazon']['AssetProcessor']['Settings'][section]
|
||||
save_asset_processor_platform_config(file_location)
|
||||
except KeyError as err:
|
||||
logger.debug(f'No-op: f{section} key does not exist in file {file_location}')
|
||||
with RegistrySettings(file_location) as settings:
|
||||
settings.remove_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{section}')
|
||||
|
||||
|
||||
def enable_scanfolder_root(config_setreg_path):
|
||||
@@ -260,18 +202,15 @@ def enable_scanfolder_root(config_setreg_path):
|
||||
:param config_setreg_path: The file path to the location of AssetProcessorPlatformConfig.setreg
|
||||
:return: None
|
||||
"""
|
||||
|
||||
file_location = path.join(config_setreg_path, AssetProcessorConfig)
|
||||
section = 'ScanFolder Root'
|
||||
|
||||
logger.debug("Enabling Asset Processor scanning of the Root folder")
|
||||
|
||||
json_dict = load_asset_processor_platform_config(file_location)
|
||||
json_dict.setdefault('Amazon', {}).setdefault('AssetProcessor', {}).setdefault('Settings',{}) \
|
||||
.setdefault(section,{})['watch'] = '@ROOT@'
|
||||
json_dict['Amazon']['AssetProcessor']['Settings'][section]['recursive'] = '0'
|
||||
json_dict['Amazon']['AssetProcessor']['Settings'][section]['order'] = '10000'
|
||||
save_asset_processor_platform_config(file_location)
|
||||
with RegistrySettings(file_location) as settings:
|
||||
settings.set_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{section}/watch', '@ROOT@')
|
||||
settings.set_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{section}/recursive', '0')
|
||||
settings.set_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{section}/order', '10000')
|
||||
|
||||
|
||||
def disable_scanfolder_root(config_setreg_path):
|
||||
@@ -281,17 +220,13 @@ def disable_scanfolder_root(config_setreg_path):
|
||||
:param config_setreg_path: The file path to the location of AssetProcessorPlatformConfig.setreg
|
||||
:return: None
|
||||
"""
|
||||
|
||||
file_location = path.join(config_setreg_path, AssetProcessorConfig)
|
||||
section = 'ScanFolder Root'
|
||||
|
||||
logger.debug("Disabling Asset Processor scanning of the Root folder")
|
||||
|
||||
try:
|
||||
del json_dict['Amazon']['AssetProcessor']['Settings'][section]
|
||||
save_asset_processor_platform_config(file_location)
|
||||
except KeyError as err:
|
||||
logger.debug(f'No-op: f{section} key does not exist in file {file_location}')
|
||||
with RegistrySettings(file_location) as settings:
|
||||
settings.remove_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{section}')
|
||||
|
||||
|
||||
def update_pattern(config_setreg_path, pattern, key, value):
|
||||
@@ -304,15 +239,12 @@ def update_pattern(config_setreg_path, pattern, key, value):
|
||||
:param value: The value to set the key to
|
||||
:return: None
|
||||
"""
|
||||
|
||||
file_location = path.join(config_setreg_path, AssetProcessorConfig)
|
||||
rc_pattern = 'RC ' + pattern
|
||||
|
||||
logger.debug("Modifying pattern for '{0}'.".format(rc_pattern))
|
||||
json_dict = load_asset_processor_platform_config(file_location)
|
||||
json_dict.setdefault('Amazon', {}).setdefault('AssetProcessor', {}).setdefault('Settings',{}) \
|
||||
.setdefault(rc_pattern,{})[key] = value
|
||||
save_asset_processor_platform_config(file_location)
|
||||
with RegistrySettings(file_location) as settings:
|
||||
settings.set_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{rc_pattern}/{key}', value)
|
||||
|
||||
|
||||
def get_pattern_key(config_setreg_path, pattern, key):
|
||||
@@ -328,11 +260,7 @@ def get_pattern_key(config_setreg_path, pattern, key):
|
||||
file_location = path.join(config_setreg_path, AssetProcessorConfig)
|
||||
rc_pattern = 'RC ' + pattern
|
||||
logger.debug("Retrieving the key '{0}' from pattern '{1}'.".format(key, rc_pattern))
|
||||
json_dict = load_asset_processor_platform_config(file_location)
|
||||
try:
|
||||
value = json_dict['Amazon']['AssetProcessor']['Settings'][rc_pattern][key]
|
||||
return value
|
||||
except KeyError as err:
|
||||
logger.error(f'KeyError attempting to query value for key "/Amazon/AssetProcessor/Settings/{rc_pattern}/{key}" in file {file_location}: {err}')
|
||||
with RegistrySettings(file_location) as settings:
|
||||
value = settings.get_key(f'{ASSET_PROCESSOR_SETTINGS_ROOT_KEY}/{rc_pattern}/{key}', None)
|
||||
|
||||
return None
|
||||
return value
|
||||
|
||||
@@ -215,43 +215,6 @@ def backup_asset_processor_logs(bin_directory: str, backup_directory: str) -> No
|
||||
shutil.copytree(ap_logs, destination)
|
||||
|
||||
|
||||
def platform_enabled(workspace: pytest.fixture, platform: str) -> bool:
|
||||
"""
|
||||
Checks to see if the platform specified is enabled for the current build of LY.
|
||||
|
||||
:param workspace: The current testing workspace
|
||||
:param platform: The name of the platform to lookup.
|
||||
:return: True if the platform is enabled, False if not.
|
||||
"""
|
||||
user_settings_file = os.path.join(workspace.paths.dev(), "_WAF_", "user_settings.options")
|
||||
assert os.path.exists(user_settings_file), f"User settings file not found at {user_settings_file}"
|
||||
|
||||
parser = ConfigParser()
|
||||
parser.read(user_settings_file)
|
||||
section = platform.title() + " Options" # The Platform Options section
|
||||
option = "enable_" + platform.lower()
|
||||
|
||||
# Make sure the platform has an options section
|
||||
assert parser.has_section(section), f"Section {section} was not found in {user_settings_file}"
|
||||
if parser.has_option(section, option):
|
||||
entry = parser.get(section, option)
|
||||
if entry.lower() == "true":
|
||||
# Found 'true'
|
||||
return True
|
||||
elif entry.lower() == "false":
|
||||
# Found 'false'
|
||||
return False
|
||||
else:
|
||||
# Found something unexpected
|
||||
# fmt:off
|
||||
logger.warning(f"Found unexpected value '{entry}' in {user_settings_file} - {section}:{option}. "
|
||||
f"Using default value of 'False'")
|
||||
# fmt:on
|
||||
else:
|
||||
logger.info(f"No option '{option}' was found in the section '{section}', defaulting to 'False'")
|
||||
return False
|
||||
|
||||
|
||||
def safe_subprocess(command: str or List[str], **kwargs: Dict) -> ProcessOutput:
|
||||
"""
|
||||
Forwards arguments to subprocess.Popen to have a processes output
|
||||
|
||||
@@ -12,6 +12,7 @@ LySettings provides an API for modifying settings files and creating/restoring b
|
||||
"""
|
||||
|
||||
import fileinput
|
||||
import json
|
||||
import logging
|
||||
import re
|
||||
import os
|
||||
@@ -89,6 +90,24 @@ class LySettings(object):
|
||||
def restore_shader_compiler_settings(self, backup_path=None):
|
||||
self._restore_settings(self._resource_locator.shader_compiler_config_file(), backup_path)
|
||||
|
||||
def backup_json_settings(self, json_settings_file, backup_path=None):
|
||||
"""
|
||||
Creates a backup of a Json/Registry Settings file in the backup_path. If no path is provided, it will store in
|
||||
the workspace temp path (the contents of the workspace temp directory are removed during workspace teardown)
|
||||
:param json_settings_file:
|
||||
:param backup_path:
|
||||
:return:
|
||||
"""
|
||||
self._backup_settings(json_settings_file, backup_path)
|
||||
|
||||
def restore_json_settings(self, json_settings_file, backup_path=None):
|
||||
"""
|
||||
Restores a Json/Registry settings file from its backup.
|
||||
The backup is stored in the backup_path.
|
||||
If no backup_path is provided, it will attempt to retrieve the backup from the workspace temp path.
|
||||
"""
|
||||
self._restore_settings(json_settings_file, backup_path)
|
||||
|
||||
def _backup_settings(self, settings_file, backup_path):
|
||||
"""
|
||||
Creates a backup of the settings file in the backup_path. If no path is
|
||||
@@ -109,6 +128,136 @@ class LySettings(object):
|
||||
ly_test_tools.environment.file_system.restore_backup(settings_file, backup_path)
|
||||
|
||||
|
||||
class JsonSettings(object):
|
||||
"""
|
||||
JsonSettings provides an API for reading, modifying and writing Json settings files.
|
||||
Can be used as a Context Manager.
|
||||
"""
|
||||
|
||||
def __init__(self, file_path, line_clean_func=None):
|
||||
self._data = None
|
||||
self._file_path = file_path
|
||||
self._line_clean_func = line_clean_func
|
||||
self._modified = False
|
||||
self._path_separator = '/'
|
||||
|
||||
def __enter__(self):
|
||||
self.load()
|
||||
return self
|
||||
|
||||
def __exit__(self, exception_type, exception_value, traceback):
|
||||
if self._modified:
|
||||
self.dump()
|
||||
|
||||
def _get_path_tokens(self, key_path):
|
||||
"""
|
||||
Splits the path using the separator and returns a list of tokens.
|
||||
The first empty token is skipped, since it points to the root of the document.
|
||||
:param key_path: Path to the key
|
||||
:return: List of path tokens
|
||||
"""
|
||||
path_tokens = key_path.split(self._path_separator)
|
||||
# Skip first empty token, it points to the root of the document
|
||||
path_tokens = path_tokens[1:]
|
||||
return path_tokens
|
||||
|
||||
def load(self):
|
||||
"""
|
||||
Load the Json file into memory
|
||||
:return: None
|
||||
"""
|
||||
with open(self._file_path, 'r') as contents:
|
||||
if not self._line_clean_func:
|
||||
self._data = json.load(contents)
|
||||
else:
|
||||
cleaned_lines = []
|
||||
for line in contents:
|
||||
clean_line = self._line_clean_func(line)
|
||||
cleaned_lines.append(clean_line)
|
||||
|
||||
self._data = json.loads(cleaned_lines)
|
||||
|
||||
def dump(self):
|
||||
"""
|
||||
Write the content into the Json file
|
||||
:return: None
|
||||
"""
|
||||
with open(self._file_path, 'w') as out_file:
|
||||
json.dump(self._data, out_file, indent=4)
|
||||
|
||||
def get_key(self, key_path, default_value=None):
|
||||
"""
|
||||
Retrieve a key by path from the Json
|
||||
:param key_path: Path to the key
|
||||
:param default_value: Default value to return if the key is not found
|
||||
:return: Value of the key or default_value if not found
|
||||
"""
|
||||
path_tokens = self._get_path_tokens(key_path)
|
||||
obj = self._data
|
||||
try:
|
||||
for token in path_tokens:
|
||||
obj = obj[token]
|
||||
return obj
|
||||
except KeyError as err:
|
||||
logger.error(f'KeyError when retrieving {key_path} from file {self._file_path}: {err}')
|
||||
return default_value
|
||||
|
||||
def set_key(self, key_path, value):
|
||||
"""
|
||||
Set a key to a value
|
||||
:param key_path: Path to the key
|
||||
:param value: The value
|
||||
:return: None
|
||||
"""
|
||||
path_tokens = self._get_path_tokens(key_path)
|
||||
obj = self._data
|
||||
try:
|
||||
for token in path_tokens[0:-1]:
|
||||
obj = obj.setdefault(token, {})
|
||||
obj[path_tokens[-1]] = value
|
||||
self._modified = True
|
||||
except KeyError as err:
|
||||
logger.error(f'KeyError when setting {key_path} from file {self._file_path}: {err}')
|
||||
|
||||
def remove_key(self, key_path):
|
||||
"""
|
||||
Remove a key by path from the Json
|
||||
:param key_path: Path to the key
|
||||
:return: None
|
||||
"""
|
||||
path_tokens = self._get_path_tokens(key_path)
|
||||
obj = self._data
|
||||
parent = None
|
||||
key = None
|
||||
try:
|
||||
for token in path_tokens:
|
||||
key = token
|
||||
parent = obj
|
||||
obj = obj[token]
|
||||
|
||||
if parent:
|
||||
del parent[key]
|
||||
self._modified = True
|
||||
else:
|
||||
logger.warning(f'Could not remove key {key} from file {self._file_path}')
|
||||
except KeyError as err:
|
||||
logger.error(f'KeyError when removing {key_path} from file {self._file_path}: {err}')
|
||||
|
||||
|
||||
class RegistrySettings(JsonSettings):
|
||||
"""
|
||||
JsonSettings provides an API for reading, modifying and writing Registry settings files.
|
||||
Files must be Json-compatible with optional line comments starting with '//'.
|
||||
"""
|
||||
def __init__(self, file_path):
|
||||
super(RegistrySettings, self).__init__(file_path, RegistrySettings._clean_line)
|
||||
|
||||
@staticmethod
|
||||
def _clean_line(line):
|
||||
comment_index = line.lstrip.startswith('//')
|
||||
return line if comment_index == -1 else line[:comment_index]
|
||||
|
||||
|
||||
def _edit_text_settings_file(settings_file, setting, value, comment_char=""):
|
||||
"""
|
||||
Find and set a specific setting in a text based settings file. Uses "setting = value" syntax to identify setting,
|
||||
|
||||
Reference in New Issue
Block a user