[LYN-2514] Extending pythin bindings to adapt CLI changes for the gem catalog

* Added ExecuteWithLockErrorHandling() which returns an outcome with the actual error we get from python so that we can expose that to the UI.
* Added cmake pybind.
* Get gems now calling get_all_gems and alphabetically sorting the result.
* Added get enabled gems function which first gets the cmake enabled gems file path from the project path and then the list of gem names that are enabled.
* Some changes to the enable and disable gem functions.
main
Benjamin Jillich 5 years ago
parent 7b6226a8aa
commit ede8daaece

@ -283,6 +283,7 @@ namespace O3DE::ProjectManager
AZ_Warning("ProjectManagerWindow", result != -1, "Append to sys path failed");
// import required modules
m_cmake = pybind11::module::import("o3de.cmake");
m_register = pybind11::module::import("o3de.register");
m_manifest = pybind11::module::import("o3de.manifest");
m_engineTemplate = pybind11::module::import("o3de.engine_template");
@ -311,7 +312,7 @@ namespace O3DE::ProjectManager
return !PyErr_Occurred();
}
bool PythonBindings::ExecuteWithLock(AZStd::function<void()> executionCallback)
AZ::Outcome<void, AZStd::string> PythonBindings::ExecuteWithLockErrorHandling(AZStd::function<void()> executionCallback)
{
AZStd::lock_guard<decltype(m_lock)> lock(m_lock);
pybind11::gil_scoped_release release;
@ -320,15 +321,20 @@ namespace O3DE::ProjectManager
try
{
executionCallback();
return true;
return AZ::Success();
}
catch ([[maybe_unused]] const std::exception& e)
{
AZ_Warning("PythonBindings", false, "Python exception %s", e.what());
return false;
return AZ::Failure<AZStd::string>(e.what());
}
}
bool PythonBindings::ExecuteWithLock(AZStd::function<void()> executionCallback)
{
return ExecuteWithLockErrorHandling(executionCallback).IsSuccess();
}
AZ::Outcome<EngineInfo> PythonBindings::GetEngineInfo()
{
EngineInfo engineInfo;
@ -419,7 +425,7 @@ namespace O3DE::ProjectManager
return result;
}
AZ::Outcome<GemInfo> PythonBindings::GetGem(const QString& path)
AZ::Outcome<GemInfo> PythonBindings::GetGemInfo(const QString& path)
{
GemInfo gemInfo = GemInfoFromPath(pybind11::str(path.toStdString()));
if (gemInfo.IsValid())
@ -432,32 +438,59 @@ namespace O3DE::ProjectManager
}
}
AZ::Outcome<QVector<GemInfo>> PythonBindings::GetGems()
AZ::Outcome<QVector<GemInfo>, AZStd::string> PythonBindings::GetAllGemInfos(const QString& projectPath)
{
QVector<GemInfo> gems;
bool result = ExecuteWithLock([&] {
// external gems
for (auto path : m_manifest.attr("get_gems")())
auto result = ExecuteWithLockErrorHandling([&]
{
gems.push_back(GemInfoFromPath(path));
}
pybind11::str pyProjectPath = projectPath.toStdString();
for (auto path : m_manifest.attr("get_all_gems")(pyProjectPath))
{
gems.push_back(GemInfoFromPath(path));
}
});
if (!result.IsSuccess())
{
return AZ::Failure<AZStd::string>(result.GetError().c_str());
}
// gems from the engine
for (auto path : m_manifest.attr("get_engine_gems")())
{
gems.push_back(GemInfoFromPath(path));
}
});
std::sort(gems.begin(), gems.end());
return AZ::Success(AZStd::move(gems));
}
if (!result)
AZ::Outcome<QVector<AZStd::string>, AZStd::string> PythonBindings::GetEnabledGemNames(const QString& projectPath)
{
// Retrieve the path to the cmake file that lists the enabled gems.
pybind11::str enabledGemsFilename;
auto result = ExecuteWithLockErrorHandling([&]
{
const pybind11::str pyProjectPath = projectPath.toStdString();
enabledGemsFilename = m_cmake.attr("get_enabled_gem_cmake_file")(
pybind11::none(), // project_name
pyProjectPath); // project_path
});
if (!result.IsSuccess())
{
return AZ::Failure();
return AZ::Failure<AZStd::string>(result.GetError().c_str());
}
else
// Retrieve the actual list of names from the cmake file.
QVector<AZStd::string> gemNames;
result = ExecuteWithLockErrorHandling([&]
{
const auto pyGemNames = m_cmake.attr("get_enabled_gems")(enabledGemsFilename);
for (auto gemName : pyGemNames)
{
gemNames.push_back(Py_To_String(gemName));
}
});
if (!result.IsSuccess())
{
return AZ::Success(AZStd::move(gems));
return AZ::Failure<AZStd::string>(result.GetError().c_str());
}
return AZ::Success(AZStd::move(gemNames));
}
bool PythonBindings::AddProject(const QString& path)
@ -637,38 +670,36 @@ namespace O3DE::ProjectManager
}
}
bool PythonBindings::AddGemToProject(const QString& gemPath, const QString& projectPath)
AZ::Outcome<void, AZStd::string> PythonBindings::AddGemToProject(const QString& gemPath, const QString& projectPath)
{
bool result = ExecuteWithLock([&] {
pybind11::str pyGemPath = gemPath.toStdString();
pybind11::str pyProjectPath = projectPath.toStdString();
m_enableGemProject.attr("enable_gem_in_project")(
pybind11::none(), // gem_name
pyGemPath,
pybind11::none(), // project_name
pyProjectPath
);
});
return result;
return ExecuteWithLockErrorHandling([&]
{
pybind11::str pyGemPath = gemPath.toStdString();
pybind11::str pyProjectPath = projectPath.toStdString();
m_enableGemProject.attr("enable_gem_in_project")(
pybind11::none(), // gem name not needed as path is provided
pyGemPath,
pybind11::none(), // project name not needed as path is provided
pyProjectPath
);
});
}
bool PythonBindings::RemoveGemFromProject(const QString& gemPath, const QString& projectPath)
AZ::Outcome<void, AZStd::string> PythonBindings::RemoveGemFromProject(const QString& gemPath, const QString& projectPath)
{
bool result = ExecuteWithLock([&] {
pybind11::str pyGemPath = gemPath.toStdString();
pybind11::str pyProjectPath = projectPath.toStdString();
m_disableGemProject.attr("disable_gem_in_project")(
pybind11::none(), // gem_name
pyGemPath,
pybind11::none(), // project_name
pyProjectPath
);
});
return result;
return ExecuteWithLockErrorHandling([&]
{
pybind11::str pyGemPath = gemPath.toStdString();
pybind11::str pyProjectPath = projectPath.toStdString();
m_disableGemProject.attr("disable_gem_in_project")(
pybind11::none(), // gem name not needed as path is provided
pyGemPath,
pybind11::none(), // project name not needed as path is provided
pyProjectPath
);
});
}
bool PythonBindings::UpdateProject([[maybe_unused]] const ProjectInfo& projectInfo)

