From accd473ff5cd03a9e003dee4476c7c2581f4f125 Mon Sep 17 00:00:00 2001 From: mgwynn Date: Fri, 4 Jun 2021 20:19:38 -0400 Subject: [PATCH 1/8] Adding python bindings for modifying project properties --- .../ProjectManager/Source/PythonBindings.cpp | 18 ++++++++++++++++++ .../ProjectManager/Source/PythonBindings.h | 6 ++++++ .../Source/PythonBindingsInterface.h | 19 +++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 37e636caef..0acbf8ffaf 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -289,6 +289,7 @@ namespace O3DE::ProjectManager m_engineTemplate = pybind11::module::import("o3de.engine_template"); m_enableGemProject = pybind11::module::import("o3de.enable_gem"); m_disableGemProject = pybind11::module::import("o3de.disable_gem"); + m_editProjectProperties = pybind11::module::import("o3de.project_properties"); // make sure the engine is registered RegisterThisEngine(); @@ -686,6 +687,23 @@ namespace O3DE::ProjectManager return projectInfo; } + AZ::Outcome PythonBindings::ModifyProjectProperties(const QString& path, const QString& origin, const QString& displayName, + const QString& summary, const QString& icon, const QString& addTag, const QString& removeTag) + { + return ExecuteWithLockErrorHandling([&] + { + m_editProjectProperties.attr("edit_project_props")( + pybind11::str(path.toStdString()), //proj_path + pybind11::none(), //proj_name not used + origin.isNull() ? pybind11::none() : pybind11::str(origin.toStdString()), //new_origin + displayName.isNull() ? pybind11::none() : pybind11::str(displayName.toStdString()), //new_display + summary.isNull() ? pybind11::none() : pybind11::str(summary.toStdString()), //new_summary + icon.isNull() ? pybind11::none() : pybind11::str(icon.toStdString()), //new_icon + addTag.isNull() ? pybind11::none() : pybind11::str(addTag.toStdString()), //new_tag + removeTag.isNull() ? pybind11::none() : pybind11::str(removeTag.toStdString())); //remove_tag + }); + } + AZ::Outcome> PythonBindings::GetProjects() { QVector projects; diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.h b/Code/Tools/ProjectManager/Source/PythonBindings.h index 278aa2d5d7..5f03d0ab28 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.h +++ b/Code/Tools/ProjectManager/Source/PythonBindings.h @@ -53,6 +53,11 @@ namespace O3DE::ProjectManager bool UpdateProject(const ProjectInfo& projectInfo) override; AZ::Outcome AddGemToProject(const QString& gemPath, const QString& projectPath) override; AZ::Outcome RemoveGemFromProject(const QString& gemPath, const QString& projectPath) override; + AZ::Outcome ModifyProjectProperties( + const QString& path, + const QString& origin = 0, + const QString& displayName = 0, + const QString& summary = 0, const QString& icon = 0, const QString& addTag = 0, const QString& removeTag = 0) override; // ProjectTemplate AZ::Outcome> GetProjectTemplates() override; @@ -78,5 +83,6 @@ namespace O3DE::ProjectManager pybind11::handle m_manifest; pybind11::handle m_enableGemProject; pybind11::handle m_disableGemProject; + pybind11::handle m_editProjectProperties; }; } diff --git a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h index 09d9187dbd..edc9510236 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h +++ b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h @@ -132,6 +132,25 @@ namespace O3DE::ProjectManager */ virtual AZ::Outcome AddGemToProject(const QString& gemPath, const QString& projectPath) = 0; + /** + * Change property in project json file + * @param path the absolute path to the gem + * @param origin the description or url for project origin (such as project host, repository, owner...etc) + * @param displayName the project display name + * @param summary short description of the project + * @param icon image used to represent the project + * @param addTag user tag to be added + * @param removeTag user tag to be removed + */ + virtual AZ::Outcome ModifyProjectProperties( + const QString& path, + const QString& origin = 0, + const QString& displayName = 0, + const QString& summary = 0, + const QString& icon = 0, + const QString& addTag = 0, + const QString& removeTag = 0) = 0; + /** * Remove gem to a project * @param gemPath the absolute path to the gem From 7984f82e481b2ddac0a8ebb7f2b28b4aa9d8f9d8 Mon Sep 17 00:00:00 2001 From: mgwynn Date: Fri, 4 Jun 2021 23:03:17 -0400 Subject: [PATCH 2/8] Bing project_properties CLI to updateProject method. Update project info struct. Update project properties cli to support lists for tags. Minor adjustments to support changes. --- .../ProjectManager/Source/ProjectInfo.cpp | 7 ++- .../Tools/ProjectManager/Source/ProjectInfo.h | 13 ++++-- .../ProjectManager/Source/PythonBindings.cpp | 45 +++++++++++-------- .../ProjectManager/Source/PythonBindings.h | 7 +-- .../Source/PythonBindingsInterface.h | 21 +-------- .../Source/UpdateProjectCtrl.cpp | 6 +-- scripts/o3de/o3de/project_properties.py | 22 ++++----- 7 files changed, 59 insertions(+), 62 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/ProjectInfo.cpp b/Code/Tools/ProjectManager/Source/ProjectInfo.cpp index f0dc05cc62..f470841f09 100644 --- a/Code/Tools/ProjectManager/Source/ProjectInfo.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectInfo.cpp @@ -15,14 +15,19 @@ namespace O3DE::ProjectManager { ProjectInfo::ProjectInfo(const QString& path, const QString& projectName, const QString& displayName, - const QString& imagePath, const QString& backgroundImagePath, bool isNew) + const QString& origin, const QString& summary, const QString& imagePath, const QString& backgroundImagePath, + bool isNew) : m_path(path) , m_projectName(projectName) , m_displayName(displayName) + , m_origin(origin) + , m_summary(summary) , m_imagePath(imagePath) , m_backgroundImagePath(backgroundImagePath) , m_isNew(isNew) { + m_userTags = QStringList(); + m_userTagsForRemoval = QStringList(); } bool ProjectInfo::operator==(const ProjectInfo& rhs) diff --git a/Code/Tools/ProjectManager/Source/ProjectInfo.h b/Code/Tools/ProjectManager/Source/ProjectInfo.h index 71fa12b344..699d0997c6 100644 --- a/Code/Tools/ProjectManager/Source/ProjectInfo.h +++ b/Code/Tools/ProjectManager/Source/ProjectInfo.h @@ -15,6 +15,7 @@ #if !defined(Q_MOC_RUN) #include #include +#include #endif namespace O3DE::ProjectManager @@ -23,8 +24,8 @@ namespace O3DE::ProjectManager { public: ProjectInfo() = default; - ProjectInfo(const QString& path, const QString& projectName, const QString& displayName, - const QString& imagePath, const QString& backgroundImagePath, bool isNew); + ProjectInfo(const QString& path, const QString& projectName, const QString& displayName, const QString& origin, + const QString& summary, const QString& imagePath, const QString& backgroundImagePath, bool isNew); bool operator==(const ProjectInfo& rhs); bool operator!=(const ProjectInfo& rhs); @@ -36,12 +37,18 @@ namespace O3DE::ProjectManager // From project.json QString m_projectName; QString m_displayName; + QString m_origin; + QString m_summary; + QStringList m_userTags; // Used on projects home screen QString m_imagePath; - QString m_backgroundImagePath; + QStringList m_backgroundImagePath; // Used in project creation bool m_isNew = false; //! Is this a new project or existing + + // Used to flag tags for removal + QStringList m_userTagsForRemoval; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 0acbf8ffaf..16bcd6e122 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #pragma pop_macro("slots") #include @@ -687,23 +688,6 @@ namespace O3DE::ProjectManager return projectInfo; } - AZ::Outcome PythonBindings::ModifyProjectProperties(const QString& path, const QString& origin, const QString& displayName, - const QString& summary, const QString& icon, const QString& addTag, const QString& removeTag) - { - return ExecuteWithLockErrorHandling([&] - { - m_editProjectProperties.attr("edit_project_props")( - pybind11::str(path.toStdString()), //proj_path - pybind11::none(), //proj_name not used - origin.isNull() ? pybind11::none() : pybind11::str(origin.toStdString()), //new_origin - displayName.isNull() ? pybind11::none() : pybind11::str(displayName.toStdString()), //new_display - summary.isNull() ? pybind11::none() : pybind11::str(summary.toStdString()), //new_summary - icon.isNull() ? pybind11::none() : pybind11::str(icon.toStdString()), //new_icon - addTag.isNull() ? pybind11::none() : pybind11::str(addTag.toStdString()), //new_tag - removeTag.isNull() ? pybind11::none() : pybind11::str(removeTag.toStdString())); //remove_tag - }); - } - AZ::Outcome> PythonBindings::GetProjects() { QVector projects; @@ -764,9 +748,32 @@ namespace O3DE::ProjectManager }); } - bool PythonBindings::UpdateProject([[maybe_unused]] const ProjectInfo& projectInfo) + AZ::Outcome PythonBindings::UpdateProject(const ProjectInfo& projectInfo) { - return false; + return ExecuteWithLockErrorHandling([&] + { + std::list newTags; + for (auto& i : projectInfo.m_userTags) + { + newTags.push_back(i.toStdString()); + } + + std::list removedTags; + for (auto& i : projectInfo.m_userTagsForRemoval) + { + removedTags.push_back(i.toStdString()); + } + + m_editProjectProperties.attr("edit_project_props")( + pybind11::str(projectInfo.m_path.toStdString()), // proj_path + pybind11::none(), // proj_name not used + pybind11::str(projectInfo.m_origin.toStdString()), // new_origin + pybind11::str(projectInfo.m_displayName.toStdString()), // new_display + pybind11::str(projectInfo.m_summary.toStdString()), // new_summary + pybind11::str(projectInfo.m_imagePath.toStdString()), // new_icon + pybind11::list(pybind11::cast(newTags)), // new_tag + pybind11::list(pybind11::cast(removedTags))); // remove_tag + }); } ProjectTemplateInfo PythonBindings::ProjectTemplateInfoFromPath(pybind11::handle path) diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.h b/Code/Tools/ProjectManager/Source/PythonBindings.h index 5f03d0ab28..707595b6fd 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.h +++ b/Code/Tools/ProjectManager/Source/PythonBindings.h @@ -50,14 +50,9 @@ namespace O3DE::ProjectManager AZ::Outcome> GetProjects() override; bool AddProject(const QString& path) override; bool RemoveProject(const QString& path) override; - bool UpdateProject(const ProjectInfo& projectInfo) override; + AZ::Outcome UpdateProject(const ProjectInfo& projectInfo) override; AZ::Outcome AddGemToProject(const QString& gemPath, const QString& projectPath) override; AZ::Outcome RemoveGemFromProject(const QString& gemPath, const QString& projectPath) override; - AZ::Outcome ModifyProjectProperties( - const QString& path, - const QString& origin = 0, - const QString& displayName = 0, - const QString& summary = 0, const QString& icon = 0, const QString& addTag = 0, const QString& removeTag = 0) override; // ProjectTemplate AZ::Outcome> GetProjectTemplates() override; diff --git a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h index edc9510236..fd94a4e964 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h +++ b/Code/Tools/ProjectManager/Source/PythonBindingsInterface.h @@ -122,7 +122,7 @@ namespace O3DE::ProjectManager * @param projectInfo the info to use to update the project * @return true on success, false on failure */ - virtual bool UpdateProject(const ProjectInfo& projectInfo) = 0; + virtual AZ::Outcome UpdateProject(const ProjectInfo& projectInfo) = 0; /** * Add a gem to a project @@ -132,25 +132,6 @@ namespace O3DE::ProjectManager */ virtual AZ::Outcome AddGemToProject(const QString& gemPath, const QString& projectPath) = 0; - /** - * Change property in project json file - * @param path the absolute path to the gem - * @param origin the description or url for project origin (such as project host, repository, owner...etc) - * @param displayName the project display name - * @param summary short description of the project - * @param icon image used to represent the project - * @param addTag user tag to be added - * @param removeTag user tag to be removed - */ - virtual AZ::Outcome ModifyProjectProperties( - const QString& path, - const QString& origin = 0, - const QString& displayName = 0, - const QString& summary = 0, - const QString& icon = 0, - const QString& addTag = 0, - const QString& removeTag = 0) = 0; - /** * Remove gem to a project * @param gemPath the absolute path to the gem diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp index a383a0f93b..19078f65ea 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp @@ -134,10 +134,10 @@ namespace O3DE::ProjectManager // Update project if settings changed if (m_projectInfo != newProjectSettings) { - bool result = PythonBindingsInterface::Get()->UpdateProject(newProjectSettings); - if (!result) + auto result = PythonBindingsInterface::Get()->UpdateProject(newProjectSettings); + if (!result.IsSuccess()) { - QMessageBox::critical(this, tr("Project update failed"), tr("Failed to update project.")); + QMessageBox::critical(this, tr("Project update failed"), tr(result.GetError().c_str())); return; } } diff --git a/scripts/o3de/o3de/project_properties.py b/scripts/o3de/o3de/project_properties.py index 69bd1b9406..83e76fc18f 100644 --- a/scripts/o3de/o3de/project_properties.py +++ b/scripts/o3de/o3de/project_properties.py @@ -45,15 +45,17 @@ def edit_project_props(proj_path, proj_name, new_origin, new_display, if new_icon: proj_json['icon_path'] = new_icon if new_tag: - proj_json.setdefault('user_tags', []).append(new_tag) + for tag in new_tag: + proj_json.setdefault('user_tags', []).append(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.') + for del_tag in remove_tag: + if del_tag in proj_json['user_tags']: + proj_json['user_tags'].remove(del_tag) + else: + logger.warn(f'{del_tag} not found in user_tags for removal.') else: - logger.warn(f'user_tags property not found for removal of tag {remove_tag}.') + logger.warn(f'user_tags property not found for removal of {remove_tag}.') manifest.save_o3de_manifest(proj_json, pathlib.Path(proj_path) / 'project.json') return 0 @@ -83,10 +85,10 @@ def add_parser_args(parser): 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 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 the user_tags property.') + group.add_argument('-pt', '--project-tag', type=default, required=False, + help='Adds tag(s) to user_tags property. These tags are intended for documentation and filtering.') + group.add_argument('-rt', '--remove-tag', type=default, required=False, + help='Removes tag(s) from the user_tags property.') parser.set_defaults(func=_edit_project_props) def add_args(subparsers) -> None: From 155271a0ee164610e70cb93726f14b67103859e8 Mon Sep 17 00:00:00 2001 From: mgwynn Date: Fri, 4 Jun 2021 23:07:36 -0400 Subject: [PATCH 3/8] Fixed data type changed by mistake for project info image path --- Code/Tools/ProjectManager/Source/ProjectInfo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Tools/ProjectManager/Source/ProjectInfo.h b/Code/Tools/ProjectManager/Source/ProjectInfo.h index 699d0997c6..63f509af18 100644 --- a/Code/Tools/ProjectManager/Source/ProjectInfo.h +++ b/Code/Tools/ProjectManager/Source/ProjectInfo.h @@ -43,7 +43,7 @@ namespace O3DE::ProjectManager // Used on projects home screen QString m_imagePath; - QStringList m_backgroundImagePath; + QString m_backgroundImagePath; // Used in project creation bool m_isNew = false; //! Is this a new project or existing From d2f8e4903719dfb97ec08795432106ce45ebbf13 Mon Sep 17 00:00:00 2001 From: mgwynn Date: Fri, 4 Jun 2021 23:16:25 -0400 Subject: [PATCH 4/8] resolving merge conflict due to variable name change from main --- Code/Tools/ProjectManager/Source/ProjectInfo.cpp | 4 ++-- Code/Tools/ProjectManager/Source/ProjectInfo.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/ProjectInfo.cpp b/Code/Tools/ProjectManager/Source/ProjectInfo.cpp index f470841f09..85716fccfa 100644 --- a/Code/Tools/ProjectManager/Source/ProjectInfo.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectInfo.cpp @@ -16,7 +16,7 @@ namespace O3DE::ProjectManager { ProjectInfo::ProjectInfo(const QString& path, const QString& projectName, const QString& displayName, const QString& origin, const QString& summary, const QString& imagePath, const QString& backgroundImagePath, - bool isNew) + bool needsBuild) : m_path(path) , m_projectName(projectName) , m_displayName(displayName) @@ -24,7 +24,7 @@ namespace O3DE::ProjectManager , m_summary(summary) , m_imagePath(imagePath) , m_backgroundImagePath(backgroundImagePath) - , m_isNew(isNew) + , m_needsBuild(needsBuild) { m_userTags = QStringList(); m_userTagsForRemoval = QStringList(); diff --git a/Code/Tools/ProjectManager/Source/ProjectInfo.h b/Code/Tools/ProjectManager/Source/ProjectInfo.h index 63f509af18..99ab8ebf31 100644 --- a/Code/Tools/ProjectManager/Source/ProjectInfo.h +++ b/Code/Tools/ProjectManager/Source/ProjectInfo.h @@ -25,7 +25,7 @@ namespace O3DE::ProjectManager public: ProjectInfo() = default; ProjectInfo(const QString& path, const QString& projectName, const QString& displayName, const QString& origin, - const QString& summary, const QString& imagePath, const QString& backgroundImagePath, bool isNew); + const QString& summary, const QString& imagePath, const QString& backgroundImagePath, bool needsBuild); bool operator==(const ProjectInfo& rhs); bool operator!=(const ProjectInfo& rhs); @@ -46,7 +46,7 @@ namespace O3DE::ProjectManager QString m_backgroundImagePath; // Used in project creation - bool m_isNew = false; //! Is this a new project or existing + bool m_needsBuild = false; //! Is this a new project or existing // Used to flag tags for removal QStringList m_userTagsForRemoval; From 6d6f8413c8fa260ff2dec8dc1aaa674125a915ad Mon Sep 17 00:00:00 2001 From: mgwynn Date: Mon, 7 Jun 2021 14:14:32 -0400 Subject: [PATCH 5/8] Incorporating review comments. Some parameter modifications. Some cli edge case handling. Remove remove_tag member from project info --- .../ProjectManager/Source/ProjectInfo.cpp | 2 - .../Tools/ProjectManager/Source/ProjectInfo.h | 14 ++++--- .../ProjectManager/Source/PythonBindings.cpp | 20 +++++----- scripts/o3de/o3de/project_properties.py | 39 +++++++++++-------- 4 files changed, 43 insertions(+), 32 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/ProjectInfo.cpp b/Code/Tools/ProjectManager/Source/ProjectInfo.cpp index 85716fccfa..99649cbfdf 100644 --- a/Code/Tools/ProjectManager/Source/ProjectInfo.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectInfo.cpp @@ -26,8 +26,6 @@ namespace O3DE::ProjectManager , m_backgroundImagePath(backgroundImagePath) , m_needsBuild(needsBuild) { - m_userTags = QStringList(); - m_userTagsForRemoval = QStringList(); } bool ProjectInfo::operator==(const ProjectInfo& rhs) diff --git a/Code/Tools/ProjectManager/Source/ProjectInfo.h b/Code/Tools/ProjectManager/Source/ProjectInfo.h index 47a10dbc14..184916a514 100644 --- a/Code/Tools/ProjectManager/Source/ProjectInfo.h +++ b/Code/Tools/ProjectManager/Source/ProjectInfo.h @@ -25,8 +25,15 @@ namespace O3DE::ProjectManager public: ProjectInfo() = default; - ProjectInfo(const QString& path, const QString& projectName, const QString& displayName, const QString& origin, - const QString& summary, const QString& imagePath, const QString& backgroundImagePath, bool needsBuild + ProjectInfo( + const QString& path, + const QString& projectName, + const QString& displayName, + const QString& origin, + const QString& summary, + const QString& imagePath, + const QString& backgroundImagePath, + bool needsBuild); bool operator==(const ProjectInfo& rhs); bool operator!=(const ProjectInfo& rhs); @@ -49,9 +56,6 @@ namespace O3DE::ProjectManager // Used in project creation - // Used to flag tags for removal - QStringList m_userTagsForRemoval; - bool m_needsBuild = false; //! Does this project need to be built }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 9fa10ce3d8..fe01209172 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -53,6 +53,7 @@ namespace Platform #define Py_To_String(obj) obj.cast().c_str() #define Py_To_String_Optional(dict, key, default_string) dict.contains(key) ? Py_To_String(dict[key]) : default_string +#define Py_To_List(obj) obj.cast> namespace RedirectOutput { @@ -678,6 +679,12 @@ namespace O3DE::ProjectManager { projectInfo.m_projectName = Py_To_String(projectData["project_name"]); projectInfo.m_displayName = Py_To_String_Optional(projectData, "display_name", projectInfo.m_projectName); + projectInfo.m_origin = Py_To_String_Optional(projectData, "origin", projectInfo.m_origin); + projectInfo.m_summary = Py_To_String_Optional(projectData, "summary", projectInfo.m_summary); + for (const auto& tag : projectData["user_tags"]) + { + projectInfo.m_userTags.append(Py_To_String(tag)); + } } catch ([[maybe_unused]] const std::exception& e) { @@ -753,17 +760,11 @@ namespace O3DE::ProjectManager return ExecuteWithLockErrorHandling([&] { std::list newTags; - for (auto& i : projectInfo.m_userTags) + for (const auto& i : projectInfo.m_userTags) { newTags.push_back(i.toStdString()); } - std::list removedTags; - for (auto& i : projectInfo.m_userTagsForRemoval) - { - removedTags.push_back(i.toStdString()); - } - m_editProjectProperties.attr("edit_project_props")( pybind11::str(projectInfo.m_path.toStdString()), // proj_path pybind11::none(), // proj_name not used @@ -771,8 +772,9 @@ namespace O3DE::ProjectManager pybind11::str(projectInfo.m_displayName.toStdString()), // new_display pybind11::str(projectInfo.m_summary.toStdString()), // new_summary pybind11::str(projectInfo.m_imagePath.toStdString()), // new_icon - pybind11::list(pybind11::cast(newTags)), // new_tag - pybind11::list(pybind11::cast(removedTags))); // remove_tag + pybind11::none(), // add_tags not used + pybind11::none(), // remove_tags not used + pybind11::list(pybind11::cast(newTags))); // replace_tags }); } diff --git a/scripts/o3de/o3de/project_properties.py b/scripts/o3de/o3de/project_properties.py index 83e76fc18f..b2268131c0 100644 --- a/scripts/o3de/o3de/project_properties.py +++ b/scripts/o3de/o3de/project_properties.py @@ -30,7 +30,7 @@ def get_project_props(name: str = None, path: pathlib.Path = None) -> dict: return proj_json def edit_project_props(proj_path, proj_name, new_origin, new_display, - new_summary, new_icon, new_tag, remove_tag) -> int: + new_summary, new_icon, new_tags, delete_tags, replace_tags) -> int: proj_json = get_project_props(proj_name, proj_path) if not proj_json: @@ -44,18 +44,22 @@ def edit_project_props(proj_path, proj_name, new_origin, new_display, proj_json['summary'] = new_summary if new_icon: proj_json['icon_path'] = new_icon - if new_tag: - for tag in new_tag: - proj_json.setdefault('user_tags', []).append(tag) - if remove_tag: + if new_tags: + tag_list = [new_tags] if isinstance(new_tags, str) else new_tags + proj_json.setdefault('user_tags', []).extend(tag_list) + if delete_tags: + removal_list = [delete_tags] if isinstance(delete_tags, str) else delete_tags if 'user_tags' in proj_json: - for del_tag in remove_tag: - if del_tag in proj_json['user_tags']: - proj_json['user_tags'].remove(del_tag) + for tag in removal_list: + if tag in proj_json['user_tags']: + proj_json['user_tags'].remove(tag) else: - logger.warn(f'{del_tag} not found in user_tags for removal.') + logger.warn(f'{tag} not found in user_tags for removal.') else: - logger.warn(f'user_tags property not found for removal of {remove_tag}.') + logger.warn(f'user_tags property not found for removal of {remove_tags}.') + if replace_tags: + tag_list = [replace_tags] if isinstance(replace_tags, str) else replace_tags + proj_json['user_tags'] = tag_list manifest.save_o3de_manifest(proj_json, pathlib.Path(proj_path) / 'project.json') return 0 @@ -67,8 +71,9 @@ def _edit_project_props(args: argparse) -> int: args.project_display, args.project_summary, args.project_icon, - args.project_tag, - args.remove_tag) + args.add_tags, + args.delete_tags, + args.replace_tags) def add_parser_args(parser): group = parser.add_mutually_exclusive_group(required=True) @@ -85,10 +90,12 @@ def add_parser_args(parser): 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=default, required=False, - help='Adds tag(s) to user_tags property. These tags are intended for documentation and filtering.') - group.add_argument('-rt', '--remove-tag', type=default, required=False, - help='Removes tag(s) from the user_tags property.') + group.add_argument('-at', '--add-tags', type=str, nargs='*', required=False, + help='Adds tag(s) to user_tags property. Space delimited list (ex. -at A B C)') + group.add_argument('-dt', '--delete-tags', type=str, nargs ='*', required=False, + help='Removes tag(s) from the user_tags property. Space delimited list (ex. -dt A B C') + group.add_argument('-rt', '--replace-tags', type=str, nargs ='*', required=False, + help='Replace entirety of user_tags proeprty with space delimited list of values') parser.set_defaults(func=_edit_project_props) def add_args(subparsers) -> None: From 01b200ad42ddf57386cea3ad44c9121e286e2477 Mon Sep 17 00:00:00 2001 From: mgwynn Date: Mon, 7 Jun 2021 14:19:48 -0400 Subject: [PATCH 6/8] removing unused define --- Code/Tools/ProjectManager/Source/PythonBindings.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index fe01209172..1db8c92d3f 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -53,7 +53,6 @@ namespace Platform #define Py_To_String(obj) obj.cast().c_str() #define Py_To_String_Optional(dict, key, default_string) dict.contains(key) ? Py_To_String(dict[key]) : default_string -#define Py_To_List(obj) obj.cast> namespace RedirectOutput { From b0826c5f9cdeb3d2d51d23fec5aaea5c6eaa0302 Mon Sep 17 00:00:00 2001 From: mgwynn Date: Mon, 7 Jun 2021 15:08:18 -0400 Subject: [PATCH 7/8] added tag managerment arguments for CLI to mutually exclusive group --- scripts/o3de/o3de/project_properties.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/o3de/o3de/project_properties.py b/scripts/o3de/o3de/project_properties.py index b2268131c0..52f1346b51 100644 --- a/scripts/o3de/o3de/project_properties.py +++ b/scripts/o3de/o3de/project_properties.py @@ -90,12 +90,13 @@ def add_parser_args(parser): 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 = parser.add_mutually_exclusive_group(required=False) group.add_argument('-at', '--add-tags', type=str, nargs='*', required=False, help='Adds tag(s) to user_tags property. Space delimited list (ex. -at A B C)') group.add_argument('-dt', '--delete-tags', type=str, nargs ='*', required=False, help='Removes tag(s) from the user_tags property. Space delimited list (ex. -dt A B C') group.add_argument('-rt', '--replace-tags', type=str, nargs ='*', required=False, - help='Replace entirety of user_tags proeprty with space delimited list of values') + help='Replace entirety of user_tags property with space delimited list of values') parser.set_defaults(func=_edit_project_props) def add_args(subparsers) -> None: From 1900a422035dcb16fa82144d6a59f630ab9fe952 Mon Sep 17 00:00:00 2001 From: mgwynn Date: Mon, 7 Jun 2021 15:43:47 -0400 Subject: [PATCH 8/8] remove const ref from iterator for python object conversion since pybind only returns copies and produces a clang error --- Code/Tools/ProjectManager/Source/PythonBindings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 1db8c92d3f..5d1463598a 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -680,7 +680,7 @@ namespace O3DE::ProjectManager projectInfo.m_displayName = Py_To_String_Optional(projectData, "display_name", projectInfo.m_projectName); projectInfo.m_origin = Py_To_String_Optional(projectData, "origin", projectInfo.m_origin); projectInfo.m_summary = Py_To_String_Optional(projectData, "summary", projectInfo.m_summary); - for (const auto& tag : projectData["user_tags"]) + for (auto tag : projectData["user_tags"]) { projectInfo.m_userTags.append(Py_To_String(tag)); }