Explorar el Código

Initial Python bindings pass for ProjectManager

Adds dependency on pybind and interface to call o3de.py functions from c++
Alex Peterson hace 4 años
padre
commit
26d886792d
Se han modificado 22 ficheros con 552 adiciones y 13 borrados
  1. 15 0
      Code/Tools/ProjectManager/CMakeLists.txt
  2. 15 0
      Code/Tools/ProjectManager/Platform/Common/Clang/projectmanager_clang.cmake
  3. 15 0
      Code/Tools/ProjectManager/Platform/Common/MSVC/projectmanager_msvc.cmake
  4. 1 0
      Code/Tools/ProjectManager/Platform/Linux/PAL_linux.cmake
  5. 14 0
      Code/Tools/ProjectManager/Platform/Linux/PAL_linux_files.cmake
  6. 42 0
      Code/Tools/ProjectManager/Platform/Linux/Python_linux.cpp
  7. 14 0
      Code/Tools/ProjectManager/Platform/Mac/PAL_mac_files.cmake
  8. 43 0
      Code/Tools/ProjectManager/Platform/Mac/Python_mac.cpp
  9. 5 0
      Code/Tools/ProjectManager/Platform/Windows/PAL_windows.cmake
  10. 14 0
      Code/Tools/ProjectManager/Platform/Windows/PAL_windows_files.cmake
  11. 43 0
      Code/Tools/ProjectManager/Platform/Windows/Python_windows.cpp
  12. 1 0
      Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h
  13. 24 0
      Code/Tools/ProjectManager/Source/ProjectInfo.cpp
  14. 36 0
      Code/Tools/ProjectManager/Source/ProjectInfo.h
  15. 3 0
      Code/Tools/ProjectManager/Source/ProjectManagerWindow.cpp
  16. 2 1
      Code/Tools/ProjectManager/Source/ProjectManagerWindow.h
  17. 5 0
      Code/Tools/ProjectManager/Source/ProjectsHome.cpp
  18. 155 0
      Code/Tools/ProjectManager/Source/PythonBindings.cpp
  19. 41 0
      Code/Tools/ProjectManager/Source/PythonBindings.h
  20. 39 0
      Code/Tools/ProjectManager/Source/PythonBindingsInterface.h
  21. 20 12
      Code/Tools/ProjectManager/Source/main.cpp
  22. 5 0
      Code/Tools/ProjectManager/project_manager_files.cmake

+ 15 - 0
Code/Tools/ProjectManager/CMakeLists.txt

@@ -13,6 +13,13 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS)
     return()
 endif()
 
