123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include <PythonLogSymbolsComponent.h>
- #include <Source/PythonCommon.h>
- #include <Source/PythonUtility.h>
- #include <Source/PythonTypeCasters.h>
- #include <Source/PythonProxyBus.h>
- #include <Source/PythonProxyObject.h>
- #include <pybind11/embed.h>
- #include <AzCore/PlatformDef.h>
- #include <AzCore/RTTI/AttributeReader.h>
- #include <AzCore/RTTI/BehaviorContext.h>
- #include <AzCore/IO/SystemFile.h>
- #include <AzCore/IO/FileIO.h>
- #include <AzCore/std/sort.h>
- #include <AzCore/std/smart_ptr/make_shared.h>
- #include <AzCore/Serialization/Utils.h>
- #include <AzFramework/CommandLine/CommandRegistrationBus.h>
- #include <AzFramework/StringFunc/StringFunc.h>
- namespace EditorPythonBindings
- {
- namespace Internal
- {
- struct FileHandle final
- {
- explicit FileHandle(AZ::IO::HandleType handle)
- : m_handle(handle)
- {}
- ~FileHandle()
- {
- Close();
- }
- void Close()
- {
- if (IsValid())
- {
- AZ::IO::FileIOBase::GetInstance()->Close(m_handle);
- }
- m_handle = AZ::IO::InvalidHandle;
- }
- bool IsValid() const
- {
- return m_handle != AZ::IO::InvalidHandle;
- }
- operator AZ::IO::HandleType() const { return m_handle; }
- AZ::IO::HandleType m_handle;
- };
- void Indent(int level, AZStd::string& buffer)
- {
- buffer.append(level * 4, ' ');
- }
- void AddCommentBlock(int level, const AZStd::string& comment, AZStd::string& buffer)
- {
- Indent(level, buffer);
- AzFramework::StringFunc::Append(buffer, "\"\"\"\n");
- Indent(level, buffer);
- AzFramework::StringFunc::Append(buffer, comment.c_str());
- Indent(level, buffer);
- AzFramework::StringFunc::Append(buffer, "\"\"\"\n");
- }
- }
- void PythonLogSymbolsComponent::Reflect(AZ::ReflectContext* context)
- {
- if (auto&& serialize = azrtti_cast<AZ::SerializeContext*>(context))
- {
- serialize->Class<PythonLogSymbolsComponent, AZ::Component>()
- ->Version(0);
- }
- }
- void PythonLogSymbolsComponent::Activate()
- {
- PythonSymbolEventBus::Handler::BusConnect();
- EditorPythonBindingsNotificationBus::Handler::BusConnect();
- AZ::Interface<AzToolsFramework::EditorPythonConsoleInterface>::Register(this);
- if (PythonSymbolEventBus::GetTotalNumOfEventHandlers() > 1)
- {
- OnPostInitialize();
- }
- }
- void PythonLogSymbolsComponent::Deactivate()
- {
- AZ::Interface<AzToolsFramework::EditorPythonConsoleInterface>::Unregister(this);
- PythonSymbolEventBus::Handler::BusDisconnect();
- EditorPythonBindingsNotificationBus::Handler::BusDisconnect();
- }
- void PythonLogSymbolsComponent::OnPostInitialize()
- {
- m_basePath.clear();
- if (AZ::IO::FileIOBase::GetInstance()->GetAlias("@user@"))
- {
- // clear out the previous symbols path
- char pythonSymbolsPath[AZ_MAX_PATH_LEN];
- AZ::IO::FileIOBase::GetInstance()->ResolvePath("@user@/python_symbols", pythonSymbolsPath, AZ_MAX_PATH_LEN);
- AZ::IO::FileIOBase::GetInstance()->CreatePath(pythonSymbolsPath);
- m_basePath = pythonSymbolsPath;
- }
- EditorPythonBindingsNotificationBus::Handler::BusDisconnect();
- PythonSymbolEventBus::ExecuteQueuedEvents();
- }
- void PythonLogSymbolsComponent::WriteMethod(AZ::IO::HandleType handle, AZStd::string_view methodName, const AZ::BehaviorMethod& behaviorMethod, const AZ::BehaviorClass* behaviorClass)
- {
- AZStd::string buffer;
- int indentLevel = 0;
- AZStd::vector<AZStd::string> pythonArgs;
- const bool isMemberLike = behaviorClass ? PythonProxyObjectManagement::IsMemberLike(behaviorMethod, behaviorClass->m_typeId) : false;
- if (isMemberLike)
- {
- indentLevel = 1;
- Internal::Indent(indentLevel, buffer);
- pythonArgs.emplace_back("self");
- }
- else
- {
- indentLevel = 0;
- }
- AzFramework::StringFunc::Append(buffer, "def ");
- if (isMemberLike || !behaviorClass)
- {
- AzFramework::StringFunc::Append(buffer, methodName.data());
- }
- else
- {
- AzFramework::StringFunc::Append(buffer, behaviorClass->m_name.c_str());
- AzFramework::StringFunc::Append(buffer, "_");
- AzFramework::StringFunc::Append(buffer, methodName.data());
- }
- AzFramework::StringFunc::Append(buffer, "(");
- AZStd::string bufferArg;
- for (size_t argIndex = 0; argIndex < behaviorMethod.GetNumArguments(); ++argIndex)
- {
- const AZStd::string* name = behaviorMethod.GetArgumentName(argIndex);
- if (!name || name->empty())
- {
- bufferArg = AZStd::string::format(" arg%zu", argIndex);
- }
- else
- {
- bufferArg = *name;
- }
- AZStd::string type = FetchPythonTypeName(*behaviorMethod.GetArgument(argIndex));
- if (!type.empty())
- {
- AzFramework::StringFunc::Append(bufferArg, ": ");
- AzFramework::StringFunc::Append(bufferArg, type.data());
- }
- pythonArgs.push_back(bufferArg);
- bufferArg.clear();
- }
- AZStd::string argsList;
- AzFramework::StringFunc::Join(buffer, pythonArgs.begin(), pythonArgs.end(), ",");
- AzFramework::StringFunc::Append(buffer, ") -> None:\n");
- Internal::Indent(indentLevel + 1, buffer);
- AzFramework::StringFunc::Append(buffer, "pass\n\n");
- AZ::IO::FileIOBase::GetInstance()->Write(handle, buffer.c_str(), buffer.size());
- }
- void PythonLogSymbolsComponent::WriteProperty(AZ::IO::HandleType handle, int level, AZStd::string_view propertyName, const AZ::BehaviorProperty& property, [[maybe_unused]] const AZ::BehaviorClass * behaviorClass)
- {
- AZStd::string buffer;
- // property declaration
- Internal::Indent(level, buffer);
- AzFramework::StringFunc::Append(buffer, "@property\n");
- Internal::Indent(level, buffer);
- AzFramework::StringFunc::Append(buffer, "def ");
- AzFramework::StringFunc::Append(buffer, propertyName.data());
- AzFramework::StringFunc::Append(buffer, "(self) -> ");
- AZStd::string_view type = FetchPythonTypeAndTraits(property.GetTypeId(), AZ::BehaviorParameter::TR_NONE);
- if (type.empty())
- {
- AzFramework::StringFunc::Append(buffer, "Any");
- }
- else
- {
- AzFramework::StringFunc::Append(buffer, type.data());
- }
- AzFramework::StringFunc::Append(buffer, ":\n");
- Internal::Indent(level + 1, buffer);
- AzFramework::StringFunc::Append(buffer, "pass\n\n");
- AZ::IO::FileIOBase::GetInstance()->Write(handle, buffer.c_str(), buffer.size());
- }
- void PythonLogSymbolsComponent::LogClass(const AZStd::string moduleName, const AZ::BehaviorClass* behaviorClass)
- {
- LogClassWithName(moduleName, behaviorClass, behaviorClass->m_name.c_str());
- }
- void PythonLogSymbolsComponent::LogClassWithName(const AZStd::string moduleName, const AZ::BehaviorClass* behaviorClass, const AZStd::string className)
- {
- auto fileHandle = OpenModuleAt(moduleName);
- if (fileHandle->IsValid())
- {
- // Behavior Class types with member methods and properties
- AZStd::string buffer;
- AzFramework::StringFunc::Append(buffer, "class ");
- AzFramework::StringFunc::Append(buffer, className.data());
- AzFramework::StringFunc::Append(buffer, ":\n");
- AZ::IO::FileIOBase::GetInstance()->Write(*fileHandle, buffer.c_str(), buffer.size());
- buffer.clear();
- if (behaviorClass->m_methods.empty() && behaviorClass->m_properties.empty())
- {
- AZStd::string body{ " # behavior class type with no methods or properties \n" };
- Internal::Indent(1, body);
- AzFramework::StringFunc::Append(body, "pass\n\n");
- AZ::IO::FileIOBase::GetInstance()->Write(*fileHandle, body.c_str(), body.size());
- }
- else
- {
- for (const auto& properyEntry : behaviorClass->m_properties)
- {
- AZ::BehaviorProperty* property = properyEntry.second;
- AZStd::string propertyName{ properyEntry.first };
- Scope::FetchScriptName(property->m_attributes, propertyName);
- WriteProperty(*fileHandle, 1, propertyName, *property, behaviorClass);
- }
- for (const auto& methodEntry : behaviorClass->m_methods)
- {
- AZ::BehaviorMethod* method = methodEntry.second;
- if (method && PythonProxyObjectManagement::IsMemberLike(*method, behaviorClass->m_typeId))
- {
- AZStd::string baseMethodName{ methodEntry.first };
- Scope::FetchScriptName(method->m_attributes, baseMethodName);
- WriteMethod(*fileHandle, baseMethodName, *method, behaviorClass);
- }
- }
- }
- }
- }
- void PythonLogSymbolsComponent::LogClassMethod(
- const AZStd::string moduleName,
- const AZStd::string globalMethodName,
- [[maybe_unused]] const AZ::BehaviorClass* behaviorClass,
- const AZ::BehaviorMethod* behaviorMethod)
- {
- auto fileHandle = OpenModuleAt(moduleName);
- if (fileHandle->IsValid())
- {
- WriteMethod(*fileHandle, globalMethodName, *behaviorMethod, nullptr);
- }
- }
- void PythonLogSymbolsComponent::LogBus(const AZStd::string moduleName, const AZStd::string busName, const AZ::BehaviorEBus* behaviorEBus)
- {
- if (behaviorEBus->m_events.empty())
- {
- return;
- }
- auto fileHandle = OpenModuleAt(moduleName);
- if (fileHandle->IsValid())
- {
- AZStd::string buffer;
- const auto& eventSenderEntry = behaviorEBus->m_events.begin();
- const AZ::BehaviorEBusEventSender& sender = eventSenderEntry->second;
- AzFramework::StringFunc::Append(buffer, "def ");
- AzFramework::StringFunc::Append(buffer, busName.data());
- bool isBroadcast = false;
- if (sender.m_event)
- {
- AZStd::string addressType = FetchPythonTypeName(behaviorEBus->m_idParam);
- if (addressType.empty())
- {
- AzFramework::StringFunc::Append(buffer, "(busCallType: int, busEventName: str, address: Any, args: Tuple[Any])");
- }
- else
- {
- AzFramework::StringFunc::Append(buffer, "(busCallType: int, busEventName: str, address: ");
- AzFramework::StringFunc::Append(buffer, AZStd::string::format(AZ_STRING_FORMAT, AZ_STRING_ARG(addressType)).c_str());
- AzFramework::StringFunc::Append(buffer, ", args: Tuple[Any])");
- }
- }
- else
- {
- AzFramework::StringFunc::Append(buffer, "(busCallType: int, busEventName: str, args: Tuple[Any])");
- isBroadcast = true;
- }
- AzFramework::StringFunc::Append(buffer, " -> Any:\n");
- AZ::IO::FileIOBase::GetInstance()->Write(*fileHandle, buffer.c_str(), buffer.size());
- buffer.clear();
- auto eventInfoBuilder = [this](const AZ::BehaviorMethod* behaviorMethod, AZStd::string& inOutStrBuffer, [[maybe_unused]] TypeMap& typeCache)
- {
- AzFramework::StringFunc::Append(inOutStrBuffer, "(");
- size_t numArguments = behaviorMethod->GetNumArguments();
- const AZ::BehaviorParameter* busIdArg = behaviorMethod->GetBusIdArgument();
- for (size_t i = 0; i < numArguments; ++i)
- {
- const AZ::BehaviorParameter* argParam = behaviorMethod->GetArgument(i);
- if (argParam == busIdArg)
- {
- // address argument is part of the bus call, skip from event argument list
- continue;
- }
- AZStd::string_view argType = FetchPythonTypeAndTraits(argParam->m_typeId, argParam->m_traits);
- AzFramework::StringFunc::Append(inOutStrBuffer, argType.data());
- if (i < (numArguments - 1))
- {
- AzFramework::StringFunc::Append(inOutStrBuffer, ", ");
- }
- }
- const AZ::BehaviorParameter* resultParam = behaviorMethod->GetResult();
- AZStd::string returnType = FetchPythonTypeName(*resultParam);
- AZStd::string returnTypeStr = AZStd::string::format(") -> " AZ_STRING_FORMAT" \n", AZ_STRING_ARG(returnType));
- AzFramework::StringFunc::Append(inOutStrBuffer, returnTypeStr.c_str());
- };
- // record the event names the behavior can send, their parameters and return type
- AZStd::string comment = behaviorEBus->m_toolTip;
- if (!behaviorEBus->m_events.empty())
- {
- AzFramework::StringFunc::Append(comment, "The following bus Call types, Event names and Argument types are supported by this bus:\n");
- AZStd::vector<AZStd::string> events;
- for (const auto& eventSenderEntry2 : behaviorEBus->m_events)
- {
- const AZStd::string& eventName = eventSenderEntry2.first;
- AZStd::string eventNameStr = AZStd::string::format("'%s', ", eventName.c_str());
- // prefer m_event info over m_broadcast
- if (!isBroadcast && eventSenderEntry2.second.m_event != nullptr)
- {
- AZStd::string eventInfo;
- AzFramework::StringFunc::Append(eventInfo, "bus.Event, ");
- AzFramework::StringFunc::Append(eventInfo, eventNameStr.c_str());
- eventInfoBuilder(eventSenderEntry2.second.m_event, eventInfo, m_typeCache);
- events.push_back(eventInfo);
- }
- else if (isBroadcast && eventSenderEntry2.second.m_broadcast != nullptr)
- {
- AZStd::string eventInfo;
- AzFramework::StringFunc::Append(eventInfo, "bus.Broadcast, ");
- AzFramework::StringFunc::Append(eventInfo, eventNameStr.c_str());
- eventInfoBuilder(eventSenderEntry2.second.m_broadcast, eventInfo, m_typeCache);
- events.push_back(eventInfo);
- }
- else
- {
- AZ_Warning("python", false, "Event %s is expected to have valid event information.", eventName.c_str());
- }
- }
- AZStd::sort(events.begin(), events.end());
- for (auto& eventInfo : events)
- {
- Internal::Indent(1, comment);
- AzFramework::StringFunc::Append(comment, eventInfo.c_str());
- }
- }
- Internal::AddCommentBlock(1, comment, buffer);
- Internal::Indent(1, buffer);
- AzFramework::StringFunc::Append(buffer, "pass\n\n");
- AZ::IO::FileIOBase::GetInstance()->Write(*fileHandle, buffer.c_str(), buffer.size());
- // can the EBus create & destroy a handler?
- if (behaviorEBus->m_createHandler && behaviorEBus->m_destroyHandler)
- {
- buffer.clear();
- AzFramework::StringFunc::Append(buffer, "def ");
- AzFramework::StringFunc::Append(buffer, busName.data());
- AzFramework::StringFunc::Append(buffer, "Handler() -> None:\n");
- Internal::Indent(1, buffer);
- AzFramework::StringFunc::Append(buffer, "pass\n\n");
- AZ::IO::FileIOBase::GetInstance()->Write(*fileHandle, buffer.c_str(), buffer.size());
- }
- }
- }
- void PythonLogSymbolsComponent::LogGlobalMethod(const AZStd::string moduleName, const AZStd::string methodName, const AZ::BehaviorMethod* behaviorMethod)
- {
- auto fileHandle = OpenModuleAt(moduleName);
- if (fileHandle->IsValid())
- {
- WriteMethod(*fileHandle, methodName, *behaviorMethod, nullptr);
- }
- auto functionMapIt = m_globalFunctionMap.find(moduleName);
- if (functionMapIt == m_globalFunctionMap.end())
- {
- auto moduleSetIt = m_moduleSet.find(moduleName);
- if (moduleSetIt != m_moduleSet.end())
- {
- m_globalFunctionMap[*moduleSetIt] = { AZStd::make_pair(behaviorMethod, methodName) };
- }
- }
- else
- {
- GlobalFunctionList& globalFunctionList = functionMapIt->second;
- globalFunctionList.emplace_back(AZStd::make_pair(behaviorMethod, methodName));
- }
- }
- void PythonLogSymbolsComponent::LogGlobalProperty(
- const AZStd::string moduleName,
- const AZStd::string propertyName,
- const AZ::BehaviorProperty* behaviorProperty)
- {
- if (!behaviorProperty->m_getter || !behaviorProperty->m_getter->GetResult())
- {
- return;
- }
- auto fileHandle = OpenModuleAt(moduleName);
- if (fileHandle->IsValid())
- {
- AZStd::string buffer;
- // add header
- AZ::u64 filesize = 0;
- AZ::IO::FileIOBase::GetInstance()->Size(fileHandle->m_handle, filesize);
- if (filesize == 0)
- {
- AzFramework::StringFunc::Append(buffer, "class property():\n");
- }
- Internal::Indent(1, buffer);
- AzFramework::StringFunc::Append(buffer, propertyName.data());
- AzFramework::StringFunc::Append(buffer, ": ClassVar[");
- const AZ::BehaviorParameter* resultParam = behaviorProperty->m_getter->GetResult();
- AZStd::string_view type = FetchPythonTypeAndTraits(resultParam->m_typeId, resultParam->m_traits);
- if (type.empty())
- {
- AzFramework::StringFunc::Append(buffer, "Any");
- }
- else
- {
- AzFramework::StringFunc::Append(buffer, type.data());
- }
- AzFramework::StringFunc::Append(buffer, "] = None");
- if (behaviorProperty->m_getter && !behaviorProperty->m_setter)
- {
- AzFramework::StringFunc::Append(buffer, " # read only");
- }
- AzFramework::StringFunc::Append(buffer, "\n");
- AZ::IO::FileIOBase::GetInstance()->Write(*fileHandle, buffer.c_str(), buffer.size());
- }
- }
- void PythonLogSymbolsComponent::Finalize()
- {
- auto fileHandle = OpenInitFileAt("azlmbr.bus");
- if (fileHandle->IsValid())
- {
- AZStd::string buffer;
- AzFramework::StringFunc::Append(buffer, "# Bus dispatch types:\n");
- AzFramework::StringFunc::Append(buffer, "from typing_extensions import Final\n");
- AzFramework::StringFunc::Append(buffer, "Broadcast: Final[int] = 0\n");
- AzFramework::StringFunc::Append(buffer, "Event: Final[int] = 1\n");
- AzFramework::StringFunc::Append(buffer, "QueueBroadcast: Final[int] = 2\n");
- AzFramework::StringFunc::Append(buffer, "QueueEvent: Final[int] = 3\n");
- AZ::IO::FileIOBase::GetInstance()->Write(*fileHandle, buffer.c_str(), buffer.size());
- }
- fileHandle->Close();
- }
- void PythonLogSymbolsComponent::GetModuleList(AZStd::vector<AZStd::string_view>& moduleList) const
- {
- moduleList.clear();
- moduleList.reserve(m_moduleSet.size());
- AZStd::copy(m_moduleSet.begin(), m_moduleSet.end(), AZStd::back_inserter(moduleList));
- }
- void PythonLogSymbolsComponent::GetGlobalFunctionList(GlobalFunctionCollection& globalFunctionCollection) const
- {
- globalFunctionCollection.clear();
- for (const auto& globalFunctionMapEntry : m_globalFunctionMap)
- {
- const AZStd::string_view moduleName{ globalFunctionMapEntry.first };
- const GlobalFunctionList& moduleFunctionList = globalFunctionMapEntry.second;
- AZStd::transform(moduleFunctionList.begin(), moduleFunctionList.end(), AZStd::back_inserter(globalFunctionCollection), [moduleName](auto& entry) -> auto
- {
- const GlobalFunctionEntry& globalFunctionEntry = entry;
- const AZ::BehaviorMethod* behaviorMethod = entry.first;
- return AzToolsFramework::EditorPythonConsoleInterface::GlobalFunction({ moduleName, globalFunctionEntry.second, behaviorMethod->m_debugDescription });
- });
- }
- }
- AZStd::string PythonLogSymbolsComponent::FetchListType(const AZ::TypeId& typeId)
- {
- AZStd::string type = "list";
- AZStd::vector<AZ::Uuid> typeList = AZ::Utils::GetContainedTypes(typeId);
- if (!typeList.empty())
- {
- // trait info not available, so defaulting to TR_NONE
- AZStd::string_view itemType = FetchPythonTypeAndTraits(typeList[0], AZ::BehaviorParameter::TR_NONE);
- if (!itemType.empty())
- {
- type = AZStd::string::format("List[" AZ_STRING_FORMAT "]", AZ_STRING_ARG(itemType));
- }
- }
- return type;
- }
- AZStd::string PythonLogSymbolsComponent::FetchMapType(const AZ::TypeId& typeId)
- {
- AZStd::string type = "dict";
- AZStd::vector<AZ::Uuid> typeList = AZ::Utils::GetContainedTypes(typeId);
- if (!typeList.empty())
- {
- // trait info not available, so defaulting to TR_NONE
- AZStd::string_view kType = FetchPythonTypeAndTraits(typeList[0], AZ::BehaviorParameter::TR_NONE);
- AZStd::string_view vType = FetchPythonTypeAndTraits(typeList[1], AZ::BehaviorParameter::TR_NONE);
- if (!kType.empty() && !vType.empty())
- {
- type = AZStd::string::format("Dict[" AZ_STRING_FORMAT ", " AZ_STRING_FORMAT "]",
- AZ_STRING_ARG(kType), AZ_STRING_ARG(vType));
- }
- }
- return type;
- }
- AZStd::string PythonLogSymbolsComponent::FetchOutcomeType(const AZ::TypeId& typeId)
- {
- AZStd::string type = "Outcome";
- AZStd::pair<AZ::Uuid, AZ::Uuid> outcomeTypes = AZ::Utils::GetOutcomeTypes(typeId);
- // trait info not available, so defaulting to TR_NONE
- AZStd::string_view valueT = FetchPythonTypeAndTraits(outcomeTypes.first, AZ::BehaviorParameter::TR_NONE);
- AZStd::string_view errorT = FetchPythonTypeAndTraits(outcomeTypes.second, AZ::BehaviorParameter::TR_NONE);
- if (!valueT.empty() && !errorT.empty())
- {
- type = AZStd::string::format("Outcome[" AZ_STRING_FORMAT ", " AZ_STRING_FORMAT "]",
- AZ_STRING_ARG(valueT), AZ_STRING_ARG(errorT));
- }
- return type;
- }
- AZStd::string PythonLogSymbolsComponent::TypeNameFallback(const AZ::TypeId& typeId)
- {
- // fall back to class data m_name
- AZ::SerializeContext* serializeContext = nullptr;
- AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationRequests::GetSerializeContext);
- if (serializeContext)
- {
- auto classData = serializeContext->FindClassData(typeId);
- if (classData)
- {
- return classData->m_name;
- }
- }
- return "";
- }
- AZStd::string_view PythonLogSymbolsComponent::FetchPythonTypeAndTraits(const AZ::TypeId& typeId, AZ::u32 traits)
- {
- if (m_typeCache.find(typeId) == m_typeCache.end())
- {
- AZStd::string type;
- if (AZ::AzTypeInfo<AZStd::string_view>::Uuid() == typeId ||
- AZ::AzTypeInfo<AZStd::string>::Uuid() == typeId)
- {
- type = "str";
- }
- else if (AZ::AzTypeInfo<char>::Uuid() == typeId &&
- traits & AZ::BehaviorParameter::TR_POINTER &&
- traits & AZ::BehaviorParameter::TR_CONST)
- {
- type = "str";
- }
- else if (AZ::AzTypeInfo<float>::Uuid() == typeId ||
- AZ::AzTypeInfo<double>::Uuid() == typeId)
- {
- type = "float";
- }
- else if (AZ::AzTypeInfo<bool>::Uuid() == typeId)
- {
- type = "bool";
- }
- else if (AZ::AzTypeInfo<AZ::s8>::Uuid() == typeId ||
- AZ::AzTypeInfo<AZ::u8>::Uuid() == typeId ||
- AZ::AzTypeInfo<AZ::s16>::Uuid() == typeId ||
- AZ::AzTypeInfo<AZ::u16>::Uuid() == typeId ||
- AZ::AzTypeInfo<AZ::s32>::Uuid() == typeId ||
- AZ::AzTypeInfo<AZ::u32>::Uuid() == typeId ||
- AZ::AzTypeInfo<AZ::s64>::Uuid() == typeId ||
- AZ::AzTypeInfo<AZ::u64>::Uuid() == typeId)
- {
- type = "int";
- }
- else if (AZ::AzTypeInfo<AZStd::vector<AZ::u8>>::Uuid() == typeId)
- {
- type = "bytes";
- }
- else if (AZ::AzTypeInfo<AZStd::any>::Uuid() == typeId)
- {
- type = "object";
- }
- else if (AZ::AzTypeInfo<void>::Uuid() == typeId)
- {
- type = "None";
- }
- else if (AZ::Utils::IsVectorContainerType(typeId))
- {
- type = FetchListType(typeId);
- }
- else if (AZ::Utils::IsMapContainerType(typeId))
- {
- type = FetchMapType(typeId);
- }
- else if (AZ::Utils::IsOutcomeType(typeId))
- {
- type = FetchOutcomeType(typeId);
- }
- else
- {
- type = TypeNameFallback(typeId);
- }
- m_typeCache[typeId] = type;
- }
- return m_typeCache[typeId];
- }
- AZStd::string PythonLogSymbolsComponent::FetchPythonTypeName(const AZ::BehaviorParameter& param)
- {
- AZStd::string pythonType = FetchPythonTypeAndTraits(param.m_typeId, param.m_traits);
- if (pythonType.empty())
- {
- if (AZ::StringFunc::Equal(param.m_name, "void"))
- {
- return "None";
- }
- return param.m_name;
- }
- return pythonType;
- }
- PythonLogSymbolsComponent::FileHandlePtr PythonLogSymbolsComponent::OpenInitFileAt(AZStd::string_view moduleName)
- {
- if (m_basePath.empty())
- {
- return AZStd::make_shared<Internal::FileHandle>(AZ::IO::InvalidHandle);
- }
- // creates the __init__.py file in this path
- AZStd::string modulePath(moduleName);
- AzFramework::StringFunc::Replace(modulePath, ".", AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING);
- AZStd::string initFile;
- AzFramework::StringFunc::Path::Join(m_basePath.c_str(), modulePath.c_str(), initFile);
- AzFramework::StringFunc::Append(initFile, AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING);
- AzFramework::StringFunc::Append(initFile, "__init__.pyi");
-
- AZ::IO::OpenMode openMode = AZ::IO::OpenMode::ModeText | AZ::IO::OpenMode::ModeWrite;
- AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
- AZ::IO::Result result = AZ::IO::FileIOBase::GetInstance()->Open(initFile.c_str(), openMode, fileHandle);
- if (result)
- {
- return AZStd::make_shared<Internal::FileHandle>(fileHandle);
- }
- return AZStd::make_shared<Internal::FileHandle>(AZ::IO::InvalidHandle);
- }
- PythonLogSymbolsComponent::FileHandlePtr PythonLogSymbolsComponent::OpenModuleAt(AZStd::string_view moduleName)
- {
- if (m_basePath.empty())
- {
- return AZStd::make_shared<Internal::FileHandle>(AZ::IO::InvalidHandle);
- }
- bool resetFile = false;
- if (m_moduleSet.find(moduleName) == m_moduleSet.end())
- {
- m_moduleSet.insert(moduleName);
- resetFile = true;
- }
- AZStd::vector<AZStd::string> moduleParts;
- AzFramework::StringFunc::Tokenize(moduleName.data(), moduleParts, '.');
- // prepare target PYI file
- AZStd::string targetModule = moduleParts.back();
- moduleParts.pop_back();
- AzFramework::StringFunc::Append(targetModule, ".pyi");
- // create an __init__.py file as the base module path
- AZStd::string initModule;
- AzFramework::StringFunc::Join(initModule, moduleParts.begin(), moduleParts.end(), '.');
- OpenInitFileAt(initModule);
- AZStd::string modulePath;
- AzFramework::StringFunc::Append(modulePath, m_basePath.c_str());
- AzFramework::StringFunc::Append(modulePath, AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING);
- AzFramework::StringFunc::Join(modulePath, moduleParts.begin(), moduleParts.end(), AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING);
- // prepare the path
- AZ::IO::FileIOBase::GetInstance()->CreatePath(modulePath.c_str());
- // assemble the file path
- AzFramework::StringFunc::Append(modulePath, AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING);
- AzFramework::StringFunc::Append(modulePath, targetModule.c_str());
- AzFramework::StringFunc::AssetDatabasePath::Normalize(modulePath);
- AZ::IO::OpenMode openMode = AZ::IO::OpenMode::ModeText;
- if (AZ::IO::SystemFile::Exists(modulePath.c_str()))
- {
- openMode |= (resetFile) ? AZ::IO::OpenMode::ModeWrite : AZ::IO::OpenMode::ModeAppend;
- }
- else
- {
- openMode |= AZ::IO::OpenMode::ModeWrite;
- }
- AZ::IO::HandleType fileHandle = AZ::IO::InvalidHandle;
- AZ::IO::Result result = AZ::IO::FileIOBase::GetInstance()->Open(modulePath.c_str(), openMode, fileHandle);
- if (result)
- {
- return AZStd::make_shared<Internal::FileHandle>(fileHandle);
- }
- return AZStd::make_shared<Internal::FileHandle>(AZ::IO::InvalidHandle);
- }
- }
|