From 4c2933b38d36dca8e2e0a2d412114a1bd1ab0d92 Mon Sep 17 00:00:00 2001 From: mgwynn Date: Mon, 17 May 2021 18:44:32 -0400 Subject: [PATCH 1/6] Adding gems metadata query --- cmake/Tools/registration.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/cmake/Tools/registration.py b/cmake/Tools/registration.py index 184d2cdb31..70fbc5ba90 100755 --- a/cmake/Tools/registration.py +++ b/cmake/Tools/registration.py @@ -2216,6 +2216,19 @@ def get_gem_data(gem_name: str = None, return None +def get_gems_metadata(): + gem_list = get_gems() + get_engine_gems() + gem_data_dict = {} + for gem in gem_list: + json_path = os.path.join(gem, 'gem.json') + if (os.path.exists(json_path)): + with open(json_path, 'r') as gem_json: + parsed_meta_data = json.loads(gem_json.read()) + gem_data_dict[str(parsed_meta_data['gem_name'])] = parsed_meta_data + else: + logger.error(f'Gem json {gem_json} is not present.') + json_result = json.dumps(gem_data_dict, indent = 4) + return json_result def get_template_data(template_name: str = None, template_path: str or pathlib.Path = None, ) -> dict or None: @@ -2410,6 +2423,12 @@ def print_downloadables(verbose: int) -> None: print_templates_data(downloadable_data['templates']) print_restricted_data(downloadable_data['templates']) +def print_gems_metadata(verbose: int) -> None: + gems_data = get_gems_metadata() + print(gems_data) + if verbose > 0: + gem_list = get_gems() + get_engine_gems() + print(gem_list) def download_engine(engine_name: str, dest_path: str) -> int: @@ -3833,7 +3852,6 @@ def _run_register_show(args: argparse) -> int: if args.this_engine: print_this_engine(args.verbose) return 0 - elif args.engines: print_engines(args.verbose) return 0 @@ -3897,6 +3915,9 @@ def _run_register_show(args: argparse) -> int: elif args.downloadable_templates: print_downloadable_templates(args.verbose) return 0 + elif args.gems_data: + print_gems_metadata(args.verbose) + return 0 else: register_show(args.verbose) return 0 @@ -4168,6 +4189,9 @@ def add_args(parser, subparsers) -> None: group.add_argument('-dt', '--downloadable-templates', action='store_true', required=False, default=False, help='Combine all repos templates into a single list of resources.') + group.add_argument('-gd', '--gems-data', action='store_true', required=False, + default=False, + help='Returns a json formatted string of meta data for all local and engine gems.') register_show_subparser.add_argument('-v', '--verbose', action='count', required=False, default=0, From 35fed7722305c8a3eaadb91f45836628d5d2ba33 Mon Sep 17 00:00:00 2001 From: mgwynn Date: Wed, 2 Jun 2021 21:56:03 -0400 Subject: [PATCH 2/6] Adding CLI script for modifying project properties (LYN-3918). Updating O3de to support it. Fixing some typo errors in manifest.py and minor optimizations --- scripts/o3de.py | 7 ++- scripts/o3de/o3de/manifest.py | 12 +--- scripts/o3de/o3de/project_properties.py | 82 +++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 11 deletions(-) create mode 100644 scripts/o3de/o3de/project_properties.py diff --git a/scripts/o3de.py b/scripts/o3de.py index 8d7532878c..85d49ec268 100755 --- a/scripts/o3de.py +++ b/scripts/o3de.py @@ -32,7 +32,7 @@ def add_args(parser, subparsers) -> None: # add the scripts/o3de directory to the front of the sys.path sys.path.insert(0, str(o3de_package_dir)) from o3de import engine_template, global_project, register, print_registration, get_registration, \ - enable_gem, disable_gem, sha256 + enable_gem, disable_gem, project_properties, sha256 # Remove the temporarily added path sys.path = sys.path[1:] @@ -55,7 +55,10 @@ def add_args(parser, subparsers) -> None: # remove a gem from a project disable_gem.add_args(subparsers) - + + # modify project properties + project_properties.add_args(subparsers) + # sha256 sha256.add_args(subparsers) diff --git a/scripts/o3de/o3de/manifest.py b/scripts/o3de/o3de/manifest.py index 2a7e5bba11..edcd44c525 100644 --- a/scripts/o3de/o3de/manifest.py +++ b/scripts/o3de/o3de/manifest.py @@ -573,9 +573,7 @@ def get_registered(engine_name: str = None, return engine_path elif isinstance(project_name, str): - enging_projects = get_engine_projects() - projects = json_data['projects'].copy() - projects.extend(engine_object['projects']) + projects = get_all_projects() for project_path in projects: project_path = pathlib.Path(project_path).resolve() project_json = project_path / 'project.json' @@ -605,9 +603,7 @@ def get_registered(engine_name: str = None, return gem_path elif isinstance(template_name, str): - engine_templates = get_engine_templates() - templates = json_data['templates'].copy() - templates.extend(engine_templates) + templates = get_all_templates() for template_path in templates: template_path = pathlib.Path(template_path).resolve() template_json = template_path / 'template.json' @@ -622,9 +618,7 @@ def get_registered(engine_name: str = None, return template_path elif isinstance(restricted_name, str): - engine_restricted = get_engine_restricted() - restricted = json_data['restricted'].copy() - restricted.extend(engine_restricted) + restricted = get_all_restricted() for restricted_path in restricted: restricted_path = pathlib.Path(restricted_path).resolve() restricted_json = restricted_path / 'restricted.json' diff --git a/scripts/o3de/o3de/project_properties.py b/scripts/o3de/o3de/project_properties.py new file mode 100644 index 0000000000..10153ff833 --- /dev/null +++ b/scripts/o3de/o3de/project_properties.py @@ -0,0 +1,82 @@ +import argparse +import json +import os +import pathlib +import sys +import logging + +from o3de import manifest + +logger = logging.getLogger() +logging.basicConfig() + +def get_project_props(name: str = None, path: pathlib.Path = None) -> dict: + proj_json = manifest.get_project_json_data(project_name=name, project_path=path) + if not proj_json: + logger.error('Could not retrieve project.json file') + return None + return proj_json + +def edit_project_props(proj_path, proj_name, new_origin, new_display, + new_summary, new_icon, new_tag) -> int: + proj_json = get_project_props(proj_name, proj_path) + + try: + if new_origin and 'origin' in proj_json: + proj_json['origin'] = new_origin + if new_display and 'display_name' in proj_json: + proj_json['display_name'] = new_display + if new_summary and 'summary' in proj_json: + proj_json['summary'] = new_summary + if new_icon and 'icon_path' in proj_json: + proj_json['icon_path'] = new_icon + if new_tag and 'user_tags' in proj_json: + proj_json['user_tags'].append(new_tag) + except Exception as e: + logger.error(e) + return 1 + + manifest.save_o3de_manifest(proj_json, pathlib.Path(proj_path)/'project.json') + return 0 + +def _edit_project_props(args: argparse) -> int: + return edit_project_props(args.project_path, + args.project_name, + args.project_origin, + args.project_display, + args.project_summary, + args.project_icon, + args.project_tag) + +def add_parser_args(parser): + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('-pp', '--project-path', type=pathlib.Path, required=False, + help='The path to the project.') + group.add_argument('-pn', '--project-name', type=str, required=False, + help='The name of the project.') + group = parser.add_argument_group('properties', 'arguments for modifying individual project properties.') + group.add_argument('-po', '--project-origin', type=str, required=False, + help='Sets description or url for project origin.') + group.add_argument('-pd', '--project-display', type=str, required=False, + help='Sets the project display name.') + group.add_argument('-ps', '--project-summary', type=str, required=False, + help='Sets the summary description of the project.') + group.add_argument('-pi', '--project-icon', type=str, required=False, + help='Sets the path to the projects icon resource.') + group.add_argument('-pt', '--project-tag', type=str, required=False, + help='Adds a tag to canonical user tags.') + parser.set_defaults(func=_edit_project_props) + +def add_args(subparsers) -> None: + enable_project_props_subparser = subparsers.add_parser('edit-project-props') + add_parser_args(enable_project_props_subparser) + +def main(): + the_parser = argparse.ArgumentParser() + add_parser_args(the_parser) + the_args = the_parser.parse_args() + ret = the_args.func(the_args) if hasattr(the_args, 'func') else 1 + sys.exit(ret) + +if __name__ == "__main__": + main() \ No newline at end of file From 5838975d626fc632d74f6069bfa329b5092ab062 Mon Sep 17 00:00:00 2001 From: mgwynn Date: Thu, 3 Jun 2021 13:29:51 -0400 Subject: [PATCH 3/6] Incorporating review comments. Minor formatting changes and changes to parameter descriptions. Removed try-catch for property modification and added creation of user_tags element if it does not exist but is modified through CLI --- scripts/o3de/o3de/project_properties.py | 37 +++++++++++++------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/scripts/o3de/o3de/project_properties.py b/scripts/o3de/o3de/project_properties.py index 10153ff833..d8453a2c4f 100644 --- a/scripts/o3de/o3de/project_properties.py +++ b/scripts/o3de/o3de/project_properties.py @@ -21,22 +21,23 @@ def edit_project_props(proj_path, proj_name, new_origin, new_display, new_summary, new_icon, new_tag) -> int: proj_json = get_project_props(proj_name, proj_path) - try: - if new_origin and 'origin' in proj_json: - proj_json['origin'] = new_origin - if new_display and 'display_name' in proj_json: - proj_json['display_name'] = new_display - if new_summary and 'summary' in proj_json: - proj_json['summary'] = new_summary - if new_icon and 'icon_path' in proj_json: - proj_json['icon_path'] = new_icon - if new_tag and 'user_tags' in proj_json: - proj_json['user_tags'].append(new_tag) - except Exception as e: - logger.error(e) + if not proj_json: return 1 - manifest.save_o3de_manifest(proj_json, pathlib.Path(proj_path)/'project.json') + if new_origin: + proj_json['origin'] = new_origin + if new_display: + proj_json['display_name'] = new_display + if new_summary: + proj_json['summary'] = new_summary + if new_icon: + proj_json['icon_path'] = new_icon + if new_tag: + if 'user_tags' not in proj_json: + proj_json['user_tags'] = [] + proj_json['user_tags'].append(new_tag) + + manifest.save_o3de_manifest(proj_json, pathlib.Path(proj_path) / 'project.json') return 0 def _edit_project_props(args: argparse) -> int: @@ -56,7 +57,7 @@ def add_parser_args(parser): help='The name of the project.') group = parser.add_argument_group('properties', 'arguments for modifying individual project properties.') group.add_argument('-po', '--project-origin', type=str, required=False, - help='Sets description or url for project origin.') + 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, help='Sets the project display name.') group.add_argument('-ps', '--project-summary', type=str, required=False, @@ -64,11 +65,11 @@ def add_parser_args(parser): group.add_argument('-pi', '--project-icon', type=str, required=False, help='Sets the path to the projects icon resource.') group.add_argument('-pt', '--project-tag', type=str, required=False, - help='Adds a tag to canonical user tags.') + help='Adds a tag to canonical user tags. These tags are intended for documentation and filtering.') parser.set_defaults(func=_edit_project_props) def add_args(subparsers) -> None: - enable_project_props_subparser = subparsers.add_parser('edit-project-props') + enable_project_props_subparser = subparsers.add_parser('edit-project-properties') add_parser_args(enable_project_props_subparser) def main(): @@ -79,4 +80,4 @@ def main(): sys.exit(ret) if __name__ == "__main__": - main() \ No newline at end of file + main() From 6681a5376844f9e3fcb0faebe6ffe6983c9bfa03 Mon Sep 17 00:00:00 2001 From: mgwynn Date: Thu, 3 Jun 2021 14:13:44 -0400 Subject: [PATCH 4/6] Add the ability to remove tags. Updated some descriptions, and updated some log messages to include parameters. --- scripts/o3de/o3de/project_properties.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/scripts/o3de/o3de/project_properties.py b/scripts/o3de/o3de/project_properties.py index d8453a2c4f..7a9610a775 100644 --- a/scripts/o3de/o3de/project_properties.py +++ b/scripts/o3de/o3de/project_properties.py @@ -13,12 +13,13 @@ logging.basicConfig() def get_project_props(name: str = None, path: pathlib.Path = None) -> dict: proj_json = manifest.get_project_json_data(project_name=name, project_path=path) if not proj_json: - logger.error('Could not retrieve project.json file') + param = name if name else path + logger.error(f'Could not retrieve project.json file for {param}') return None return proj_json def edit_project_props(proj_path, proj_name, new_origin, new_display, - new_summary, new_icon, new_tag) -> int: + new_summary, new_icon, new_tag, remove_tag) -> int: proj_json = get_project_props(proj_name, proj_path) if not proj_json: @@ -36,6 +37,14 @@ def edit_project_props(proj_path, proj_name, new_origin, new_display, if 'user_tags' not in proj_json: proj_json['user_tags'] = [] proj_json['user_tags'].append(new_tag) + if remove_tag: + if 'user_tags' in proj_json: + if remove_tag in proj_json['user_tags']: + proj_json['user_tags'].remove(remove_tag) + else: + logger.warn(f'{remove_tag} not found in user_tags for removal.') + else: + logger.warn(f'user_tags property not found for removal of tag {remove_tag}.') manifest.save_o3de_manifest(proj_json, pathlib.Path(proj_path) / 'project.json') return 0 @@ -47,7 +56,8 @@ def _edit_project_props(args: argparse) -> int: args.project_display, args.project_summary, args.project_icon, - args.project_tag) + args.project_tag, + args.remove_tag) def add_parser_args(parser): group = parser.add_mutually_exclusive_group(required=True) @@ -65,7 +75,9 @@ def add_parser_args(parser): group.add_argument('-pi', '--project-icon', type=str, required=False, help='Sets the path to the projects icon resource.') group.add_argument('-pt', '--project-tag', type=str, required=False, - help='Adds a tag to canonical user tags. These tags are intended for documentation and filtering.') + help='Adds a tag to user tags. These tags are intended for documentation and filtering.') + group.add_argument('-rt', '--remove-tag', type=str, required=False, + help='Removes a tag from user tags. These tags are intended for documentation and filtering.') parser.set_defaults(func=_edit_project_props) def add_args(subparsers) -> None: From 7bba5ed2fc6f91a66fd2fbaada65ac130d7b1c87 Mon Sep 17 00:00:00 2001 From: mgwynn Date: Thu, 3 Jun 2021 14:43:13 -0400 Subject: [PATCH 5/6] Incorporated suggestion to use setdefault to handle missing tag property rather than explicitly checking for and creating it. --- scripts/o3de/o3de/project_properties.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/scripts/o3de/o3de/project_properties.py b/scripts/o3de/o3de/project_properties.py index 7a9610a775..63ff05a8da 100644 --- a/scripts/o3de/o3de/project_properties.py +++ b/scripts/o3de/o3de/project_properties.py @@ -34,9 +34,7 @@ def edit_project_props(proj_path, proj_name, new_origin, new_display, if new_icon: proj_json['icon_path'] = new_icon if new_tag: - if 'user_tags' not in proj_json: - proj_json['user_tags'] = [] - proj_json['user_tags'].append(new_tag) + proj_json.setdefault('user_tags', []).append(new_tag) if remove_tag: if 'user_tags' in proj_json: if remove_tag in proj_json['user_tags']: @@ -75,9 +73,9 @@ def add_parser_args(parser): group.add_argument('-pi', '--project-icon', type=str, required=False, help='Sets the path to the projects icon resource.') group.add_argument('-pt', '--project-tag', type=str, required=False, - help='Adds a tag to user tags. These tags are intended for documentation and filtering.') + help='Adds a tag to user_tags property. These tags are intended for documentation and filtering.') group.add_argument('-rt', '--remove-tag', type=str, required=False, - help='Removes a tag from user tags. These tags are intended for documentation and filtering.') + help='Removes a tag from the user_tags property.') parser.set_defaults(func=_edit_project_props) def add_args(subparsers) -> None: From e99a95d909948d51b02b6fefb3f393eace5b7aca Mon Sep 17 00:00:00 2001 From: mgwynn Date: Thu, 3 Jun 2021 15:02:18 -0400 Subject: [PATCH 6/6] Added copyright header for validation --- scripts/o3de/o3de/project_properties.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/scripts/o3de/o3de/project_properties.py b/scripts/o3de/o3de/project_properties.py index 63ff05a8da..69bd1b9406 100644 --- a/scripts/o3de/o3de/project_properties.py +++ b/scripts/o3de/o3de/project_properties.py @@ -1,3 +1,14 @@ +# +# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or +# its licensors. +# +# For complete copyright and license terms please see the LICENSE at the root of this +# distribution (the "License"). All use of this software is governed by the License, +# or, if provided, by the license below or the license accompanying this file. Do not +# remove or modify any license notices. This file is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# + import argparse import json import os