From c7b9dc83f58fe72162b076ba9c88d682f5d0eda6 Mon Sep 17 00:00:00 2001 From: Felix Date: Tue, 15 Jul 2025 20:20:09 +0200 Subject: [PATCH] [Python] Avoid include own type (#8625) This prevents the include of the type defined in the pyi, otherwise this leads to error message like this: error: Name XYZ already defined (possibly by an import) [no-redef] --- include/codegen/python.cc | 16 ++++++++++ include/codegen/python.h | 5 +++ src/idl_gen_python.cpp | 31 ++++++++++++++----- tests/MyGame/Example/ArrayStruct.pyi | 1 - tests/MyGame/Example/ArrayTable.pyi | 1 - tests/MyGame/Example/NestedStruct.pyi | 1 - tests/MyGame/Example/NestedUnion/Any.pyi | 1 - .../Example/NestedUnion/NestedUnionTest.pyi | 1 - tests/MyGame/Example/NestedUnion/Test.pyi | 1 - .../NestedUnion/TestSimpleTableWithEnum.pyi | 1 - tests/MyGame/Example/NestedUnion/Vec3.pyi | 1 - tests/MyGame/MonsterExtra.pyi | 1 - 12 files changed, 45 insertions(+), 16 deletions(-) diff --git a/include/codegen/python.cc b/include/codegen/python.cc index cea958891..ae6c82b94 100644 --- a/include/codegen/python.cc +++ b/include/codegen/python.cc @@ -59,5 +59,21 @@ const python::Import &python::Imports::Import(const std::string &module, imports.push_back(std::move(import)); return imports.back(); } + +const python::Import &python::Imports::Export(const std::string &module) { + python::Import import; + import.module = module; + exports.push_back(std::move(import)); + return exports.back(); +} + +const python::Import &python::Imports::Export(const std::string &module, + const std::string &name) { + python::Import import; + import.module = module; + import.name = name; + exports.push_back(std::move(import)); + return exports.back(); +} } // namespace python } // namespace flatbuffers diff --git a/include/codegen/python.h b/include/codegen/python.h index 778eacfc4..b79e37cd5 100644 --- a/include/codegen/python.h +++ b/include/codegen/python.h @@ -85,7 +85,12 @@ struct Imports { const python::Import &Import(const std::string &module, const std::string &name); + const python::Import &Export(const std::string &module); + const python::Import &Export(const std::string &module, + const std::string &name); + std::vector imports; + std::vector exports; }; } // namespace python } // namespace flatbuffers diff --git a/src/idl_gen_python.cpp b/src/idl_gen_python.cpp index 2ea1e8c15..30cfc211d 100644 --- a/src/idl_gen_python.cpp +++ b/src/idl_gen_python.cpp @@ -290,6 +290,7 @@ class PythonStubGenerator { void GenerateObjectStub(std::stringstream &stub, const StructDef *struct_def, Imports *imports) const { std::string name = namer_.ObjectType(*struct_def); + imports->Export(ModuleFor(struct_def), namer_.Type(*struct_def)); stub << "class " << name; if (version_.major != 3) stub << "(object)"; @@ -327,6 +328,7 @@ class PythonStubGenerator { void GenerateStructStub(std::stringstream &stub, const StructDef *struct_def, Imports *imports) const { std::string type = namer_.Type(*struct_def); + imports->Export(ModuleFor(struct_def), namer_.Type(*struct_def)); stub << "class " << type; if (version_.major != 3) stub << "(object)"; @@ -545,6 +547,7 @@ class PythonStubGenerator { void GenerateEnumStub(std::stringstream &stub, const EnumDef *enum_def, Imports *imports) const { stub << "class " << namer_.Type(*enum_def); + imports->Export(ModuleFor(enum_def), namer_.Type(*enum_def)); if (version_.major == 3){ imports->Import("enum", "IntEnum"); @@ -589,18 +592,32 @@ class PythonStubGenerator { } } + // Remove imports from exports + for (const Import &import : imports.exports) { + if (import.name == "") { + modules.erase(import.module); + } else { + auto search = names_by_module.find(import.module); + if (search != names_by_module.end()) { + search->second.erase(import.name); + } + } + } + for (const std::string &module : modules) { ss << "import " << module << '\n'; } for (const auto &import : names_by_module) { - ss << "from " << import.first << " import "; - size_t i = 0; - for (const std::string &name : import.second) { - if (i > 0) ss << ", "; - ss << name; - ++i; + if (!import.second.empty()) { + ss << "from " << import.first << " import "; + size_t i = 0; + for (const std::string &name : import.second) { + if (i > 0) ss << ", "; + ss << name; + ++i; + } + ss << '\n'; } - ss << '\n'; } } diff --git a/tests/MyGame/Example/ArrayStruct.pyi b/tests/MyGame/Example/ArrayStruct.pyi index 29bb83c67..6c5cbefb2 100644 --- a/tests/MyGame/Example/ArrayStruct.pyi +++ b/tests/MyGame/Example/ArrayStruct.pyi @@ -5,7 +5,6 @@ import numpy as np import flatbuffers import typing -from MyGame.Example.ArrayStruct import ArrayStruct from MyGame.Example.NestedStruct import NestedStruct, NestedStructT from MyGame.Example.TestEnum import TestEnum diff --git a/tests/MyGame/Example/ArrayTable.pyi b/tests/MyGame/Example/ArrayTable.pyi index 10f2af319..5d713418d 100644 --- a/tests/MyGame/Example/ArrayTable.pyi +++ b/tests/MyGame/Example/ArrayTable.pyi @@ -6,7 +6,6 @@ import numpy as np import flatbuffers import typing from MyGame.Example.ArrayStruct import ArrayStruct, ArrayStructT -from MyGame.Example.ArrayTable import ArrayTable uoffset: typing.TypeAlias = flatbuffers.number_types.UOffsetTFlags.py_type diff --git a/tests/MyGame/Example/NestedStruct.pyi b/tests/MyGame/Example/NestedStruct.pyi index 09e6fc689..7fe982ce3 100644 --- a/tests/MyGame/Example/NestedStruct.pyi +++ b/tests/MyGame/Example/NestedStruct.pyi @@ -5,7 +5,6 @@ import numpy as np import flatbuffers import typing -from MyGame.Example.NestedStruct import NestedStruct from MyGame.Example.TestEnum import TestEnum uoffset: typing.TypeAlias = flatbuffers.number_types.UOffsetTFlags.py_type diff --git a/tests/MyGame/Example/NestedUnion/Any.pyi b/tests/MyGame/Example/NestedUnion/Any.pyi index dee0f7f2e..f4809211b 100644 --- a/tests/MyGame/Example/NestedUnion/Any.pyi +++ b/tests/MyGame/Example/NestedUnion/Any.pyi @@ -5,7 +5,6 @@ import numpy as np import flatbuffers import typing -from MyGame.Example.NestedUnion.Any import Any from MyGame.Example.NestedUnion.TestSimpleTableWithEnum import TestSimpleTableWithEnum from MyGame.Example.NestedUnion.Vec3 import Vec3 from flatbuffers import table diff --git a/tests/MyGame/Example/NestedUnion/NestedUnionTest.pyi b/tests/MyGame/Example/NestedUnion/NestedUnionTest.pyi index 06a906d40..97a742dd9 100644 --- a/tests/MyGame/Example/NestedUnion/NestedUnionTest.pyi +++ b/tests/MyGame/Example/NestedUnion/NestedUnionTest.pyi @@ -6,7 +6,6 @@ import numpy as np import flatbuffers import typing from MyGame.Example.NestedUnion.Any import Any -from MyGame.Example.NestedUnion.NestedUnionTest import NestedUnionTest from MyGame.Example.NestedUnion.TestSimpleTableWithEnum import TestSimpleTableWithEnumT from MyGame.Example.NestedUnion.Vec3 import Vec3T from flatbuffers import table diff --git a/tests/MyGame/Example/NestedUnion/Test.pyi b/tests/MyGame/Example/NestedUnion/Test.pyi index 2fa64aa82..f1cfa321f 100644 --- a/tests/MyGame/Example/NestedUnion/Test.pyi +++ b/tests/MyGame/Example/NestedUnion/Test.pyi @@ -5,7 +5,6 @@ import numpy as np import flatbuffers import typing -from MyGame.Example.NestedUnion.Test import Test uoffset: typing.TypeAlias = flatbuffers.number_types.UOffsetTFlags.py_type diff --git a/tests/MyGame/Example/NestedUnion/TestSimpleTableWithEnum.pyi b/tests/MyGame/Example/NestedUnion/TestSimpleTableWithEnum.pyi index 117b19d53..4c8b6dff3 100644 --- a/tests/MyGame/Example/NestedUnion/TestSimpleTableWithEnum.pyi +++ b/tests/MyGame/Example/NestedUnion/TestSimpleTableWithEnum.pyi @@ -6,7 +6,6 @@ import numpy as np import flatbuffers import typing from MyGame.Example.NestedUnion.Color import Color -from MyGame.Example.NestedUnion.TestSimpleTableWithEnum import TestSimpleTableWithEnum uoffset: typing.TypeAlias = flatbuffers.number_types.UOffsetTFlags.py_type diff --git a/tests/MyGame/Example/NestedUnion/Vec3.pyi b/tests/MyGame/Example/NestedUnion/Vec3.pyi index c570c20b4..9205c5fe3 100644 --- a/tests/MyGame/Example/NestedUnion/Vec3.pyi +++ b/tests/MyGame/Example/NestedUnion/Vec3.pyi @@ -7,7 +7,6 @@ import flatbuffers import typing from MyGame.Example.NestedUnion.Color import Color from MyGame.Example.NestedUnion.Test import Test, TestT -from MyGame.Example.NestedUnion.Vec3 import Vec3 uoffset: typing.TypeAlias = flatbuffers.number_types.UOffsetTFlags.py_type diff --git a/tests/MyGame/MonsterExtra.pyi b/tests/MyGame/MonsterExtra.pyi index 693cc5126..5088cd276 100644 --- a/tests/MyGame/MonsterExtra.pyi +++ b/tests/MyGame/MonsterExtra.pyi @@ -5,7 +5,6 @@ import numpy as np import flatbuffers import typing -from MyGame.MonsterExtra import MonsterExtra uoffset: typing.TypeAlias = flatbuffers.number_types.UOffsetTFlags.py_type