Refactored ProjectManagerSettings, added tests, changed project built successful to be tracked by project path, added project ids, changed project settings path to use project id and name

Signed-off-by: nggieber <52797929+AMZN-nggieber@users.noreply.github.com>
This commit is contained in:
nggieber
2021-12-06 09:22:03 -08:00
parent 6150a60e57
commit 15237af23c
28 changed files with 622 additions and 132 deletions
+17 -5
View File
@@ -1113,7 +1113,7 @@ def create_from_template(destination_path: pathlib.Path,
try:
template_json_data = json.load(s)
except KeyError as e:
logger.error(f'Could read template json {template_json}: {str(e)}.')
logger.error(f'Could not read template json {template_json}: {str(e)}.')
return 1
# read template name from the json
@@ -1338,7 +1338,8 @@ def create_project(project_path: pathlib.Path,
no_register: bool = False,
system_component_class_id: str = None,
editor_system_component_class_id: str = None,
module_id: str = None) -> int:
module_id: str = None,
project_id: str = None) -> int:
"""
Template instantiation specialization that makes all default assumptions for a Project template instantiation,
reducing the effort needed in instancing a project
@@ -1366,6 +1367,7 @@ def create_project(project_path: pathlib.Path,
:param editor_system_component_class_id: optionally specify a uuid for the editor system component class, default is
random uuid
:param module_id: optionally specify a uuid for the module class, default is random uuid
:param project_id: optionally specify a str for the project id, default is random uuid
:return: 0 for success or non 0 failure code
"""
if template_name and template_path:
@@ -1405,7 +1407,7 @@ def create_project(project_path: pathlib.Path,
try:
template_json_data = json.load(s)
except json.JSONDecodeError as e:
logger.error(f'Could read template json {template_json}: {str(e)}.')
logger.error(f'Could not read template json {template_json}: {str(e)}.')
return 1
# read template name from the json
@@ -1577,6 +1579,12 @@ def create_project(project_path: pathlib.Path,
replacements.append(("${NameLower}", project_name.lower()))
replacements.append(("${SanitizedCppName}", sanitized_cpp_name))
# was a project id specified
if project_id:
replacements.append(("${ProjectId}", project_id))
else:
replacements.append(("${ProjectId}", '{' + str(uuid.uuid4()) + '}'))
# module id is a uuid with { and -
if module_id:
replacements.append(("${ModuleClassId}", module_id))
@@ -1784,7 +1792,7 @@ def create_gem(gem_path: pathlib.Path,
try:
template_json_data = json.load(s)
except json.JSONDecodeError as e:
logger.error(f'Could read template json {template_json}: {str(e)}.')
logger.error(f'Could not read template json {template_json}: {str(e)}.')
return 1
# read template name from the json
@@ -2123,7 +2131,8 @@ def _run_create_project(args: argparse) -> int:
args.no_register,
args.system_component_class_id,
args.editor_system_component_class_id,
args.module_id)
args.module_id,
args.project_id)
def _run_create_gem(args: argparse) -> int:
@@ -2404,6 +2413,9 @@ def add_args(subparsers) -> None:
create_project_subparser.add_argument('--module-id', type=uuid.UUID, required=False,
help='The uuid you want to associate with the module, default is a random'
' uuid Ex. {b60c92eb-3139-454b-a917-a9d3c5819594}')
create_project_subparser.add_argument('--project-id', type=str, required=False,
help='The str id you want to associate with the project, default is a random uuid'
' Ex. {b60c92eb-3139-454b-a917-a9d3c5819594}')
create_project_subparser.add_argument('-f', '--force', action='store_true', default=False,
help='Copies over instantiated template directory even if it exist.')
create_project_subparser.add_argument('--no-register', action='store_true', default=False,
+9 -4
View File
@@ -29,6 +29,7 @@ def get_project_props(name: str = None, path: pathlib.Path = None) -> dict:
def edit_project_props(proj_path: pathlib.Path = None,
proj_name: str = None,
new_name: str = None,
new_id: str = None,
new_origin: str = None,
new_display: str = None,
new_summary: str = None,
@@ -40,14 +41,15 @@ def edit_project_props(proj_path: pathlib.Path = None,
if not proj_json:
return 1
if new_origin:
proj_json['origin'] = new_origin
if new_name:
if not utils.validate_identifier(new_name):
logger.error(f'Project name must be fewer than 64 characters, contain only alphanumeric, "_" or "-" characters, and start with a letter. {new_name}')
return 1
proj_json['project_name'] = new_name
proj_json['project_name'] = new_name
if new_id:
proj_json['project_id'] = new_id
if new_origin:
proj_json['origin'] = new_origin
if new_display:
proj_json['display_name'] = new_display
if new_summary:
@@ -78,6 +80,7 @@ def _edit_project_props(args: argparse) -> int:
return edit_project_props(args.project_path,
args.project_name,
args.project_new_name,
args.project_id,
args.project_origin,
args.project_display,
args.project_summary,
@@ -95,6 +98,8 @@ def add_parser_args(parser):
group = parser.add_argument_group('properties', 'arguments for modifying individual project properties.')
group.add_argument('-pnn', '--project-new-name', type=str, required=False,
help='Sets the name for the project.')
group.add_argument('-pid', '--project-id', type=str, required=False,
help='Sets the ID for the project.')
group.add_argument('-po', '--project-origin', type=str, required=False,
help='Sets description or url for project origin (such as project host, repository, owner...etc).')
group.add_argument('-pd', '--project-display', type=str, required=False,
+1 -1
View File
@@ -570,7 +570,7 @@ def remove_invalid_o3de_projects(manifest_path: pathlib.Path = None) -> int:
result = 0
for project in json_data.get('projects', []):
if not validation.valid_o3de_project_json(pathlib.Path(project).resolve() / 'project.json'):
if not validation.valid_o3de_project_json(pathlib.Path(project).resolve() / 'project.json', generate_uuid=True):
logger.warning(f"Project path {project} is invalid.")
# Attempt to unregister all invalid projects even if previous projects failed to unregister
# but combine the result codes of each command.
+16 -1
View File
@@ -10,6 +10,7 @@ This file validating o3de object json files
"""
import json
import pathlib
import uuid
def valid_o3de_json_dict(json_data: dict, key: str) -> bool:
return key in json_data
@@ -44,7 +45,7 @@ def valid_o3de_engine_json(file_name: str or pathlib.Path) -> bool:
return True
def valid_o3de_project_json(file_name: str or pathlib.Path) -> bool:
def valid_o3de_project_json(file_name: str or pathlib.Path, generate_uuid: bool = True) -> bool:
file_name = pathlib.Path(file_name).resolve()
if not file_name.is_file():
return False
@@ -53,8 +54,22 @@ def valid_o3de_project_json(file_name: str or pathlib.Path) -> bool:
try:
json_data = json.load(f)
test = json_data['project_name']
if not generate_uuid:
test = json_data['project_id']
else:
test = json_data.get('project_id', 'No ID')
generate_new_id = test == 'No ID'
except (json.JSONDecodeError, KeyError) as e:
return False
# Generate a random uuid for the project json if it is missing instead of failing if generate_uuid is true
if generate_uuid and generate_new_id:
with file_name.open('w') as f:
new_uuid = '{' + str(uuid.uuid4()) + '}'
json_data.update({'project_id': new_uuid})
f.write(json.dumps(json_data, indent=4) + '\n')
return True
@@ -16,6 +16,7 @@ from o3de import project_properties
TEST_PROJECT_JSON_PAYLOAD = '''
{
"project_name": "TestProject",
"project_id": "{24114e69-306d-4de6-b3b4-4cb1a3eca58e}"
"origin": "The primary repo for TestProject goes here: i.e. http://www.mydomain.com",
"license": "What license TestProject uses goes here: i.e. https://opensource.org/licenses/MIT",
"display_name": "TestProject",
@@ -45,20 +46,20 @@ def init_project_json_data(request):
@pytest.mark.usefixtures('init_project_json_data')
class TestEditProjectProperties:
@pytest.mark.parametrize("project_path, project_name, project_new_name, project_origin, project_display,\
project_summary, project_icon, add_tags, delete_tags,\
replace_tags, expected_result", [
@pytest.mark.parametrize("project_path, project_name, project_new_name, project_id, project_origin,\
project_display, project_summary, project_icon,\
add_tags, delete_tags, replace_tags, expected_result", [
pytest.param(pathlib.PurePath('E:/TestProject'),
'test', 'test', 'editing by pytest', 'Unit Test', 'pyTest project', 'pytest.bmp', 'A B C',
'test', 'test', 'editing by pytest', 'ID', 'Unit Test', 'pyTest project', 'pytest.bmp', 'A B C',
'B', 'D E F', 0),
pytest.param('',
'test', 'test', 'editing by pytest', 'Unit Test', 'pyTest project', 'pytest.bmp', 'A B C',
'test', 'test', 'editing by pytest', 'ID', 'Unit Test', 'pyTest project', 'pytest.bmp', 'A B C',
'B', 'D E F', 1)
]
)
def test_edit_project_properties(self, project_path, project_name, project_new_name, project_origin, project_display,
project_summary, project_icon, add_tags, delete_tags,
replace_tags, expected_result):
def test_edit_project_properties(self, project_path, project_name, project_new_name, project_origin, project_id,
project_display,project_summary, project_icon, add_tags,
delete_tags, replace_tags, expected_result):
def get_project_json_data(project_name: str, project_path) -> dict:
if not project_path:
@@ -72,12 +73,14 @@ class TestEditProjectProperties:
with patch('o3de.manifest.get_project_json_data', side_effect=get_project_json_data) as get_project_json_data_patch, \
patch('o3de.manifest.save_o3de_manifest', side_effect=save_o3de_manifest) as save_o3de_manifest_patch:
result = project_properties.edit_project_props(project_path, project_name, project_new_name, project_origin,
project_display, project_summary, project_icon,
add_tags, delete_tags, replace_tags)
result = project_properties.edit_project_props(project_path, project_name, project_new_name, project_id,
project_origin, project_display, project_summary, project_icon,
add_tags, delete_tags, replace_tags)
assert result == expected_result
if project_path:
assert self.project_json.data
assert self.project_json.data.get('project_name', '') == project_new_name
assert self.project_json.data.get('project_id', '') == project_id
assert self.project_json.data.get('origin', '') == project_origin
assert self.project_json.data.get('display_name', '') == project_display
assert self.project_json.data.get('summary', '') == project_summary