+# This will set python_package_name to whatever the package 'Python' is associated with
+ly_get_package_association(Python python_package_name)
+if (NOT python_package_name)
+    set(python_package_name "python-no-package-assocation-found")
+    message(WARNING "Python was not found in the package assocation list.  Did someone call ly_associate_package(xxxxxxx Python) ?")
+endif()
+
 ly_add_target(
     NAME ProjectManager APPLICATION
     OUTPUT_NAME o3de
@@ -22,7 +29,13 @@ ly_add_target(
     AUTORCC
     FILES_CMAKE
         project_manager_files.cmake
+        Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
+    PLATFORM_INCLUDE_FILES
         Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake
+        Platform/Common/${PAL_TRAIT_COMPILER_ID}/projectmanager_${PAL_TRAIT_COMPILER_ID_LOWERCASE}.cmake
+    COMPILE_DEFINITIONS
+        PRIVATE
+            PY_PACKAGE="${python_package_name}" 
     INCLUDE_DIRECTORIES
         PUBLIC
             .
@@ -34,6 +47,8 @@ ly_add_target(
             3rdParty::Qt::Core
             3rdParty::Qt::Concurrent
             3rdParty::Qt::Widgets
+            3rdParty::Python
+            3rdParty::pybind11
             AZ::AzCore
             AZ::AzFramework
             AZ::AzToolsFramework

+ 15 - 0
Code/Tools/ProjectManager/Platform/Common/Clang/projectmanager_clang.cmake

@@ -0,0 +1,15 @@
+#
+# 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.
+#
+
+set(LY_COMPILE_OPTIONS
+    PRIVATE
+        -fexceptions # The macro PYBIND11_EMBEDDED_MODULE uses a try catch block
+)

+ 15 - 0
Code/Tools/ProjectManager/Platform/Common/MSVC/projectmanager_msvc.cmake

@@ -0,0 +1,15 @@
+#
+# 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.
+#
+
+set(LY_COMPILE_OPTIONS
+    PRIVATE
+        /EHsc # The macro PYBIND11_EMBEDDED_MODULE uses a try catch block
+)

+ 1 - 0
Code/Tools/ProjectManager/Platform/Linux/PAL_linux.cmake

@@ -8,3 +8,4 @@
 # 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.
 #
+

+ 14 - 0
Code/Tools/ProjectManager/Platform/Linux/PAL_linux_files.cmake

@@ -0,0 +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.
+#
+
+set(FILES
+    Python_linux.cpp
+)

+ 42 - 0
Code/Tools/ProjectManager/Platform/Linux/Python_linux.cpp

@@ -0,0 +1,42 @@
+/*
+ * 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.
+ *
+ */
+
+#include <AzCore/PlatformDef.h>
+#include <AzCore/std/containers/unordered_set.h>
+#include <AzCore/IO/SystemFile.h>
+#include <AzCore/IO/Path/Path.h>
+#include <AzFramework/StringFunc/StringFunc.h>
+
+namespace Platform
+{
+    extern bool InsertPythonLibraryPath(AZStd::unordered_set<AZStd::string>& paths, const char* pythonPackage, const char* engineRoot, const char* subPath);
+
+    bool InsertPythonBinaryLibraryPaths(AZStd::unordered_set<AZStd::string>& paths, const char* pythonPackage, const char* engineRoot)
+    {
+        bool succeeded = true;
+
+        succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python/lib");
+        succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python/lib/python3.7/lib-dynload");
+        succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python/lib/python3.7");
+        succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python/lib/python3.7/site-packages");
+        return succeeded;
+    }
+
+    AZStd::string GetPythonHomePath(const char* pythonPackage, const char* engineRoot)
+    {
+        // append lib path to Python paths
+        AZ::IO::FixedMaxPath libPath = engineRoot;
+        libPath /= AZ::IO::FixedMaxPathString::format("python/runtime/%s/python", pythonPackage);
+        libPath = libPath.LexicallyNormal();
+        return libPath.String();
+    }
+}

+ 14 - 0
Code/Tools/ProjectManager/Platform/Mac/PAL_mac_files.cmake

@@ -0,0 +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.
+#
+
+set(FILES
+    Python_mac.cpp
+)

+ 43 - 0
Code/Tools/ProjectManager/Platform/Mac/Python_mac.cpp

@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ */
+
+#include <AzCore/PlatformDef.h>
+#include <AzCore/std/containers/unordered_set.h>
+#include <AzCore/IO/SystemFile.h>
+#include <AzCore/IO/Path/Path.h>
+#include <AzFramework/StringFunc/StringFunc.h>
+
+namespace Platform
+{
+    extern bool InsertPythonLibraryPath(AZStd::unordered_set<AZStd::string>& paths, const char* pythonPackage, const char* engineRoot, const char* subPath);
+
+    bool InsertPythonBinaryLibraryPaths(AZStd::unordered_set<AZStd::string>& paths, const char* pythonPackage, const char* engineRoot)
+    {
+        bool succeeded = true;
+        
+        succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/Python.framework/Versions/3.7/lib");
+        succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/Python.framework/Versions/3.7/lib/python3.7/lib-dynload");
+        succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/Python.framework/Versions/3.7/lib/python3.7");
+        succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/Python.framework/Versions/3.7/lib/python3.7/site-packages");
+
+        return succeeded;
+    }
+
+    AZStd::string GetPythonHomePath(const char* pythonPackage, const char* engineRoot)
+    {
+        // append lib path to Python paths
+        AZ::IO::FixedMaxPath libPath = engineRoot;
+        libPath /= AZ::IO::FixedMaxPathString::format("python/runtime/%s/Python.framework/Versions/3.7", pythonPackage);
+        libPath = libPath.LexicallyNormal();
+        return libPath.String();
+    }
+}

+ 5 - 0
Code/Tools/ProjectManager/Platform/Windows/PAL_windows.cmake

@@ -8,3 +8,8 @@
 # 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.
 #
+
+set(LY_COMPILE_DEFINITIONS
+    PRIVATE
+        HAVE_ROUND # defined for Windows since http://p-nand-q.com/python/building-python-33-with-vs2013.html
+)

+ 14 - 0
Code/Tools/ProjectManager/Platform/Windows/PAL_windows_files.cmake

@@ -0,0 +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.
+#
+
+set(FILES
+    Python_windows.cpp
+)

+ 43 - 0
Code/Tools/ProjectManager/Platform/Windows/Python_windows.cpp

@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *
+ */
+
+#include <AzCore/PlatformDef.h>
+#include <AzCore/std/containers/unordered_set.h>
+#include <AzCore/IO/SystemFile.h>
+#include <AzCore/IO/Path/Path.h>
+#include <AzFramework/StringFunc/StringFunc.h>
+
+namespace Platform
+{
+    extern bool InsertPythonLibraryPath(AZStd::unordered_set<AZStd::string>& paths, const char* pythonPackage, const char* engineRoot, const char* subPath);
+
+    bool InsertPythonBinaryLibraryPaths(AZStd::unordered_set<AZStd::string>& paths, const char* pythonPackage, const char* engineRoot)
+    {
+        bool succeeded = true;
+        
+        succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python");
+        succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python/lib");
+        succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python/lib/site-packages");
+        succeeded = succeeded && InsertPythonLibraryPath(paths, pythonPackage, engineRoot, "python/runtime/%s/python/DLLs");
+
+        return succeeded;
+    }
+
+    AZStd::string GetPythonHomePath(const char* pythonPackage, const char* engineRoot)
+    {
+        // append lib path to Python paths
+        AZ::IO::FixedMaxPath libPath = engineRoot;
+        libPath /= AZ::IO::FixedMaxPathString::format("python/runtime/%s/python", pythonPackage);
+        libPath = libPath.LexicallyNormal();
+        return libPath.String();
+    }
+}

+ 1 - 0
Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h

@@ -37,6 +37,7 @@ namespace O3DE::ProjectManager
 
         GemInfo(const QString& name, const QString& creator, const QString& summary, Platforms platforms, bool isAdded);
 
+        QString m_path;
         QString m_name;
         QString m_displayName;
         AZ::Uuid m_uuid;

+ 24 - 0
Code/Tools/ProjectManager/Source/ProjectInfo.cpp

@@ -0,0 +1,24 @@
+/*
+* 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.
+*
+*/
+
+#include "ProjectInfo.h"
+
+namespace O3DE::ProjectManager
+{
+    ProjectInfo::ProjectInfo(const QString& path, const QString& projectName, const QString& productName, const AZ::Uuid projectId)
+        : m_path(path)
+        , m_projectName(projectName)
+        , m_productName(productName)
+        , m_projectId(projectId)
+    {
+    }
+} // namespace O3DE::ProjectManager

+ 36 - 0
Code/Tools/ProjectManager/Source/ProjectInfo.h

@@ -0,0 +1,36 @@
+/*
+* 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.
+*
+*/
+
+#pragma once
+
+#if !defined(Q_MOC_RUN)
+#include <AzCore/Math/Uuid.h>
+#include <QString>
+#endif
+
+namespace O3DE::ProjectManager
+{
+    class ProjectInfo
+    {
+    public:
+        ProjectInfo() = default;
+        ProjectInfo(const QString& path, const QString& projectName, const QString& productName, const AZ::Uuid projectId);
+
+        // from o3de_manifest.json and o3de_projects.json
+        QString m_path;
+
+        // from project.json
+        QString m_projectName;
+        QString m_productName;
+        AZ::Uuid m_projectId;
+    };
+} // namespace O3DE::ProjectManager

+ 3 - 0
Code/Tools/ProjectManager/Source/ProjectManagerWindow.cpp

@@ -28,6 +28,8 @@ namespace O3DE::ProjectManager
     {
         m_ui->setupUi(this);
 
+        m_pythonBindings = AZStd::make_unique<PythonBindings>(engineRootPath);
+
         ConnectSlotsAndSignals();
 
         QDir rootDir = QString::fromUtf8(engineRootPath.Native().data(), aznumeric_cast<int>(engineRootPath.Native().size()));
@@ -44,6 +46,7 @@ namespace O3DE::ProjectManager
 
     ProjectManagerWindow::~ProjectManagerWindow()
     {
+        m_pythonBindings.reset();
     }
 
     void ProjectManagerWindow::BuildScreens()

+ 2 - 1
Code/Tools/ProjectManager/Source/ProjectManagerWindow.h

@@ -17,7 +17,7 @@
 #include <QMainWindow>
 #include <QStackedWidget>
 
-#include <AzCore/IO/Path/Path_fwd.h>
+#include <PythonBindings.h>
 #endif
 
 namespace Ui
@@ -52,6 +52,7 @@ namespace O3DE::ProjectManager
 
     private:
         QScopedPointer<Ui::ProjectManagerWindowClass> m_ui;
+        AZStd::unique_ptr<PythonBindings> m_pythonBindings;
     };
 
 } // namespace O3DE::ProjectManager

+ 5 - 0
Code/Tools/ProjectManager/Source/ProjectsHome.cpp

@@ -14,6 +14,8 @@
 
 #include <Source/ui_ProjectsHome.h>
 
+#include <PythonBindingsInterface.h>
+
 namespace O3DE::ProjectManager
 {
     ProjectsHome::ProjectsHome(ProjectManagerWindow* window)
@@ -23,6 +25,9 @@ namespace O3DE::ProjectManager
         m_ui->setupUi(this);
 
         ConnectSlotsAndSignals();
+
+        // example of how to get the current project name
+        ProjectInfo currentProject = PythonBindingsInterface::Get()->GetCurrentProject();
     }
 
     ProjectsHome::~ProjectsHome()

+ 155 - 0
Code/Tools/ProjectManager/Source/PythonBindings.cpp

@@ -0,0 +1,155 @@
+/*
+ * 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.
+ *
+ */
+
+#include <PythonBindings.h>
+
+// Qt defines slots, which interferes with the use here.
+#pragma push_macro("slots")
+#undef slots
+#include <Python.h>
+#include <pybind11/functional.h>
+#include <pybind11/pybind11.h>
+#include <pybind11/embed.h>
+#include <pybind11/eval.h>
+#pragma pop_macro("slots")
+
+#include <AzCore/IO/FileIO.h>
+#include <AzCore/IO/SystemFile.h>
+#include <AzCore/std/string/conversions.h>
+#include <AzCore/StringFunc/StringFunc.h>
+
+namespace Platform
+{
+    bool InsertPythonLibraryPath(
+        AZStd::unordered_set<AZStd::string>& paths, const char* pythonPackage, const char* engineRoot, const char* subPath)
+    {
+        // append lib path to Python paths
+        AZ::IO::FixedMaxPath libPath = engineRoot;
+        libPath /= AZ::IO::FixedMaxPathString::format(subPath, pythonPackage);
+        libPath = libPath.LexicallyNormal();
+        if (AZ::IO::SystemFile::Exists(libPath.c_str()))
+        {
+            paths.insert(libPath.c_str());
+            return true;
+        }
+
+        AZ_Warning("python", false, "Python library path should exist. path:%s", libPath.c_str());
+        return false;
+    }
+
+    // Implemented in each different platform's PAL implentation files, as it differs per platform.
+    AZStd::string GetPythonHomePath(const char* pythonPackage, const char* engineRoot);
+
+} // namespace Platform
+
+namespace O3DE::ProjectManager 
+{
+    PythonBindings::PythonBindings(const AZ::IO::PathView& enginePath)
+        : m_enginePath(enginePath)
+    {
+        StartPython();
+    }
+
+    PythonBindings::~PythonBindings()
+    {
+        StopPython();
+    }
+
+    bool PythonBindings::StartPython()
+    {
+        if (Py_IsInitialized())
+        {
+            AZ_Warning("python", false, "Python is already active");
+            return false;
+        }
+
+        // set PYTHON_HOME
+        AZStd::string pyBasePath = Platform::GetPythonHomePath(PY_PACKAGE, m_enginePath.c_str());
+        if (!AZ::IO::SystemFile::Exists(pyBasePath.c_str()))
+        {
+            AZ_Warning("python", false, "Python home path must exist. path:%s", pyBasePath.c_str());
+            return false;
+        }
+
+        AZStd::wstring pyHomePath;
+        AZStd::to_wstring(pyHomePath, pyBasePath);
+        Py_SetPythonHome(pyHomePath.c_str());
+
+        // display basic Python information
+        AZ_TracePrintf("python", "Py_GetVersion=%s \n", Py_GetVersion());
+        AZ_TracePrintf("python", "Py_GetPath=%ls \n", Py_GetPath());
+        AZ_TracePrintf("python", "Py_GetExecPrefix=%ls \n", Py_GetExecPrefix());
+        AZ_TracePrintf("python", "Py_GetProgramFullPath=%ls \n", Py_GetProgramFullPath());
+
+        try
+        {
+            // ignore system location for sites site-packages
+            Py_IsolatedFlag = 1; // -I - Also sets Py_NoUserSiteDirectory.  If removed PyNoUserSiteDirectory should be set.
+            Py_IgnoreEnvironmentFlag = 1; // -E
+
+            const bool initializeSignalHandlers = true;
+            pybind11::initialize_interpreter(initializeSignalHandlers);
+
+            // Acquire GIL before calling Python code
+            AZStd::lock_guard<decltype(m_lock)> lock(m_lock);
+            pybind11::gil_scoped_acquire acquire;
+
+            // Setup sys.path
+            int result = PyRun_SimpleString("import sys");
+            AZ_Warning("ProjectManagerWindow", result != -1, "Import sys failed");
+            result = PyRun_SimpleString(AZStd::string::format("sys.path.append('%s')", m_enginePath.c_str()).c_str());
+            AZ_Warning("ProjectManagerWindow", result != -1, "Append to sys path failed");
+
+            return result == 0 && !PyErr_Occurred();
+        } catch ([[maybe_unused]] const std::exception& e)
+        {
+            AZ_Warning("python", false, "Py_Initialize() failed with %s", e.what());
+            return false;
+        }
+    }
+
+    bool PythonBindings::StopPython()
+    {
+        if (Py_IsInitialized())
+        {
+            pybind11::finalize_interpreter();
+        }
+        else
+        {
+            AZ_Warning("python", false, "Did not finalize since Py_IsInitialized() was false");
+        }
+        return !PyErr_Occurred();
+    }
+
+    void PythonBindings::ExecuteWithLock(AZStd::function<void()> executionCallback)
+    {
+        AZStd::lock_guard<decltype(m_lock)> lock(m_lock);
+        pybind11::gil_scoped_release release;
+        pybind11::gil_scoped_acquire acquire;
+        executionCallback();
+    }
+
+    ProjectInfo PythonBindings::GetCurrentProject()
+    {
+        ProjectInfo project;
+
+        ExecuteWithLock([&] {
+            auto currentProjectTool = pybind11::module::import("cmake.Tools.current_project");
+            auto getCurrentProject = currentProjectTool.attr("get_current_project");
+            auto currentProject = getCurrentProject(m_enginePath.c_str());
+
+            project.m_path = currentProject.cast<std::string>().c_str();
+        });
+
+        return project; 
+    }
+}

+ 41 - 0
Code/Tools/ProjectManager/Source/PythonBindings.h

@@ -0,0 +1,41 @@
+/*
+ * 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.
+ *
+ */
+#pragma once
+
+#include <PythonBindingsInterface.h>
+#include <AzCore/IO/Path/Path.h> 
+#include <AzCore/std/parallel/semaphore.h>
+
+namespace O3DE::ProjectManager
+{
+    class PythonBindings 
+        : public PythonBindingsInterface::Registrar
+    {
+    public:
+        PythonBindings() = default;
+        PythonBindings(const AZ::IO::PathView& enginePath);
+        ~PythonBindings() override;
+
+        // PythonBindings overrides
+        ProjectInfo GetCurrentProject() override;
+
+    private:
+        AZ_DISABLE_COPY_MOVE(PythonBindings);
+
+        void ExecuteWithLock(AZStd::function<void()> executionCallback);
+        bool StartPython();
+        bool StopPython();
+
+        AZ::IO::FixedMaxPath m_enginePath;
+        AZStd::recursive_mutex m_lock;
+    };
+}

+ 39 - 0
Code/Tools/ProjectManager/Source/PythonBindingsInterface.h

@@ -0,0 +1,39 @@
+/*
+ * 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.
+ *
+ */
+#pragma once
+
+#include <AzCore/EBus/EBus.h>
+#include <AzCore/Interface/Interface.h>
+#include <AzCore/std/string/string.h>
+#include <AzCore/std/containers/vector.h>
+
+#include <GemCatalog/GemInfo.h>
+#include <ProjectInfo.h>
+
+namespace O3DE::ProjectManager
+{
+    //! Interface used to interact with the o3de cli python functions
+    class IPythonBindings
+    {
+    public:
+        AZ_RTTI(O3DE::ProjectManager::IPythonBindings, "{C2B72CA4-56A9-4601-A584-3B40E83AA17C}");
+        AZ_DISABLE_COPY_MOVE(IPythonBindings);
+
+        IPythonBindings() = default;
+        virtual ~IPythonBindings() = default;
+
+        //! Get the current project 
+        virtual ProjectInfo GetCurrentProject() = 0;
+    };
+
+    using PythonBindingsInterface = AZ::Interface<IPythonBindings>;
+} // namespace O3DE::ProjectManager

+ 20 - 12
Code/Tools/ProjectManager/Source/main.cpp

@@ -35,21 +35,29 @@ int main(int argc, char* argv[])
     QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
     AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware);
 
-    QApplication app(argc, argv);
 
-    // Need to use settings registry to get EngineRootFolder
-    AZ::IO::FixedMaxPath engineRootPath;
+    AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
+    int runSuccess = 0;
     {
-        AZ::ComponentApplication componentApplication;
-        auto settingsRegistry = AZ::SettingsRegistry::Get();
-        settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
-    }
+        QApplication app(argc, argv);
+
+        // Need to use settings registry to get EngineRootFolder
+        AZ::IO::FixedMaxPath engineRootPath;
+        {
+            AZ::ComponentApplication componentApplication;
+            auto settingsRegistry = AZ::SettingsRegistry::Get();
+            settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
+        }
 
-    AzQtComponents::StyleManager styleManager(&app);
-    styleManager.initialize(&app, engineRootPath);
+        AzQtComponents::StyleManager styleManager(&app);
+        styleManager.initialize(&app, engineRootPath);
 
-    O3DE::ProjectManager::ProjectManagerWindow window(nullptr, engineRootPath);
-    window.show();
+        O3DE::ProjectManager::ProjectManagerWindow window(nullptr, engineRootPath);
+        window.show();
+
+        runSuccess = app.exec();
+    }
+    AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
 
-    return app.exec();
+    return runSuccess;
 }

+ 5 - 0
Code/Tools/ProjectManager/project_manager_files.cmake

@@ -19,9 +19,14 @@ set(FILES
     Source/FirstTimeUse.h
     Source/FirstTimeUse.cpp
     Source/FirstTimeUse.ui
+    Source/ProjectInfo.h
+    Source/ProjectInfo.cpp
     Source/ProjectManagerWindow.h
     Source/ProjectManagerWindow.cpp
     Source/ProjectManagerWindow.ui
+    Source/PythonBindings.h
+    Source/PythonBindings.cpp
+    Source/PythonBindingsInterface.h
     Source/NewProjectSettings.h
     Source/NewProjectSettings.cpp
     Source/NewProjectSettings.ui