[Python] Generate `.pyi` stub files when `--python-typing` is on. (#8312)
* [Python] Generate `.pyi` stub files when `--python-typing` is on. To support this change, the following modifications were made: - added a new option to disable `numpy` helpers generation; - added a new flag to control the target Python version: `--python-version` can be one of the following: - `0.x.x` – compatible with any Python version; - `2.x.x` – compatible with Python 2; - `3.x.x` – compatible with Python 3. - added codegen utilities for Python; - added a note that the generated .py file is empty. * [Python] Update Bazel build rules. * [Python] Update Bazel build rules. * [Python] Run buildifier on BUILD.bazel files. --------- Co-authored-by: Derek Bailey <derekbailey@google.com>
This commit is contained in:
parent
58c8eb5847
commit
3b27f5396e
|
@ -37,6 +37,7 @@ filegroup(
|
|||
"pnpm-lock.yaml",
|
||||
"typescript.bzl",
|
||||
"//grpc/src/compiler:distribution",
|
||||
"//include/codegen:distribution",
|
||||
"//reflection:distribution",
|
||||
"//src:distribution",
|
||||
"//ts:distribution",
|
||||
|
|
|
@ -183,6 +183,8 @@ set(FlatBuffers_Compiler_SRCS
|
|||
src/bfbs_gen_lua.h
|
||||
src/bfbs_gen_nim.h
|
||||
src/bfbs_namer.h
|
||||
include/codegen/python.h
|
||||
include/codegen/python.cc
|
||||
include/flatbuffers/code_generators.h
|
||||
src/binary_annotator.h
|
||||
src/binary_annotator.cpp
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
###############################################################################
|
||||
# Bazel now uses Bzlmod by default to manage external dependencies.
|
||||
# Please consider migrating your external dependencies from WORKSPACE to MODULE.bazel.
|
||||
#
|
||||
# For more details, please check https://github.com/bazelbuild/bazel/issues/18958
|
||||
###############################################################################
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,24 @@
|
|||
load("@rules_cc//cc:defs.bzl", "cc_library")
|
||||
|
||||
package(
|
||||
default_visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "distribution",
|
||||
srcs = [
|
||||
"BUILD.bazel",
|
||||
] + glob([
|
||||
"*.cc",
|
||||
"*.h",
|
||||
]),
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "python",
|
||||
srcs = ["python.cc"],
|
||||
hdrs = ["python.h"],
|
||||
strip_include_prefix = "/include",
|
||||
visibility = ["//src:__subpackages__"],
|
||||
)
|
|
@ -0,0 +1,63 @@
|
|||
#include "codegen/python.h"
|
||||
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace flatbuffers {
|
||||
namespace python {
|
||||
Version::Version(const std::string &version) {
|
||||
std::stringstream ss(version);
|
||||
char dot;
|
||||
ss >> major >> dot >> minor >> dot >> micro;
|
||||
}
|
||||
|
||||
bool Version::IsValid() const {
|
||||
return (major == 0 || major == 2 || major == 3) && minor >= 0 && micro >= 0;
|
||||
}
|
||||
|
||||
std::set<std::string> Keywords(const Version &version) {
|
||||
switch (version.major) {
|
||||
case 2:
|
||||
// https://docs.python.org/2/reference/lexical_analysis.html#keywords
|
||||
return {
|
||||
"and", "as", "assert", "break", "class", "continue", "def",
|
||||
"del", "elif", "else", "except", "exec", "finally", "for",
|
||||
"from", "global", "if", "import", "in", "is", "lambda",
|
||||
"not", "or", "pass", "print", "raise", "return", "try",
|
||||
"while", "with", "yield",
|
||||
};
|
||||
case 0:
|
||||
case 3:
|
||||
// https://docs.python.org/3/reference/lexical_analysis.html#keywords
|
||||
return {
|
||||
"and", "as", "assert", "async", "await", "break",
|
||||
"class", "continue", "def", "del", "elif", "else",
|
||||
"except", "False", "finally", "for", "from", "global",
|
||||
"if", "import", "in", "is", "lambda", "None",
|
||||
"nonlocal", "not", "or", "pass", "raise", "return",
|
||||
"True", "try", "while", "with", "yield",
|
||||
};
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
const python::Import &python::Imports::Import(const std::string &module) {
|
||||
python::Import import;
|
||||
import.module = module;
|
||||
imports.push_back(std::move(import));
|
||||
return imports.back();
|
||||
}
|
||||
|
||||
const python::Import &python::Imports::Import(const std::string &module,
|
||||
const std::string &name) {
|
||||
python::Import import;
|
||||
import.module = module;
|
||||
import.name = name;
|
||||
imports.push_back(std::move(import));
|
||||
return imports.back();
|
||||
}
|
||||
} // namespace python
|
||||
} // namespace flatbuffers
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef FLATBUFFERS_INCLUDE_CODEGEN_PYTHON_H_
|
||||
#define FLATBUFFERS_INCLUDE_CODEGEN_PYTHON_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace flatbuffers {
|
||||
namespace python {
|
||||
// `Version` represent a Python version.
|
||||
//
|
||||
// The zero value (i.e. `Version{}`) represents both Python2 and Python3.
|
||||
//
|
||||
// https://docs.python.org/3/faq/general.html#how-does-the-python-version-numbering-scheme-work
|
||||
struct Version {
|
||||
explicit Version(const std::string &version);
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
int16_t major = 0;
|
||||
int16_t minor = 0;
|
||||
int16_t micro = 0;
|
||||
};
|
||||
|
||||
std::set<std::string> Keywords(const Version &version);
|
||||
|
||||
struct Import {
|
||||
bool IsLocal() const { return module == "."; }
|
||||
|
||||
std::string module;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct Imports {
|
||||
const python::Import &Import(const std::string &module);
|
||||
const python::Import &Import(const std::string &module,
|
||||
const std::string &name);
|
||||
|
||||
std::vector<python::Import> imports;
|
||||
};
|
||||
} // namespace python
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_INCLUDE_CODEGEN_PYTHON_H_
|
|
@ -706,8 +706,26 @@ struct IDLOptions {
|
|||
bool no_leak_private_annotations;
|
||||
bool require_json_eof;
|
||||
bool keep_proto_id;
|
||||
|
||||
/********************************** Python **********************************/
|
||||
bool python_no_type_prefix_suffix;
|
||||
bool python_typing;
|
||||
|
||||
// The target Python version. Can be one of the following:
|
||||
// - "0"
|
||||
// - "2"
|
||||
// - "3"
|
||||
// - "2.<minor>"
|
||||
// - "3.<minor>"
|
||||
// - "2.<minor>.<micro>"
|
||||
// - "3.<minor>.<micro>"
|
||||
//
|
||||
// https://docs.python.org/3/faq/general.html#how-does-the-python-version-numbering-scheme-work
|
||||
std::string python_version;
|
||||
|
||||
// Whether to generate numpy helpers.
|
||||
bool python_gen_numpy;
|
||||
|
||||
bool ts_omit_entrypoint;
|
||||
ProtoIdGapAction proto_id_gap_action;
|
||||
|
||||
|
@ -828,6 +846,7 @@ struct IDLOptions {
|
|||
keep_proto_id(false),
|
||||
python_no_type_prefix_suffix(false),
|
||||
python_typing(false),
|
||||
python_gen_numpy(true),
|
||||
ts_omit_entrypoint(false),
|
||||
proto_id_gap_action(ProtoIdGapAction::WARNING),
|
||||
mini_reflect(IDLOptions::kNone),
|
||||
|
|
|
@ -155,5 +155,6 @@ cc_library(
|
|||
"//grpc/src/compiler:python_generator",
|
||||
"//grpc/src/compiler:swift_generator",
|
||||
"//grpc/src/compiler:ts_generator",
|
||||
"//include/codegen:python",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <list>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#include "annotated_binary_text_gen.h"
|
||||
#include "binary_annotator.h"
|
||||
|
@ -254,6 +255,8 @@ const static FlatCOption flatc_options[] = {
|
|||
{ "", "python-no-type-prefix-suffix", "",
|
||||
"Skip emission of Python functions that are prefixed with typenames" },
|
||||
{ "", "python-typing", "", "Generate Python type annotations" },
|
||||
{ "", "python-version", "", "Generate code for the given Python version." },
|
||||
{ "", "python-gen-numpy", "", "Whether to generate numpy helpers." },
|
||||
{ "", "ts-omit-entrypoint", "",
|
||||
"Omit emission of namespace entrypoint file" },
|
||||
{ "", "file-names-only", "",
|
||||
|
@ -671,6 +674,18 @@ FlatCOptions FlatCompiler::ParseFromCommandLineArguments(int argc,
|
|||
opts.python_no_type_prefix_suffix = true;
|
||||
} else if (arg == "--python-typing") {
|
||||
opts.python_typing = true;
|
||||
} else if (arg.rfind("--python-version=", 0) == 0) {
|
||||
opts.python_version =
|
||||
arg.substr(std::string("--python-version=").size());
|
||||
} else if (arg == "--python-version") {
|
||||
if (++argi >= argc) Error("missing value following: " + arg, true);
|
||||
opts.python_version = argv[argi];
|
||||
} else if (arg == "--python-gen-numpy" ||
|
||||
arg == "--python-gen-numpy=true") {
|
||||
opts.python_gen_numpy = true;
|
||||
} else if (arg == "--no-python-gen-numpy" ||
|
||||
arg == "--python-gen-numpy=false") {
|
||||
opts.python_gen_numpy = false;
|
||||
} else if (arg == "--ts-omit-entrypoint") {
|
||||
opts.ts_omit_entrypoint = true;
|
||||
} else if (arg == "--annotate-sparse-vectors") {
|
||||
|
|
|
@ -19,13 +19,17 @@
|
|||
#include "idl_gen_python.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "codegen/python.h"
|
||||
#include "flatbuffers/code_generators.h"
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/idl.h"
|
||||
|
@ -40,15 +44,6 @@ namespace {
|
|||
typedef std::pair<std::string, std::string> ImportMapEntry;
|
||||
typedef std::set<ImportMapEntry> ImportMap;
|
||||
|
||||
static std::set<std::string> PythonKeywords() {
|
||||
return { "False", "None", "True", "and", "as", "assert",
|
||||
"break", "class", "continue", "def", "del", "elif",
|
||||
"else", "except", "finally", "for", "from", "global",
|
||||
"if", "import", "in", "is", "lambda", "nonlocal",
|
||||
"not", "or", "pass", "raise", "return", "try",
|
||||
"while", "with", "yield" };
|
||||
}
|
||||
|
||||
static Namer::Config PythonDefaultConfig() {
|
||||
return { /*types=*/Case::kKeep,
|
||||
/*constants=*/Case::kScreamingSnake,
|
||||
|
@ -72,21 +67,594 @@ static Namer::Config PythonDefaultConfig() {
|
|||
/*filename_extension=*/".py" };
|
||||
}
|
||||
|
||||
static Namer::Config kStubConfig = {
|
||||
/*types=*/Case::kKeep,
|
||||
/*constants=*/Case::kScreamingSnake,
|
||||
/*methods=*/Case::kUpperCamel,
|
||||
/*functions=*/Case::kUpperCamel,
|
||||
/*fields=*/Case::kLowerCamel,
|
||||
/*variables=*/Case::kLowerCamel,
|
||||
/*variants=*/Case::kKeep,
|
||||
/*enum_variant_seperator=*/".",
|
||||
/*escape_keywords=*/Namer::Config::Escape::AfterConvertingCase,
|
||||
/*namespaces=*/Case::kKeep, // Packages in python.
|
||||
/*namespace_seperator=*/".",
|
||||
/*object_prefix=*/"",
|
||||
/*object_suffix=*/"T",
|
||||
/*keyword_prefix=*/"",
|
||||
/*keyword_suffix=*/"_",
|
||||
/*filenames=*/Case::kKeep,
|
||||
/*directories=*/Case::kKeep,
|
||||
/*output_path=*/"",
|
||||
/*filename_suffix=*/"",
|
||||
/*filename_extension=*/".pyi",
|
||||
};
|
||||
|
||||
// Hardcode spaces per indentation.
|
||||
static const CommentConfig def_comment = { nullptr, "#", nullptr };
|
||||
static const std::string Indent = " ";
|
||||
|
||||
} // namespace
|
||||
class PythonStubGenerator {
|
||||
public:
|
||||
PythonStubGenerator(const Parser &parser, const std::string &path,
|
||||
const Version &version)
|
||||
: parser_{parser},
|
||||
namer_{WithFlagOptions(kStubConfig, parser.opts, path),
|
||||
Keywords(version)},
|
||||
version_(version) {}
|
||||
|
||||
bool Generate() {
|
||||
if (parser_.opts.one_file) {
|
||||
Imports imports;
|
||||
std::stringstream stub;
|
||||
|
||||
DeclareUOffset(stub, &imports);
|
||||
for (const EnumDef *def : parser_.enums_.vec) {
|
||||
if (def->generated) continue;
|
||||
GenerateEnumStub(stub, def, &imports);
|
||||
}
|
||||
for (const StructDef *def : parser_.structs_.vec) {
|
||||
if (def->generated) continue;
|
||||
GenerateStructStub(stub, def, &imports);
|
||||
}
|
||||
|
||||
std::string filename =
|
||||
namer_.config_.output_path +
|
||||
StripPath(StripExtension(parser_.file_being_parsed_)) +
|
||||
namer_.config_.filename_suffix + namer_.config_.filename_extension;
|
||||
|
||||
return SaveFile(filename, imports, stub);
|
||||
}
|
||||
|
||||
for (const EnumDef *def : parser_.enums_.vec) {
|
||||
if (def->generated) continue;
|
||||
|
||||
Imports imports;
|
||||
std::stringstream stub;
|
||||
|
||||
DeclareUOffset(stub, &imports);
|
||||
GenerateEnumStub(stub, def, &imports);
|
||||
|
||||
std::string filename = namer_.Directories(*def->defined_namespace) +
|
||||
namer_.File(*def, SkipFile::Suffix);
|
||||
if (!SaveFile(filename, imports, stub)) return false;
|
||||
}
|
||||
|
||||
for (const StructDef *def : parser_.structs_.vec) {
|
||||
if (def->generated) continue;
|
||||
|
||||
Imports imports;
|
||||
std::stringstream stub;
|
||||
|
||||
DeclareUOffset(stub, &imports);
|
||||
GenerateStructStub(stub, def, &imports);
|
||||
|
||||
std::string filename = namer_.Directories(*def->defined_namespace) +
|
||||
namer_.File(*def, SkipFile::Suffix);
|
||||
if (!SaveFile(filename, imports, stub)) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool SaveFile(const std::string &filename, const Imports &imports,
|
||||
const std::stringstream &content) {
|
||||
std::stringstream ss;
|
||||
GenerateImports(ss, imports);
|
||||
ss << '\n';
|
||||
ss << content.str() << '\n';
|
||||
|
||||
EnsureDirExists(StripFileName(filename));
|
||||
return flatbuffers::SaveFile(filename.c_str(), ss.str(), false);
|
||||
}
|
||||
|
||||
static void DeclareUOffset(std::stringstream &stub, Imports *imports) {
|
||||
imports->Import("flatbuffers");
|
||||
imports->Import("typing");
|
||||
stub << "uoffset: typing.TypeAlias = "
|
||||
"flatbuffers.number_types.UOffsetTFlags.py_type\n"
|
||||
<< '\n';
|
||||
}
|
||||
|
||||
std::string ModuleForFile(const std::string &file) const {
|
||||
if (parser_.file_being_parsed_ == file) return ".";
|
||||
|
||||
std::string module = parser_.opts.include_prefix + StripExtension(file) +
|
||||
parser_.opts.filename_suffix;
|
||||
std::replace(module.begin(), module.end(), '/', '.');
|
||||
return module;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string ModuleFor(const T *def) const {
|
||||
if (parser_.opts.one_file) return ModuleForFile(def->file);
|
||||
return namer_.NamespacedType(*def);
|
||||
}
|
||||
|
||||
const StructDef *GetNestedStruct(const FieldDef *field) const {
|
||||
const Value *nested = field->attributes.Lookup("nested_flatbuffer");
|
||||
if (nested == nullptr) return nullptr;
|
||||
|
||||
StructDef *nested_def = parser_.LookupStruct(nested->constant);
|
||||
if (nested_def != nullptr) return nested_def;
|
||||
|
||||
return parser_.LookupStruct(namer_.NamespacedType(
|
||||
parser_.current_namespace_->components, nested->constant));
|
||||
}
|
||||
|
||||
static std::string ScalarType(BaseType type) {
|
||||
if (IsBool(type)) return "bool";
|
||||
if (IsInteger(type)) return "int";
|
||||
if (IsFloat(type)) return "float";
|
||||
FLATBUFFERS_ASSERT(false);
|
||||
return "None";
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
std::string UnionType(const EnumDef &enum_def, Imports *imports,
|
||||
F type) const {
|
||||
imports->Import("typing");
|
||||
|
||||
std::string result = "";
|
||||
for (const EnumVal *val : enum_def.Vals()) {
|
||||
if (!result.empty()) result += ", ";
|
||||
|
||||
switch (val->union_type.base_type) {
|
||||
case BASE_TYPE_STRUCT: {
|
||||
Import import = imports->Import(ModuleFor(val->union_type.struct_def),
|
||||
type(*val->union_type.struct_def));
|
||||
result += import.name;
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_STRING:
|
||||
result += "str";
|
||||
break;
|
||||
case BASE_TYPE_NONE:
|
||||
result += "None";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "typing.Union[" + result + "]";
|
||||
}
|
||||
|
||||
std::string UnionObjectType(const EnumDef &enum_def, Imports *imports) const {
|
||||
return UnionType(enum_def, imports, [this](const StructDef &struct_def) {
|
||||
return namer_.ObjectType(struct_def);
|
||||
});
|
||||
}
|
||||
|
||||
std::string UnionType(const EnumDef &enum_def, Imports *imports) const {
|
||||
return UnionType(enum_def, imports, [this](const StructDef &struct_def) {
|
||||
return namer_.Type(struct_def);
|
||||
});
|
||||
}
|
||||
|
||||
std::string EnumType(const EnumDef &enum_def, Imports *imports) const {
|
||||
imports->Import("typing");
|
||||
const Import &import =
|
||||
imports->Import(ModuleFor(&enum_def), namer_.Type(enum_def));
|
||||
|
||||
std::string result = "";
|
||||
for (const EnumVal *val : enum_def.Vals()) {
|
||||
if (!result.empty()) result += ", ";
|
||||
result += import.name + "." + namer_.Variant(*val);
|
||||
}
|
||||
return "typing.Literal[" + result + "]";
|
||||
}
|
||||
|
||||
std::string TypeOf(const Type &type, Imports *imports) const {
|
||||
if (type.enum_def != nullptr) return EnumType(*type.enum_def, imports);
|
||||
if (IsScalar(type.base_type)) return ScalarType(type.base_type);
|
||||
|
||||
switch (type.base_type) {
|
||||
case BASE_TYPE_STRUCT: {
|
||||
const Import &import = imports->Import(ModuleFor(type.struct_def),
|
||||
namer_.Type(*type.struct_def));
|
||||
return import.name;
|
||||
}
|
||||
case BASE_TYPE_STRING:
|
||||
return "str";
|
||||
case BASE_TYPE_ARRAY:
|
||||
case BASE_TYPE_VECTOR: {
|
||||
imports->Import("typing");
|
||||
return "typing.List[" + TypeOf(type.VectorType(), imports) + "]";
|
||||
}
|
||||
case BASE_TYPE_UNION:
|
||||
return UnionType(*type.enum_def, imports);
|
||||
default:
|
||||
FLATBUFFERS_ASSERT(0);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string GenerateObjectFieldStub(const FieldDef *field,
|
||||
Imports *imports) const {
|
||||
std::string field_name = namer_.Field(*field);
|
||||
|
||||
const Type &field_type = field->value.type;
|
||||
if (IsScalar(field_type.base_type)) {
|
||||
std::string result = field_name + ": " + TypeOf(field_type, imports);
|
||||
if (field->IsOptional()) result += " | None";
|
||||
return result;
|
||||
}
|
||||
|
||||
switch (field_type.base_type) {
|
||||
case BASE_TYPE_STRUCT: {
|
||||
Import import =
|
||||
imports->Import(ModuleFor(field_type.struct_def),
|
||||
namer_.ObjectType(*field_type.struct_def));
|
||||
return field_name + ": " + import.name + " | None";
|
||||
}
|
||||
case BASE_TYPE_STRING:
|
||||
return field_name + ": str | None";
|
||||
case BASE_TYPE_ARRAY:
|
||||
case BASE_TYPE_VECTOR: {
|
||||
imports->Import("typing");
|
||||
if (field_type.element == BASE_TYPE_STRUCT) {
|
||||
Import import =
|
||||
imports->Import(ModuleFor(field_type.struct_def),
|
||||
namer_.ObjectType(*field_type.struct_def));
|
||||
return field_name + ": typing.List[" + import.name + "]";
|
||||
}
|
||||
if (field_type.element == BASE_TYPE_STRING) {
|
||||
return field_name + ": typing.List[str]";
|
||||
}
|
||||
return field_name + ": typing.List[" +
|
||||
TypeOf(field_type.VectorType(), imports) + "]";
|
||||
}
|
||||
case BASE_TYPE_UNION:
|
||||
return field_name + ": " +
|
||||
UnionObjectType(*field->value.type.enum_def, imports);
|
||||
default:
|
||||
return field_name;
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateObjectStub(std::stringstream &stub, const StructDef *struct_def,
|
||||
Imports *imports) const {
|
||||
std::string name = namer_.ObjectType(*struct_def);
|
||||
|
||||
stub << "class " << name;
|
||||
if (version_.major != 3) stub << "(object)";
|
||||
stub << ":\n";
|
||||
for (const FieldDef *field : struct_def->fields.vec) {
|
||||
if (field->deprecated) continue;
|
||||
stub << " " << GenerateObjectFieldStub(field, imports) << "\n";
|
||||
}
|
||||
|
||||
stub << " @classmethod\n";
|
||||
stub << " def InitFromBuf(cls, buf: bytes, pos: int) -> " << name
|
||||
<< ": ...\n";
|
||||
|
||||
stub << " @classmethod\n";
|
||||
stub << " def InitFromPackedBuf(cls, buf: bytes, pos: int = 0) -> " << name
|
||||
<< ": ...\n";
|
||||
|
||||
const Import &import =
|
||||
imports->Import(ModuleFor(struct_def), namer_.Type(*struct_def));
|
||||
|
||||
stub << " @classmethod\n";
|
||||
stub << " def InitFromObj(cls, " << namer_.Variable(*struct_def)
|
||||
<< ": " + import.name + ") -> " << name << ": ...\n";
|
||||
|
||||
stub << " def _UnPack(self, " << namer_.Variable(*struct_def) << ": "
|
||||
<< import.name << ") -> None: ...\n";
|
||||
|
||||
stub << " def Pack(self, builder: flatbuffers.Builder) -> None: ...\n";
|
||||
|
||||
if (parser_.opts.gen_compare) {
|
||||
stub << " def __eq__(self, other: " << name + ") -> bool: ...\n";
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateStructStub(std::stringstream &stub, const StructDef *struct_def,
|
||||
Imports *imports) const {
|
||||
std::string type = namer_.Type(*struct_def);
|
||||
|
||||
stub << "class " << type;
|
||||
if (version_.major != 3) stub << "(object)";
|
||||
stub << ":\n";
|
||||
if (struct_def->fixed) {
|
||||
stub << " @classmethod\n";
|
||||
stub << " def SizeOf(cls) -> int: ...\n\n";
|
||||
} else {
|
||||
stub << " @classmethod\n";
|
||||
stub << " def GetRootAs(cls, buf: bytes, offset: int) -> " << type
|
||||
<< ": ...\n";
|
||||
|
||||
if (!parser_.opts.python_no_type_prefix_suffix) {
|
||||
stub << " @classmethod\n";
|
||||
stub << " def GetRootAs" << type
|
||||
<< "(cls, buf: bytes, offset: int) -> " << type << ": ...\n";
|
||||
}
|
||||
if (parser_.file_identifier_.length()) {
|
||||
stub << " @classmethod\n";
|
||||
stub << " def " << type
|
||||
<< "BufferHasIdentifier(cls, buf: bytes, offset: int, "
|
||||
"size_prefixed: bool) -> bool: ...\n";
|
||||
}
|
||||
}
|
||||
|
||||
stub << " def Init(self, buf: bytes, pos: int) -> None: ...\n";
|
||||
|
||||
for (const FieldDef *field : struct_def->fields.vec) {
|
||||
if (field->deprecated) continue;
|
||||
|
||||
std::string name = namer_.Method(*field);
|
||||
|
||||
const Type &field_type = field->value.type;
|
||||
if (IsScalar(field_type.base_type)) {
|
||||
stub << " def " << name << "(self) -> " << TypeOf(field_type, imports);
|
||||
if (field->IsOptional()) stub << " | None";
|
||||
stub << ": ...\n";
|
||||
} else {
|
||||
switch (field_type.base_type) {
|
||||
case BASE_TYPE_STRUCT: {
|
||||
const Import &import =
|
||||
imports->Import(ModuleFor(field_type.struct_def),
|
||||
namer_.Type(*field_type.struct_def));
|
||||
if (struct_def->fixed) {
|
||||
stub << " def " << name << "(self, obj: " << import.name
|
||||
<< ") -> " << import.name << ": ...\n";
|
||||
} else {
|
||||
stub << " def " << name + "(self) -> " << import.name
|
||||
<< " | None: ...\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_STRING:
|
||||
stub << " def " << name << "(self) -> str | None: ...\n";
|
||||
break;
|
||||
case BASE_TYPE_ARRAY:
|
||||
case BASE_TYPE_VECTOR: {
|
||||
switch (field_type.element) {
|
||||
case BASE_TYPE_STRUCT: {
|
||||
const Import &import =
|
||||
imports->Import(ModuleFor(field_type.struct_def),
|
||||
namer_.Type(*field_type.struct_def));
|
||||
stub << " def " << name << "(self, i: int) -> " << import.name
|
||||
<< " | None: ...\n";
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_STRING:
|
||||
stub << " def " << name << "(self, i: int) -> str: ...\n";
|
||||
break;
|
||||
default: // scalars
|
||||
stub << " def " << name << "(self, i: int) -> "
|
||||
<< TypeOf(field_type, imports) << ": ...\n";
|
||||
|
||||
if (parser_.opts.python_gen_numpy) {
|
||||
stub << " def " << name
|
||||
<< "AsNumpy(self) -> np.ndarray: ...\n";
|
||||
}
|
||||
|
||||
const StructDef *nested_def = GetNestedStruct(field);
|
||||
if (nested_def != nullptr) {
|
||||
const Import &import = imports->Import(
|
||||
ModuleFor(nested_def), namer_.Type(*nested_def));
|
||||
|
||||
stub << " def " << name + "NestedRoot(self) -> "
|
||||
<< import.name << " | None: ...\n";
|
||||
}
|
||||
break;
|
||||
}
|
||||
stub << " def " << name << "Length(self) -> int: ...\n";
|
||||
stub << " def " << name << "IsNone(self) -> bool: ...\n";
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_UNION: {
|
||||
imports->Import("flatbuffers", "table");
|
||||
stub << " def " << name << "(self) -> table.Table | None: ...\n";
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parser_.opts.generate_object_based_api) {
|
||||
GenerateObjectStub(stub, struct_def, imports);
|
||||
}
|
||||
|
||||
if (struct_def->fixed) {
|
||||
GenerateStructBuilderStub(stub, struct_def, imports);
|
||||
} else {
|
||||
GenerateTableBuilderStub(stub, struct_def, imports);
|
||||
}
|
||||
}
|
||||
|
||||
void StructBuilderArgs(const StructDef &struct_def, const std::string prefix,
|
||||
Imports *imports,
|
||||
std::vector<std::string> *args) const {
|
||||
for (const FieldDef *field : struct_def.fields.vec) {
|
||||
const Type type = IsArray(field->value.type)
|
||||
? field->value.type.VectorType()
|
||||
: field->value.type;
|
||||
if (type.base_type == BASE_TYPE_STRUCT) {
|
||||
StructBuilderArgs(*field->value.type.struct_def,
|
||||
prefix + namer_.Field(*field) + "_", imports, args);
|
||||
} else {
|
||||
args->push_back(prefix + namer_.Field(*field) + ": " +
|
||||
TypeOf(type, imports));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateStructBuilderStub(std::stringstream &stub,
|
||||
const StructDef *struct_def,
|
||||
Imports *imports) const {
|
||||
imports->Import("flatbuffers");
|
||||
|
||||
std::vector<std::string> args;
|
||||
StructBuilderArgs(*struct_def, "", imports, &args);
|
||||
|
||||
stub << '\n';
|
||||
stub << "def Create" + namer_.Type(*struct_def)
|
||||
<< "(builder: flatbuffers.Builder";
|
||||
for (const std::string &arg : args) {
|
||||
stub << ", " << arg;
|
||||
}
|
||||
stub << ") -> uoffset: ...\n";
|
||||
}
|
||||
|
||||
void GenerateTableBuilderStub(std::stringstream &stub,
|
||||
const StructDef *struct_def,
|
||||
Imports *imports) const {
|
||||
std::string type = namer_.Type(*struct_def);
|
||||
|
||||
/**************************** def TableStart ****************************/
|
||||
stub << "def ";
|
||||
if (!parser_.opts.python_no_type_prefix_suffix) stub << type;
|
||||
stub << "Start(builder: flatbuffers.Builder) -> None: ...\n";
|
||||
if (!parser_.opts.one_file && !parser_.opts.python_no_type_prefix_suffix) {
|
||||
stub << "def Start(builder: flatbuffers.Builder) -> None: ...\n";
|
||||
}
|
||||
|
||||
/************************** def TableAddField ***************************/
|
||||
for (const FieldDef *field : struct_def->fields.vec) {
|
||||
if (field->deprecated) continue;
|
||||
|
||||
stub << "def ";
|
||||
if (!parser_.opts.python_no_type_prefix_suffix) stub << type;
|
||||
stub << "Add" << namer_.Method(*field)
|
||||
<< "(builder: flatbuffers.Builder, "
|
||||
<< namer_.Variable(*field) + ": ";
|
||||
if (IsScalar(field->value.type.base_type)) {
|
||||
stub << TypeOf(field->value.type, imports);
|
||||
} else if (IsArray(field->value.type)) {
|
||||
stub << TypeOf(field->value.type.VectorType(), imports);
|
||||
} else {
|
||||
stub << "uoffset";
|
||||
}
|
||||
stub << ") -> None: ...\n";
|
||||
|
||||
if (IsVector(field->value.type)) {
|
||||
stub << "def ";
|
||||
if (!parser_.opts.python_no_type_prefix_suffix) stub << type;
|
||||
stub << "Start" << namer_.Method(*field)
|
||||
<< "Vector(builder: flatbuffers.Builder, num_elems: int) -> "
|
||||
"uoffset: ...\n";
|
||||
|
||||
if (!parser_.opts.one_file &&
|
||||
!parser_.opts.python_no_type_prefix_suffix) {
|
||||
stub << "def Start" << namer_.Method(*field)
|
||||
<< "Vector(builder: flatbuffers.Builder, num_elems: int) -> "
|
||||
"uoffset: ...\n";
|
||||
}
|
||||
|
||||
if (GetNestedStruct(field) != nullptr) {
|
||||
stub << "def " << type << "Make" << namer_.Method(*field)
|
||||
<< "VectorFromBytes(builder: flatbuffers.Builder, buf: "
|
||||
"bytes) -> uoffset: ...\n";
|
||||
if (!parser_.opts.one_file) {
|
||||
stub << "def Make" << namer_.Method(*field)
|
||||
<< "VectorFromBytes(builder: flatbuffers.Builder, buf: "
|
||||
"bytes) -> uoffset: ...\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***************************** def TableEnd *****************************/
|
||||
stub << "def ";
|
||||
if (!parser_.opts.python_no_type_prefix_suffix) stub << type;
|
||||
stub << "End(builder: flatbuffers.Builder) -> uoffset: ...\n";
|
||||
if (!parser_.opts.one_file && !parser_.opts.python_no_type_prefix_suffix) {
|
||||
stub << "def End(builder: flatbuffers.Builder) -> uoffset: ...\n";
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateEnumStub(std::stringstream &stub, const EnumDef *enum_def,
|
||||
Imports *imports) const {
|
||||
stub << "class " << namer_.Type(*enum_def);
|
||||
if (version_.major != 3) stub << "(object)";
|
||||
stub << ":\n";
|
||||
for (const EnumVal *val : enum_def->Vals()) {
|
||||
stub << " " << namer_.Variant(*val) << ": "
|
||||
<< ScalarType(enum_def->underlying_type.base_type) << "\n";
|
||||
}
|
||||
if (parser_.opts.generate_object_based_api & enum_def->is_union) {
|
||||
imports->Import("flatbuffers", "table");
|
||||
stub << "def " << namer_.Function(*enum_def)
|
||||
<< "Creator(union_type: " << EnumType(*enum_def, imports)
|
||||
<< ", table: table.Table) -> " << UnionType(*enum_def, imports)
|
||||
<< ": ...\n";
|
||||
}
|
||||
}
|
||||
|
||||
void GenerateImports(std::stringstream &ss, const Imports &imports) {
|
||||
ss << "from __future__ import annotations\n";
|
||||
ss << '\n';
|
||||
ss << "import flatbuffers\n";
|
||||
if (parser_.opts.python_gen_numpy) {
|
||||
ss << "import numpy as np\n";
|
||||
}
|
||||
ss << '\n';
|
||||
|
||||
std::set<std::string> modules;
|
||||
std::map<std::string, std::set<std::string>> names_by_module;
|
||||
for (const Import &import : imports.imports) {
|
||||
if (import.IsLocal()) continue; // skip all local imports
|
||||
if (import.name == "") {
|
||||
modules.insert(import.module);
|
||||
} else {
|
||||
names_by_module[import.module].insert(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;
|
||||
}
|
||||
ss << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
const Parser &parser_;
|
||||
const IdlNamer namer_;
|
||||
const Version version_;
|
||||
};} // namespace
|
||||
|
||||
class PythonGenerator : public BaseGenerator {
|
||||
public:
|
||||
PythonGenerator(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name)
|
||||
const std::string &file_name, const Version &version)
|
||||
: BaseGenerator(parser, path, file_name, "" /* not used */,
|
||||
"" /* not used */, "py"),
|
||||
float_const_gen_("float('nan')", "float('inf')", "float('-inf')"),
|
||||
namer_(WithFlagOptions(PythonDefaultConfig(), parser.opts, path),
|
||||
PythonKeywords()) {}
|
||||
Keywords(version)) {}
|
||||
|
||||
// Most field accessors need to retrieve and test the field offset first,
|
||||
// this is the prefix code for that.
|
||||
|
@ -940,7 +1508,9 @@ class PythonGenerator : public BaseGenerator {
|
|||
GetMemberOfVectorOfStruct(struct_def, field, code_ptr, imports);
|
||||
} else {
|
||||
GetMemberOfVectorOfNonStruct(struct_def, field, code_ptr);
|
||||
GetVectorOfNonStructAsNumpy(struct_def, field, code_ptr);
|
||||
if (parser_.opts.python_gen_numpy) {
|
||||
GetVectorOfNonStructAsNumpy(struct_def, field, code_ptr);
|
||||
}
|
||||
GetVectorAsNestedFlatbuffer(struct_def, field, code_ptr, imports);
|
||||
}
|
||||
break;
|
||||
|
@ -951,7 +1521,9 @@ class PythonGenerator : public BaseGenerator {
|
|||
GetArrayOfStruct(struct_def, field, code_ptr, imports);
|
||||
} else {
|
||||
GetArrayOfNonStruct(struct_def, field, code_ptr);
|
||||
GetVectorOfNonStructAsNumpy(struct_def, field, code_ptr);
|
||||
if (parser_.opts.python_gen_numpy) {
|
||||
GetVectorOfNonStructAsNumpy(struct_def, field, code_ptr);
|
||||
}
|
||||
GetVectorAsNestedFlatbuffer(struct_def, field, code_ptr, imports);
|
||||
}
|
||||
break;
|
||||
|
@ -1480,13 +2052,17 @@ class PythonGenerator : public BaseGenerator {
|
|||
return;
|
||||
}
|
||||
|
||||
code += GenIndents(3) + "if np is None:";
|
||||
GenUnpackforScalarVectorHelper(struct_def, field, code_ptr, 4);
|
||||
if (parser_.opts.python_gen_numpy) {
|
||||
code += GenIndents(3) + "if np is None:";
|
||||
GenUnpackforScalarVectorHelper(struct_def, field, code_ptr, 4);
|
||||
|
||||
// If numpy exists, use the AsNumpy method to optimize the unpack speed.
|
||||
code += GenIndents(3) + "else:";
|
||||
code += GenIndents(4) + "self." + field_field + " = " + struct_var + "." +
|
||||
field_method + "AsNumpy()";
|
||||
// If numpy exists, use the AsNumpy method to optimize the unpack speed.
|
||||
code += GenIndents(3) + "else:";
|
||||
code += GenIndents(4) + "self." + field_field + " = " + struct_var + "." +
|
||||
field_method + "AsNumpy()";
|
||||
} else {
|
||||
GenUnpackforScalarVectorHelper(struct_def, field, code_ptr, 3);
|
||||
}
|
||||
}
|
||||
|
||||
void GenUnPackForScalar(const StructDef &struct_def, const FieldDef &field,
|
||||
|
@ -1685,14 +2261,20 @@ class PythonGenerator : public BaseGenerator {
|
|||
return;
|
||||
}
|
||||
|
||||
code_prefix += GenIndents(3) + "if np is not None and type(self." +
|
||||
field_field + ") is np.ndarray:";
|
||||
code_prefix += GenIndents(4) + field_field +
|
||||
" = builder.CreateNumpyVector(self." + field_field + ")";
|
||||
code_prefix += GenIndents(3) + "else:";
|
||||
GenPackForScalarVectorFieldHelper(struct_def, field, code_prefix_ptr, 4);
|
||||
code_prefix += "(self." + field_field + "[i])";
|
||||
code_prefix += GenIndents(4) + field_field + " = builder.EndVector()";
|
||||
if (parser_.opts.python_gen_numpy) {
|
||||
code_prefix += GenIndents(3) + "if np is not None and type(self." +
|
||||
field_field + ") is np.ndarray:";
|
||||
code_prefix += GenIndents(4) + field_field +
|
||||
" = builder.CreateNumpyVector(self." + field_field + ")";
|
||||
code_prefix += GenIndents(3) + "else:";
|
||||
GenPackForScalarVectorFieldHelper(struct_def, field, code_prefix_ptr, 4);
|
||||
code_prefix += "(self." + field_field + "[i])";
|
||||
code_prefix += GenIndents(4) + field_field + " = builder.EndVector()";
|
||||
} else {
|
||||
GenPackForScalarVectorFieldHelper(struct_def, field, code_prefix_ptr, 3);
|
||||
code_prefix += "(self." + field_field + "[i])";
|
||||
code_prefix += GenIndents(4) + field_field + " = builder.EndVector()";
|
||||
}
|
||||
}
|
||||
|
||||
void GenPackForStructField(const StructDef &struct_def, const FieldDef &field,
|
||||
|
@ -2113,7 +2695,9 @@ class PythonGenerator : public BaseGenerator {
|
|||
const std::string local_import = "." + mod;
|
||||
|
||||
code += "import flatbuffers\n";
|
||||
code += "from flatbuffers.compat import import_numpy\n";
|
||||
if (parser_.opts.python_gen_numpy) {
|
||||
code += "from flatbuffers.compat import import_numpy\n";
|
||||
}
|
||||
if (parser_.opts.python_typing) {
|
||||
code += "from typing import Any\n";
|
||||
|
||||
|
@ -2129,7 +2713,9 @@ class PythonGenerator : public BaseGenerator {
|
|||
}
|
||||
}
|
||||
}
|
||||
code += "np = import_numpy()\n\n";
|
||||
if (parser_.opts.python_gen_numpy) {
|
||||
code += "np = import_numpy()\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2140,6 +2726,7 @@ class PythonGenerator : public BaseGenerator {
|
|||
std::string code = "";
|
||||
if (classcode.empty()) {
|
||||
BeginFile(LastNamespacePart(ns), false, &code, "", {});
|
||||
code += "# NOTE " + defname + " does not declare any structs or enums\n";
|
||||
} else {
|
||||
BeginFile(LastNamespacePart(ns), needs_imports, &code, mod, imports);
|
||||
code += classcode;
|
||||
|
@ -2169,8 +2756,17 @@ class PythonGenerator : public BaseGenerator {
|
|||
|
||||
static bool GeneratePython(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name) {
|
||||
python::PythonGenerator generator(parser, path, file_name);
|
||||
return generator.generate();
|
||||
python::Version version{parser.opts.python_version};
|
||||
if (!version.IsValid()) return false;
|
||||
|
||||
python::PythonGenerator generator(parser, path, file_name, version);
|
||||
if (!generator.generate()) return false;
|
||||
|
||||
if (parser.opts.python_typing) {
|
||||
python::PythonStubGenerator stub_generator(parser, path, version);
|
||||
if (!stub_generator.Generate()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
|
|
@ -2,3 +2,4 @@
|
|||
|
||||
# namespace: OtherNameSpace
|
||||
|
||||
# NOTE FromInclude.py does not declare any structs or enums
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import flatbuffers
|
||||
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
|
||||
|
||||
uoffset: typing.TypeAlias = flatbuffers.number_types.UOffsetTFlags.py_type
|
||||
|
||||
class ArrayStruct(object):
|
||||
@classmethod
|
||||
def SizeOf(cls) -> int: ...
|
||||
|
||||
def Init(self, buf: bytes, pos: int) -> None: ...
|
||||
def A(self) -> float: ...
|
||||
def B(self, i: int) -> typing.List[int]: ...
|
||||
def BAsNumpy(self) -> np.ndarray: ...
|
||||
def BLength(self) -> int: ...
|
||||
def BIsNone(self) -> bool: ...
|
||||
def C(self) -> int: ...
|
||||
def D(self, i: int) -> NestedStruct | None: ...
|
||||
def DLength(self) -> int: ...
|
||||
def DIsNone(self) -> bool: ...
|
||||
def E(self) -> int: ...
|
||||
def F(self, i: int) -> typing.List[int]: ...
|
||||
def FAsNumpy(self) -> np.ndarray: ...
|
||||
def FLength(self) -> int: ...
|
||||
def FIsNone(self) -> bool: ...
|
||||
class ArrayStructT(object):
|
||||
a: float
|
||||
b: typing.List[int]
|
||||
c: int
|
||||
d: typing.List[NestedStructT]
|
||||
e: int
|
||||
f: typing.List[int]
|
||||
@classmethod
|
||||
def InitFromBuf(cls, buf: bytes, pos: int) -> ArrayStructT: ...
|
||||
@classmethod
|
||||
def InitFromPackedBuf(cls, buf: bytes, pos: int = 0) -> ArrayStructT: ...
|
||||
@classmethod
|
||||
def InitFromObj(cls, arrayStruct: ArrayStruct) -> ArrayStructT: ...
|
||||
def _UnPack(self, arrayStruct: ArrayStruct) -> None: ...
|
||||
def Pack(self, builder: flatbuffers.Builder) -> None: ...
|
||||
|
||||
def CreateArrayStruct(builder: flatbuffers.Builder, a: float, b: int, c: int, d_a: int, d_b: typing.Literal[TestEnum.A, TestEnum.B, TestEnum.C], d_c: typing.Literal[TestEnum.A, TestEnum.B, TestEnum.C], d_d: int, e: int, f: int) -> uoffset: ...
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import flatbuffers
|
||||
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
|
||||
|
||||
class ArrayTable(object):
|
||||
@classmethod
|
||||
def GetRootAs(cls, buf: bytes, offset: int) -> ArrayTable: ...
|
||||
@classmethod
|
||||
def GetRootAsArrayTable(cls, buf: bytes, offset: int) -> ArrayTable: ...
|
||||
@classmethod
|
||||
def ArrayTableBufferHasIdentifier(cls, buf: bytes, offset: int, size_prefixed: bool) -> bool: ...
|
||||
def Init(self, buf: bytes, pos: int) -> None: ...
|
||||
def A(self) -> ArrayStruct | None: ...
|
||||
class ArrayTableT(object):
|
||||
a: ArrayStructT | None
|
||||
@classmethod
|
||||
def InitFromBuf(cls, buf: bytes, pos: int) -> ArrayTableT: ...
|
||||
@classmethod
|
||||
def InitFromPackedBuf(cls, buf: bytes, pos: int = 0) -> ArrayTableT: ...
|
||||
@classmethod
|
||||
def InitFromObj(cls, arrayTable: ArrayTable) -> ArrayTableT: ...
|
||||
def _UnPack(self, arrayTable: ArrayTable) -> None: ...
|
||||
def Pack(self, builder: flatbuffers.Builder) -> None: ...
|
||||
def ArrayTableStart(builder: flatbuffers.Builder) -> None: ...
|
||||
def Start(builder: flatbuffers.Builder) -> None: ...
|
||||
def ArrayTableAddA(builder: flatbuffers.Builder, a: uoffset) -> None: ...
|
||||
def ArrayTableEnd(builder: flatbuffers.Builder) -> uoffset: ...
|
||||
def End(builder: flatbuffers.Builder) -> uoffset: ...
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import flatbuffers
|
||||
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
|
||||
|
||||
class NestedStruct(object):
|
||||
@classmethod
|
||||
def SizeOf(cls) -> int: ...
|
||||
|
||||
def Init(self, buf: bytes, pos: int) -> None: ...
|
||||
def A(self, i: int) -> typing.List[int]: ...
|
||||
def AAsNumpy(self) -> np.ndarray: ...
|
||||
def ALength(self) -> int: ...
|
||||
def AIsNone(self) -> bool: ...
|
||||
def B(self) -> typing.Literal[TestEnum.A, TestEnum.B, TestEnum.C]: ...
|
||||
def C(self, i: int) -> typing.Literal[TestEnum.A, TestEnum.B, TestEnum.C]: ...
|
||||
def CAsNumpy(self) -> np.ndarray: ...
|
||||
def CLength(self) -> int: ...
|
||||
def CIsNone(self) -> bool: ...
|
||||
def D(self, i: int) -> typing.List[int]: ...
|
||||
def DAsNumpy(self) -> np.ndarray: ...
|
||||
def DLength(self) -> int: ...
|
||||
def DIsNone(self) -> bool: ...
|
||||
class NestedStructT(object):
|
||||
a: typing.List[int]
|
||||
b: typing.Literal[TestEnum.A, TestEnum.B, TestEnum.C]
|
||||
c: typing.List[typing.Literal[TestEnum.A, TestEnum.B, TestEnum.C]]
|
||||
d: typing.List[int]
|
||||
@classmethod
|
||||
def InitFromBuf(cls, buf: bytes, pos: int) -> NestedStructT: ...
|
||||
@classmethod
|
||||
def InitFromPackedBuf(cls, buf: bytes, pos: int = 0) -> NestedStructT: ...
|
||||
@classmethod
|
||||
def InitFromObj(cls, nestedStruct: NestedStruct) -> NestedStructT: ...
|
||||
def _UnPack(self, nestedStruct: NestedStruct) -> None: ...
|
||||
def Pack(self, builder: flatbuffers.Builder) -> None: ...
|
||||
|
||||
def CreateNestedStruct(builder: flatbuffers.Builder, a: int, b: typing.Literal[TestEnum.A, TestEnum.B, TestEnum.C], c: typing.Literal[TestEnum.A, TestEnum.B, TestEnum.C], d: int) -> uoffset: ...
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import flatbuffers
|
||||
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
|
||||
|
||||
uoffset: typing.TypeAlias = flatbuffers.number_types.UOffsetTFlags.py_type
|
||||
|
||||
class Any(object):
|
||||
NONE: int
|
||||
Vec3: int
|
||||
TestSimpleTableWithEnum: int
|
||||
def AnyCreator(union_type: typing.Literal[Any.NONE, Any.Vec3, Any.TestSimpleTableWithEnum], table: table.Table) -> typing.Union[None, Vec3, TestSimpleTableWithEnum]: ...
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import flatbuffers
|
||||
import numpy as np
|
||||
|
||||
import flatbuffers
|
||||
import typing
|
||||
|
||||
uoffset: typing.TypeAlias = flatbuffers.number_types.UOffsetTFlags.py_type
|
||||
|
||||
class Color(object):
|
||||
Red: int
|
||||
Green: int
|
||||
Blue: int
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import flatbuffers
|
||||
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
|
||||
|
||||
uoffset: typing.TypeAlias = flatbuffers.number_types.UOffsetTFlags.py_type
|
||||
|
||||
class NestedUnionTest(object):
|
||||
@classmethod
|
||||
def GetRootAs(cls, buf: bytes, offset: int) -> NestedUnionTest: ...
|
||||
@classmethod
|
||||
def GetRootAsNestedUnionTest(cls, buf: bytes, offset: int) -> NestedUnionTest: ...
|
||||
def Init(self, buf: bytes, pos: int) -> None: ...
|
||||
def Name(self) -> str | None: ...
|
||||
def DataType(self) -> typing.Literal[Any.NONE, Any.Vec3, Any.TestSimpleTableWithEnum]: ...
|
||||
def Data(self) -> table.Table | None: ...
|
||||
def Id(self) -> int: ...
|
||||
class NestedUnionTestT(object):
|
||||
name: str | None
|
||||
dataType: typing.Literal[Any.NONE, Any.Vec3, Any.TestSimpleTableWithEnum]
|
||||
data: typing.Union[None, Vec3T, TestSimpleTableWithEnumT]
|
||||
id: int
|
||||
@classmethod
|
||||
def InitFromBuf(cls, buf: bytes, pos: int) -> NestedUnionTestT: ...
|
||||
@classmethod
|
||||
def InitFromPackedBuf(cls, buf: bytes, pos: int = 0) -> NestedUnionTestT: ...
|
||||
@classmethod
|
||||
def InitFromObj(cls, nestedUnionTest: NestedUnionTest) -> NestedUnionTestT: ...
|
||||
def _UnPack(self, nestedUnionTest: NestedUnionTest) -> None: ...
|
||||
def Pack(self, builder: flatbuffers.Builder) -> None: ...
|
||||
def NestedUnionTestStart(builder: flatbuffers.Builder) -> None: ...
|
||||
def Start(builder: flatbuffers.Builder) -> None: ...
|
||||
def NestedUnionTestAddName(builder: flatbuffers.Builder, name: uoffset) -> None: ...
|
||||
def NestedUnionTestAddDataType(builder: flatbuffers.Builder, dataType: typing.Literal[Any.NONE, Any.Vec3, Any.TestSimpleTableWithEnum]) -> None: ...
|
||||
def NestedUnionTestAddData(builder: flatbuffers.Builder, data: uoffset) -> None: ...
|
||||
def NestedUnionTestAddId(builder: flatbuffers.Builder, id: int) -> None: ...
|
||||
def NestedUnionTestEnd(builder: flatbuffers.Builder) -> uoffset: ...
|
||||
def End(builder: flatbuffers.Builder) -> uoffset: ...
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import flatbuffers
|
||||
import numpy as np
|
||||
|
||||
import flatbuffers
|
||||
import typing
|
||||
from MyGame.Example.NestedUnion.Test import Test
|
||||
|
||||
uoffset: typing.TypeAlias = flatbuffers.number_types.UOffsetTFlags.py_type
|
||||
|
||||
class Test(object):
|
||||
@classmethod
|
||||
def SizeOf(cls) -> int: ...
|
||||
|
||||
def Init(self, buf: bytes, pos: int) -> None: ...
|
||||
def A(self) -> int: ...
|
||||
def B(self) -> int: ...
|
||||
class TestT(object):
|
||||
a: int
|
||||
b: int
|
||||
@classmethod
|
||||
def InitFromBuf(cls, buf: bytes, pos: int) -> TestT: ...
|
||||
@classmethod
|
||||
def InitFromPackedBuf(cls, buf: bytes, pos: int = 0) -> TestT: ...
|
||||
@classmethod
|
||||
def InitFromObj(cls, test: Test) -> TestT: ...
|
||||
def _UnPack(self, test: Test) -> None: ...
|
||||
def Pack(self, builder: flatbuffers.Builder) -> None: ...
|
||||
|
||||
def CreateTest(builder: flatbuffers.Builder, a: int, b: int) -> uoffset: ...
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import flatbuffers
|
||||
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
|
||||
|
||||
class TestSimpleTableWithEnum(object):
|
||||
@classmethod
|
||||
def GetRootAs(cls, buf: bytes, offset: int) -> TestSimpleTableWithEnum: ...
|
||||
@classmethod
|
||||
def GetRootAsTestSimpleTableWithEnum(cls, buf: bytes, offset: int) -> TestSimpleTableWithEnum: ...
|
||||
def Init(self, buf: bytes, pos: int) -> None: ...
|
||||
def Color(self) -> typing.Literal[Color.Red, Color.Green, Color.Blue]: ...
|
||||
class TestSimpleTableWithEnumT(object):
|
||||
color: typing.Literal[Color.Red, Color.Green, Color.Blue]
|
||||
@classmethod
|
||||
def InitFromBuf(cls, buf: bytes, pos: int) -> TestSimpleTableWithEnumT: ...
|
||||
@classmethod
|
||||
def InitFromPackedBuf(cls, buf: bytes, pos: int = 0) -> TestSimpleTableWithEnumT: ...
|
||||
@classmethod
|
||||
def InitFromObj(cls, testSimpleTableWithEnum: TestSimpleTableWithEnum) -> TestSimpleTableWithEnumT: ...
|
||||
def _UnPack(self, testSimpleTableWithEnum: TestSimpleTableWithEnum) -> None: ...
|
||||
def Pack(self, builder: flatbuffers.Builder) -> None: ...
|
||||
def TestSimpleTableWithEnumStart(builder: flatbuffers.Builder) -> None: ...
|
||||
def Start(builder: flatbuffers.Builder) -> None: ...
|
||||
def TestSimpleTableWithEnumAddColor(builder: flatbuffers.Builder, color: typing.Literal[Color.Red, Color.Green, Color.Blue]) -> None: ...
|
||||
def TestSimpleTableWithEnumEnd(builder: flatbuffers.Builder) -> uoffset: ...
|
||||
def End(builder: flatbuffers.Builder) -> uoffset: ...
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import flatbuffers
|
||||
import numpy as np
|
||||
|
||||
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
|
||||
|
||||
class Vec3(object):
|
||||
@classmethod
|
||||
def GetRootAs(cls, buf: bytes, offset: int) -> Vec3: ...
|
||||
@classmethod
|
||||
def GetRootAsVec3(cls, buf: bytes, offset: int) -> Vec3: ...
|
||||
def Init(self, buf: bytes, pos: int) -> None: ...
|
||||
def X(self) -> float: ...
|
||||
def Y(self) -> float: ...
|
||||
def Z(self) -> float: ...
|
||||
def Test1(self) -> float: ...
|
||||
def Test2(self) -> typing.Literal[Color.Red, Color.Green, Color.Blue]: ...
|
||||
def Test3(self) -> Test | None: ...
|
||||
class Vec3T(object):
|
||||
x: float
|
||||
y: float
|
||||
z: float
|
||||
test1: float
|
||||
test2: typing.Literal[Color.Red, Color.Green, Color.Blue]
|
||||
test3: TestT | None
|
||||
@classmethod
|
||||
def InitFromBuf(cls, buf: bytes, pos: int) -> Vec3T: ...
|
||||
@classmethod
|
||||
def InitFromPackedBuf(cls, buf: bytes, pos: int = 0) -> Vec3T: ...
|
||||
@classmethod
|
||||
def InitFromObj(cls, vec3: Vec3) -> Vec3T: ...
|
||||
def _UnPack(self, vec3: Vec3) -> None: ...
|
||||
def Pack(self, builder: flatbuffers.Builder) -> None: ...
|
||||
def Vec3Start(builder: flatbuffers.Builder) -> None: ...
|
||||
def Start(builder: flatbuffers.Builder) -> None: ...
|
||||
def Vec3AddX(builder: flatbuffers.Builder, x: float) -> None: ...
|
||||
def Vec3AddY(builder: flatbuffers.Builder, y: float) -> None: ...
|
||||
def Vec3AddZ(builder: flatbuffers.Builder, z: float) -> None: ...
|
||||
def Vec3AddTest1(builder: flatbuffers.Builder, test1: float) -> None: ...
|
||||
def Vec3AddTest2(builder: flatbuffers.Builder, test2: typing.Literal[Color.Red, Color.Green, Color.Blue]) -> None: ...
|
||||
def Vec3AddTest3(builder: flatbuffers.Builder, test3: uoffset) -> None: ...
|
||||
def Vec3End(builder: flatbuffers.Builder) -> uoffset: ...
|
||||
def End(builder: flatbuffers.Builder) -> uoffset: ...
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import flatbuffers
|
||||
import numpy as np
|
||||
|
||||
import flatbuffers
|
||||
import typing
|
||||
|
||||
uoffset: typing.TypeAlias = flatbuffers.number_types.UOffsetTFlags.py_type
|
||||
|
||||
class TestEnum(object):
|
||||
A: int
|
||||
B: int
|
||||
C: int
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import flatbuffers
|
||||
import numpy as np
|
||||
|
||||
import flatbuffers
|
||||
import typing
|
||||
from MyGame.MonsterExtra import MonsterExtra
|
||||
|
||||
uoffset: typing.TypeAlias = flatbuffers.number_types.UOffsetTFlags.py_type
|
||||
|
||||
class MonsterExtra(object):
|
||||
@classmethod
|
||||
def GetRootAs(cls, buf: bytes, offset: int) -> MonsterExtra: ...
|
||||
@classmethod
|
||||
def GetRootAsMonsterExtra(cls, buf: bytes, offset: int) -> MonsterExtra: ...
|
||||
@classmethod
|
||||
def MonsterExtraBufferHasIdentifier(cls, buf: bytes, offset: int, size_prefixed: bool) -> bool: ...
|
||||
def Init(self, buf: bytes, pos: int) -> None: ...
|
||||
def D0(self) -> float: ...
|
||||
def D1(self) -> float: ...
|
||||
def D2(self) -> float: ...
|
||||
def D3(self) -> float: ...
|
||||
def F0(self) -> float: ...
|
||||
def F1(self) -> float: ...
|
||||
def F2(self) -> float: ...
|
||||
def F3(self) -> float: ...
|
||||
def Dvec(self, i: int) -> typing.List[float]: ...
|
||||
def DvecAsNumpy(self) -> np.ndarray: ...
|
||||
def DvecLength(self) -> int: ...
|
||||
def DvecIsNone(self) -> bool: ...
|
||||
def Fvec(self, i: int) -> typing.List[float]: ...
|
||||
def FvecAsNumpy(self) -> np.ndarray: ...
|
||||
def FvecLength(self) -> int: ...
|
||||
def FvecIsNone(self) -> bool: ...
|
||||
class MonsterExtraT(object):
|
||||
d0: float
|
||||
d1: float
|
||||
d2: float
|
||||
d3: float
|
||||
f0: float
|
||||
f1: float
|
||||
f2: float
|
||||
f3: float
|
||||
dvec: typing.List[float]
|
||||
fvec: typing.List[float]
|
||||
@classmethod
|
||||
def InitFromBuf(cls, buf: bytes, pos: int) -> MonsterExtraT: ...
|
||||
@classmethod
|
||||
def InitFromPackedBuf(cls, buf: bytes, pos: int = 0) -> MonsterExtraT: ...
|
||||
@classmethod
|
||||
def InitFromObj(cls, monsterExtra: MonsterExtra) -> MonsterExtraT: ...
|
||||
def _UnPack(self, monsterExtra: MonsterExtra) -> None: ...
|
||||
def Pack(self, builder: flatbuffers.Builder) -> None: ...
|
||||
def __eq__(self, other: MonsterExtraT) -> bool: ...
|
||||
def MonsterExtraStart(builder: flatbuffers.Builder) -> None: ...
|
||||
def Start(builder: flatbuffers.Builder) -> None: ...
|
||||
def MonsterExtraAddD0(builder: flatbuffers.Builder, d0: float) -> None: ...
|
||||
def MonsterExtraAddD1(builder: flatbuffers.Builder, d1: float) -> None: ...
|
||||
def MonsterExtraAddD2(builder: flatbuffers.Builder, d2: float) -> None: ...
|
||||
def MonsterExtraAddD3(builder: flatbuffers.Builder, d3: float) -> None: ...
|
||||
def MonsterExtraAddF0(builder: flatbuffers.Builder, f0: float) -> None: ...
|
||||
def MonsterExtraAddF1(builder: flatbuffers.Builder, f1: float) -> None: ...
|
||||
def MonsterExtraAddF2(builder: flatbuffers.Builder, f2: float) -> None: ...
|
||||
def MonsterExtraAddF3(builder: flatbuffers.Builder, f3: float) -> None: ...
|
||||
def MonsterExtraAddDvec(builder: flatbuffers.Builder, dvec: uoffset) -> None: ...
|
||||
def MonsterExtraStartDvecVector(builder: flatbuffers.Builder, num_elems: int) -> uoffset: ...
|
||||
def StartDvecVector(builder: flatbuffers.Builder, num_elems: int) -> uoffset: ...
|
||||
def MonsterExtraAddFvec(builder: flatbuffers.Builder, fvec: uoffset) -> None: ...
|
||||
def MonsterExtraStartFvecVector(builder: flatbuffers.Builder, num_elems: int) -> uoffset: ...
|
||||
def StartFvecVector(builder: flatbuffers.Builder, num_elems: int) -> uoffset: ...
|
||||
def MonsterExtraEnd(builder: flatbuffers.Builder) -> uoffset: ...
|
||||
def End(builder: flatbuffers.Builder) -> uoffset: ...
|
||||
|
|
@ -2,3 +2,4 @@
|
|||
|
||||
# namespace: OtherNameSpace
|
||||
|
||||
# NOTE FromInclude.py does not declare any structs or enums
|
||||
|
|
|
@ -2,3 +2,4 @@
|
|||
|
||||
# namespace: OtherNameSpace
|
||||
|
||||
# NOTE TableB.py does not declare any structs or enums
|
||||
|
|
|
@ -2,3 +2,4 @@
|
|||
|
||||
# namespace: OtherNameSpace
|
||||
|
||||
# NOTE Unused.py does not declare any structs or enums
|
||||
|
|
|
@ -2,3 +2,4 @@
|
|||
|
||||
# namespace:
|
||||
|
||||
# NOTE TableA.py does not declare any structs or enums
|
||||
|
|
Loading…
Reference in New Issue