@ -39,8 +39,9 @@ namespace O3DE::ProjectManager
bool SetEngineInfo(const EngineInfo& engineInfo) override;
// Gem
AZ::Outcome<GemInfo> GetGem(const QString& path) override;
AZ::Outcome<QVector<GemInfo>> GetGems() override;
AZ::Outcome<GemInfo> GetGemInfo(const QString& path) override;
AZ::Outcome<QVector<GemInfo>, AZStd::string> GetAllGemInfos(const QString& projectPath) override;
AZ::Outcome<QVector<AZStd::string>, AZStd::string> GetEnabledGemNames(const QString& projectPath) override;
// Project
AZ::Outcome<ProjectInfo> CreateProject(const QString& projectTemplatePath, const ProjectInfo& projectInfo) override;
@ -49,8 +50,8 @@ namespace O3DE::ProjectManager
bool AddProject(const QString& path) override;
bool RemoveProject(const QString& path) override;
bool UpdateProject(const ProjectInfo& projectInfo) override;
bool AddGemToProject(const QString& gemPath, const QString& projectPath) override;
bool RemoveGemFromProject(const QString& gemPath, const QString& projectPath) override;
AZ::Outcome<void, AZStd::string> AddGemToProject(const QString& gemPath, const QString& projectPath) override;
AZ::Outcome<void, AZStd::string> RemoveGemFromProject(const QString& gemPath, const QString& projectPath) override;
// ProjectTemplate
AZ::Outcome<QVector<ProjectTemplateInfo>> GetProjectTemplates() override;
@ -58,6 +59,7 @@ namespace O3DE::ProjectManager
private:
AZ_DISABLE_COPY_MOVE(PythonBindings);
AZ::Outcome<void, AZStd::string> ExecuteWithLockErrorHandling(AZStd::function<void()> executionCallback);
bool ExecuteWithLock(AZStd::function<void()> executionCallback);
GemInfo GemInfoFromPath(pybind11::handle path);
ProjectInfo ProjectInfoFromPath(pybind11::handle path);
@ -68,6 +70,7 @@ namespace O3DE::ProjectManager
AZ::IO::FixedMaxPath m_enginePath;
pybind11::handle m_engineTemplate;
AZStd::recursive_mutex m_lock;
pybind11::handle m_cmake;
pybind11::handle m_register;
pybind11::handle m_manifest;
pybind11::handle m_enableGemProject;

@ -57,13 +57,21 @@ namespace O3DE::ProjectManager
* @param path the absolute path to the Gem
* @return an outcome with GemInfo on success
*/
virtual AZ::Outcome<GemInfo> GetGem(const QString& path) = 0;
virtual AZ::Outcome<GemInfo> GetGemInfo(const QString& path) = 0;
/**
* Get info about all known Gems
* @return an outcome with GemInfos on success
* Get all available gem infos. This concatenates gems registered by the engine and the project.
* @param path The absolute path to the project.
* @return A list of gem infos.
*/
virtual AZ::Outcome<QVector<GemInfo>> GetGems() = 0;
virtual AZ::Outcome<QVector<GemInfo>, AZStd::string> GetAllGemInfos(const QString& projectPath) = 0;
/**
* Get a list of all enabled gem names for a given project.
* @param[in] projectPath Absolute file path to the project.
* @return A list of gem names of all the enabled gems for a given project or a error message on failure.
*/
virtual AZ::Outcome<QVector<AZStd::string>, AZStd::string> GetEnabledGemNames(const QString& projectPath) = 0;
// Projects
@ -114,17 +122,17 @@ namespace O3DE::ProjectManager
* Add a gem to a project
* @param gemPath the absolute path to the gem
* @param projectPath the absolute path to the project
* @return true on success, false on failure
* @return An outcome with the success flag as well as an error message in case of a failure.
*/
virtual bool AddGemToProject(const QString& gemPath, const QString& projectPath) = 0;
virtual AZ::Outcome<void, AZStd::string> AddGemToProject(const QString& gemPath, const QString& projectPath) = 0;
/**
* Remove gem to a project
* @param gemPath the absolute path to the gem
* @param projectPath the absolute path to the project
* @return true on success, false on failure
* @return An outcome with the success flag as well as an error message in case of a failure.
*/
virtual bool RemoveGemFromProject(const QString& gemPath, const QString& projectPath) = 0;
virtual AZ::Outcome<void, AZStd::string> RemoveGemFromProject(const QString& gemPath, const QString& projectPath) = 0;
// Project Templates

Loading…
Cancel
Save