chore: import upstream snapshot with attribution
cffconvert / validate (push) Has been skipped
License Check / license-check (push) Failing after 2s

This commit is contained in:
wehub-resource-sync
2026-07-13 12:14:16 +08:00
commit 8a852e4b4e
36502 changed files with 9277225 additions and 0 deletions
+178
View File
@@ -0,0 +1,178 @@
load("@flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@xla//third_party/rules_python/python:py_binary.bzl", "py_binary")
load("@xla//third_party/rules_python/python:py_library.bzl", "py_library")
load("//tensorflow:tensorflow.bzl", "py_test")
load("//tensorflow:tensorflow.default.bzl", "get_compatible_with_portable")
load("//tensorflow/lite:special_rules.bzl", "tflite_portable_test_suite", "tflite_schema_utils_friends")
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:LICENSE"],
default_visibility = [
"//visibility:public",
],
licenses = ["notice"],
)
filegroup(
name = "tflite_internal_cc_3p_api_deps_src",
srcs = [
":schema_fbs_srcs",
":schema_utils.h",
],
visibility = [
"//tensorflow/lite:__pkg__",
],
)
# This is the package group declaration to which targets for TensorFlow Lite
# Flatbuffer schema utilities.
#
# Its usage should be rare, and is often abused by tools that are doing
# Flatbuffer creation/manipulation in unofficially supported ways.
package_group(
name = "utils_friends",
packages = [
"//tensorflow/compiler/mlir/lite/...",
"//tensorflow/lite/...",
] + tflite_schema_utils_friends(),
)
py_binary(
name = "upgrade_schema",
srcs = ["upgrade_schema.py"],
strict_deps = True,
deps = [":upgrade_schema_main_lib"],
)
py_library(
name = "upgrade_schema_main_lib",
srcs = [
"upgrade_schema.py",
],
data = [
"//tensorflow/compiler/mlir/lite/schema:schema_v0.fbs",
"//tensorflow/compiler/mlir/lite/schema:schema_v1.fbs",
"//tensorflow/compiler/mlir/lite/schema:schema_v2.fbs",
"//tensorflow/compiler/mlir/lite/schema:schema_v3.fbs",
"@flatbuffers//:flatc",
],
strict_deps = True,
deps = [
"//tensorflow:tensorflow_py",
"//tensorflow/python/platform:resource_loader",
],
)
py_test(
name = "upgrade_schema_test",
size = "small",
srcs = ["upgrade_schema_test.py"],
strict_deps = True,
tags = [
"manual",
"no_oss",
"no_pip",
"notap",
],
deps = [
":upgrade_schema_main_lib",
"//tensorflow/python/framework:test_lib",
"//tensorflow/python/platform:client_testlib",
],
)
# copybara:uncomment_begin(google-only)
# py_test(
# name = "schema_validation_test",
# srcs = ["schema_validation_test.py"],
# data = [
# ":schema_fbs_srcs",
# ":schema_generated.h.oss",
# ],
# strict_deps = True,
# # TODO(b/235550563): Enable this TAP with FlatBuffer 2.0.6 migration.
# tags = [
# "manual",
# "notap",
# ],
# deps = [
# "//testing/pybase",
# "@absl_py//absl/flags",
# ],
# )
# copybara:uncomment_end
exports_files([
"conversion_metadata.fbs",
])
# copybara:uncomment_begin(google-only)
# flatbuffer_cc_library(
# name = "schema_fbs",
# srcs = ["//tensorflow/compiler/mlir/lite/schema:schema.fbs"],
# compatible_with = get_compatible_with_portable(),
# )
# copybara:uncomment_end(google-only)
cc_library(
name = "schema_fbs", # copybara:comment_replace name = "schema_fbs_for_oss",
hdrs = [
":schema_generated.h",
"//tensorflow/compiler/mlir/lite/schema:schema_generated.h",
],
deps = [
"//tensorflow/compiler/mlir/lite/schema:schema_fbs",
"@flatbuffers//:runtime_cc",
],
)
# Generic schema for flatbuffer converter (but with mutable makes bigger).
flatbuffer_cc_library(
name = "schema_fbs_with_mutable",
srcs = ["//tensorflow/compiler/mlir/lite/schema:schema.fbs"],
compatible_with = get_compatible_with_portable(),
flatc_args = [
"--gen-mutable",
"--gen-object-api",
],
out_prefix = "mutable/",
)
# Generic schema for inference on device (but with reflections makes bigger).
flatbuffer_cc_library(
name = "schema_fbs_with_reflection",
srcs = ["//tensorflow/compiler/mlir/lite/schema:schema.fbs"],
compatible_with = get_compatible_with_portable(),
flatc_args = [
"--reflect-types",
"--reflect-names",
"--no-union-value-namespacing",
"--gen-object-api",
],
out_prefix = "reflection/",
)
cc_library(
name = "schema_utils",
hdrs = ["schema_utils.h"],
compatible_with = get_compatible_with_portable(),
visibility = ["//visibility:public"],
deps = ["//tensorflow/compiler/mlir/lite/schema:schema_utils"],
)
cc_library(
name = "schema_conversion_utils",
hdrs = ["schema_conversion_utils.h"],
compatible_with = get_compatible_with_portable(),
visibility = ["//visibility:public"],
deps = ["//tensorflow/compiler/mlir/lite/schema:schema_conversion_utils"],
)
flatbuffer_cc_library(
name = "conversion_metadata_fbs",
srcs = ["//tensorflow/compiler/mlir/lite/schema:conversion_metadata.fbs"],
compatible_with = get_compatible_with_portable(),
)
tflite_portable_test_suite()
@@ -0,0 +1,49 @@
load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_cc//cc:cc_test.bzl", "cc_test")
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:LICENSE"],
default_visibility = [
"//visibility:public",
],
licenses = ["notice"],
)
cc_library(
name = "generator",
srcs = ["generator.cc"],
hdrs = ["generator.h"],
deps = [
"//tensorflow/lite/schema:schema_fbs",
],
)
cc_binary(
name = "generate",
srcs = ["generate.cc"],
deps = [
":generator",
],
)
cc_test(
name = "generator_test",
srcs = ["generator_test.cc"],
deps = [
":generator",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "consistency_test",
srcs = ["consistency_test.cc"],
data = [
"//tensorflow/lite:builtin_ops.h",
],
deps = [
":generator",
"@com_google_googletest//:gtest_main",
],
)
@@ -0,0 +1,15 @@
# Builtin Ops Header Generator.
This directory contains a code generator to generate a pure C header for
builtin op definition.
Whenever you add a new builtin op, please execute:
```sh
bazel run \
//tensorflow/lite/schema/builtin_ops_header:generate > \
tensorflow/lite/builtin_ops.h &&
bazel run \
//tensorflow/lite/schema/builtin_ops_list:generate > \
tensorflow/lite/kernels/builtin_ops_list.inc
```
@@ -0,0 +1,47 @@
/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <fstream>
#include <ios>
#include <iterator>
#include <sstream>
#include <string>
#include <gtest/gtest.h>
#include "tensorflow/lite/schema/builtin_ops_header/generator.h"
namespace {
const char* kHeaderFileName =
"tensorflow/lite/builtin_ops.h";
// The test ensures that `builtin_ops.h` is consistent with the FlatBuffer
// schema definition. When the schema is modified, it's required to run the
// generator to re-generate the header.
// Please see README.md for more details.
TEST(BuiltinOpsHeaderTest, TestConsistency) {
std::ifstream input_stream(kHeaderFileName, std::ios::binary);
ASSERT_TRUE(input_stream);
std::string file_content((std::istreambuf_iterator<char>(input_stream)),
std::istreambuf_iterator<char>());
std::ostringstream output_stream;
tflite::builtin_ops_header::GenerateHeader(output_stream);
std::string generated_content = output_stream.str();
EXPECT_EQ(file_content, generated_content);
}
} // anonymous namespace
@@ -0,0 +1,25 @@
/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <iostream>
#include "tensorflow/lite/schema/builtin_ops_header/generator.h"
// This executable is used to generate builtin_ops.h in TensorFlow Lite.
// Please see README.md for more details.
int main() {
if (!tflite::builtin_ops_header::GenerateHeader(std::cout)) {
std::cerr << "Failed to generate the header file.\n";
}
return 0;
}
@@ -0,0 +1,140 @@
/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/schema/builtin_ops_header/generator.h"
#include <cctype>
#include <iostream>
#include <ostream>
#include <string>
#include "tensorflow/lite/schema/schema_generated.h"
namespace tflite {
namespace builtin_ops_header {
namespace {
const char* kFileHeader =
R"(/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_LITE_BUILTIN_OPS_H_
#define TENSORFLOW_LITE_BUILTIN_OPS_H_
// DO NOT EDIT MANUALLY: This file is automatically generated by
// `schema/builtin_ops_header/generator.cc`.
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// The enum for builtin operators.
// Note: CUSTOM, DELEGATE, and PLACEHOLDER_FOR_GREATER_OP_CODES are 3 special
// ops which are not real built-in ops.
typedef enum {
)";
const char* kFileFooter =
R"(} TfLiteBuiltinOperator;
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // TENSORFLOW_LITE_BUILTIN_OPS_H_
)";
} // anonymous namespace
bool IsValidInputEnumName(const std::string& name) {
const char* begin = name.c_str();
const char* ch = begin;
while (*ch != '\0') {
// If it's not the first character, expect an underscore.
if (ch != begin) {
if (*ch != '_') {
return false;
}
++ch;
}
// Expecting a word with upper case letters or digits, like "CONV",
// "CONV2D", "2D"...etc.
bool empty = true;
while (isupper(*ch) || isdigit(*ch)) {
// It's not empty if at least one character is consumed.
empty = false;
++ch;
}
if (empty) {
return false;
}
}
return true;
}
std::string ConstantizeVariableName(const std::string& name) {
std::string result = "kTfLiteBuiltin";
bool uppercase = true;
for (char input_char : name) {
if (input_char == '_') {
uppercase = true;
} else if (uppercase) {
result += toupper(input_char);
uppercase = false;
} else {
result += tolower(input_char);
}
}
return result;
}
bool GenerateHeader(std::ostream& os) {
auto enum_names = tflite::EnumNamesBuiltinOperator();
// Check if all the input enum names are valid.
for (auto enum_value : EnumValuesBuiltinOperator()) {
auto enum_name = enum_names[enum_value];
if (!IsValidInputEnumName(enum_name)) {
std::cerr << "Invalid input enum name: " << enum_name << std::endl;
return false;
}
}
os << kFileHeader;
for (auto enum_value : EnumValuesBuiltinOperator()) {
auto enum_name = enum_names[enum_value];
os << " ";
os << ConstantizeVariableName(enum_name);
os << " = ";
os << enum_value;
os << ",\n";
}
os << kFileFooter;
return true;
}
} // namespace builtin_ops_header
} // namespace tflite
@@ -0,0 +1,39 @@
/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// An utility library to generate pure C header for builtin ops definition.
#ifndef TENSORFLOW_LITE_SCHEMA_BUILTIN_OPS_HEADER_GENERATOR_H_
#define TENSORFLOW_LITE_SCHEMA_BUILTIN_OPS_HEADER_GENERATOR_H_
#include <iostream>
#include <string>
namespace tflite {
namespace builtin_ops_header {
// Check if the input enum name (from the Flatbuffer definition) is valid.
bool IsValidInputEnumName(const std::string& name);
// Convert the enum name from Flatbuffer convention to C enum name convention.
// E.g. `L2_POOL_2D` becomes `kTfLiteBuiltinL2Pool2d`.
std::string ConstantizeVariableName(const std::string& name);
// The function generates a pure C header for builtin ops definition, and write
// it to the output stream.
bool GenerateHeader(std::ostream& os);
} // namespace builtin_ops_header
} // namespace tflite
#endif // TENSORFLOW_LITE_SCHEMA_BUILTIN_OPS_HEADER_GENERATOR_H_
@@ -0,0 +1,58 @@
/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/schema/builtin_ops_header/generator.h"
#include <gtest/gtest.h>
namespace {
using tflite::builtin_ops_header::ConstantizeVariableName;
using tflite::builtin_ops_header::IsValidInputEnumName;
TEST(TestIsValidInputEnumName, TestWithValidInputNames) {
EXPECT_TRUE(IsValidInputEnumName("ADD"));
EXPECT_TRUE(IsValidInputEnumName("CONV_2D"));
EXPECT_TRUE(IsValidInputEnumName("L2_POOL_2D"));
}
TEST(TestIsValidInputEnumName, TestWithLeadingUnderscore) {
EXPECT_FALSE(IsValidInputEnumName("_ADD"));
EXPECT_FALSE(IsValidInputEnumName("_CONV_2D"));
}
TEST(TestIsValidInputEnumName, TestWithLowerCase) {
EXPECT_FALSE(IsValidInputEnumName("_AdD"));
EXPECT_FALSE(IsValidInputEnumName("_COnV_2D"));
}
TEST(TestIsValidInputEnumName, TestWithOtherCharacters) {
EXPECT_FALSE(IsValidInputEnumName("_AdD!2D"));
EXPECT_FALSE(IsValidInputEnumName("_COnV?2D"));
}
TEST(TestIsValidInputEnumName, TestWithDoubleUnderscores) {
EXPECT_FALSE(IsValidInputEnumName("ADD__2D"));
EXPECT_FALSE(IsValidInputEnumName("CONV__2D"));
}
TEST(TestConstantizeVariableName, TestWithValidInputNames) {
EXPECT_EQ(ConstantizeVariableName("ADD"), "kTfLiteBuiltinAdd");
EXPECT_EQ(ConstantizeVariableName("CONV_2D"), "kTfLiteBuiltinConv2d");
EXPECT_EQ(ConstantizeVariableName("L2_POOL_2D"), "kTfLiteBuiltinL2Pool2d");
}
} // anonymous namespace
@@ -0,0 +1,58 @@
# This package contains code to auto-generate the contents of the file
# tensorflow/lite/kernels:builtin_ops_list.inc
# from the BuiltinOperator enum in the FlatBuffer schema,
# and a test to verify that the checked-in copy remains up-to-date.
# TODO(b/184934065): consider merging the code in this directory with
# the code in ../builtin_ops_header/, i.e. have a single tool generate
# both the builtin_ops.h header and the builtin_ops_list.inc file?
load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_cc//cc:cc_test.bzl", "cc_test")
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:LICENSE"],
default_visibility = [
"//visibility:public",
],
licenses = ["notice"],
)
cc_library(
name = "generator",
srcs = ["generator.cc"],
hdrs = ["generator.h"],
deps = [
"//tensorflow/lite/schema:schema_fbs",
],
)
cc_binary(
name = "generate",
srcs = ["generate.cc"],
deps = [
":generator",
],
)
cc_test(
name = "generator_test",
srcs = ["generator_test.cc"],
deps = [
":generator",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "consistency_test",
srcs = ["consistency_test.cc"],
data = [
"//tensorflow/lite/kernels:builtin_ops_list.inc",
],
deps = [
":generator",
"@com_google_googletest//:gtest_main",
],
)
@@ -0,0 +1,15 @@
# Builtin Ops List Generator.
This directory contains a code generator to generate a pure C header for
builtin ops lists.
Whenever you add a new builtin op, please execute:
```sh
bazel run \
//tensorflow/lite/schema/builtin_ops_header:generate > \
tensorflow/lite/builtin_ops.h &&
bazel run \
//tensorflow/lite/schema/builtin_ops_list:generate > \
tensorflow/lite/kernels/builtin_ops_list.inc
```
@@ -0,0 +1,47 @@
/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <fstream>
#include <ios>
#include <iterator>
#include <sstream>
#include <string>
#include <gtest/gtest.h>
#include "tensorflow/lite/schema/builtin_ops_list/generator.h"
namespace {
const char* kHeaderFileName =
"tensorflow/lite/kernels/builtin_ops_list.inc";
// The test ensures that `builtin_ops_list.inc` header is consistent with the
// FlatBuffer schema definition. When the schema is modified, it's required to
// run the generator to re-generate the header.
// Please see README.md for more details.
TEST(BuiltinOpsHeaderTest, TestConsistency) {
std::ifstream input_stream(kHeaderFileName, std::ios::binary);
ASSERT_TRUE(input_stream);
std::string file_content((std::istreambuf_iterator<char>(input_stream)),
std::istreambuf_iterator<char>());
std::ostringstream output_stream;
tflite::builtin_ops_list::GenerateHeader(output_stream);
std::string generated_content = output_stream.str();
EXPECT_EQ(file_content, generated_content);
}
} // anonymous namespace
@@ -0,0 +1,26 @@
/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include <iostream>
#include "tensorflow/lite/schema/builtin_ops_list/generator.h"
// This executable is used to generate builtin_ops.h in TensorFlow Lite.
// Please see README.md for more details.
int main() {
if (!tflite::builtin_ops_list::GenerateHeader(std::cout)) {
std::cerr << "Failed to generate the header file.\n";
}
return 0;
}
@@ -0,0 +1,106 @@
/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/schema/builtin_ops_list/generator.h"
#include <cctype>
#include <iostream>
#include <string>
#include "tensorflow/lite/schema/schema_generated.h"
namespace tflite {
namespace builtin_ops_list {
const char kFileHeader[] = R"(
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// DO NOT EDIT MANUALLY: This file is automatically generated by
// `tensorflow/lite/schema/builtin_ops_list/generator.cc`.
)";
bool IsValidInputEnumName(const std::string& name) {
const char* begin = name.c_str();
const char* ch = begin;
while (*ch != '\0') {
// If it's not the first character, expect an underscore.
if (ch != begin) {
if (*ch != '_') {
return false;
}
++ch;
}
// Expecting a word with upper case letters or digits, like "CONV",
// "CONV2D", "2D"...etc.
bool empty = true;
while (isupper(*ch) || isdigit(*ch)) {
// It's not empty if at least one character is consumed.
empty = false;
++ch;
}
if (empty) {
return false;
}
}
return true;
}
bool GenerateHeader(std::ostream& os) {
auto enum_names = tflite::EnumNamesBuiltinOperator();
os << kFileHeader;
// Check if all the input enum names are valid.
for (auto enum_value : EnumValuesBuiltinOperator()) {
std::string enum_name = enum_names[enum_value];
if (!IsValidInputEnumName(enum_name)) {
std::cerr << "Invalid input enum name: " << enum_name << std::endl;
return false;
}
}
for (auto enum_value : EnumValuesBuiltinOperator()) {
std::string enum_name = enum_names[enum_value];
// Skip pseudo-opcodes that aren't real ops.
if (enum_name == "CUSTOM" ||
enum_name == "PLACEHOLDER_FOR_GREATER_OP_CODES" ||
enum_name == "DELEGATE") {
continue;
}
// Skip ops that aren't declared in builtin_op_kernels.h.
if (enum_name == "CALL" || enum_name == "CONCAT_EMBEDDINGS") {
continue;
}
os << "TFLITE_OP(Register_" << enum_name << ")\n";
}
return true;
}
} // namespace builtin_ops_list
} // namespace tflite
@@ -0,0 +1,35 @@
/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
// An utility library to generate pure C header for builtin ops definition.
#ifndef TENSORFLOW_LITE_SCHEMA_BUILTIN_OPS_LIST_GENERATOR_H_
#define TENSORFLOW_LITE_SCHEMA_BUILTIN_OPS_LIST_GENERATOR_H_
#include <iostream>
#include <string>
namespace tflite {
namespace builtin_ops_list {
// Check if the input enum name (from the Flatbuffer definition) is valid.
bool IsValidInputEnumName(const std::string& name);
// The function generates a pure C header for builtin ops definition, and write
// it to the output stream.
bool GenerateHeader(std::ostream& os);
} // namespace builtin_ops_list
} // namespace tflite
#endif // TENSORFLOW_LITE_SCHEMA_BUILTIN_OPS_LIST_GENERATOR_H_
@@ -0,0 +1,51 @@
/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "tensorflow/lite/schema/builtin_ops_list/generator.h"
#include <gtest/gtest.h>
namespace {
using tflite::builtin_ops_list::IsValidInputEnumName;
TEST(TestIsValidInputEnumName, TestWithValidInputNames) {
EXPECT_TRUE(IsValidInputEnumName("ADD"));
EXPECT_TRUE(IsValidInputEnumName("CONV_2D"));
EXPECT_TRUE(IsValidInputEnumName("L2_POOL_2D"));
}
TEST(TestIsValidInputEnumName, TestWithLeadingUnderscore) {
EXPECT_FALSE(IsValidInputEnumName("_ADD"));
EXPECT_FALSE(IsValidInputEnumName("_CONV_2D"));
}
TEST(TestIsValidInputEnumName, TestWithLowerCase) {
EXPECT_FALSE(IsValidInputEnumName("_AdD"));
EXPECT_FALSE(IsValidInputEnumName("_COnV_2D"));
}
TEST(TestIsValidInputEnumName, TestWithOtherCharacters) {
EXPECT_FALSE(IsValidInputEnumName("_AdD!2D"));
EXPECT_FALSE(IsValidInputEnumName("_COnV?2D"));
}
TEST(TestIsValidInputEnumName, TestWithDoubleUnderscores) {
EXPECT_FALSE(IsValidInputEnumName("ADD__2D"));
EXPECT_FALSE(IsValidInputEnumName("CONV__2D"));
}
} // anonymous namespace
+20
View File
@@ -0,0 +1,20 @@
/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_LITE_SCHEMA_CONVERSION_METADATA_GENERATED_H_
#define TENSORFLOW_LITE_SCHEMA_CONVERSION_METADATA_GENERATED_H_
#include "tensorflow/compiler/mlir/lite/schema/conversion_metadata_generated.h"
#endif // TENSORFLOW_LITE_SCHEMA_CONVERSION_METADATA_GENERATED_H_
@@ -0,0 +1,20 @@
/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_LITE_SCHEMA_SCHEMA_CONVERSION_UTILS_H_
#define TENSORFLOW_LITE_SCHEMA_SCHEMA_CONVERSION_UTILS_H_
#include "tensorflow/compiler/mlir/lite/schema/schema_conversion_utils.h" // IWYU pragma: keep
#endif // TENSORFLOW_LITE_SCHEMA_SCHEMA_CONVERSION_UTILS_H_
+20
View File
@@ -0,0 +1,20 @@
/* Copyright 2024 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_LITE_SCHEMA_SCHEMA_GENERATED_H_
#define TENSORFLOW_LITE_SCHEMA_SCHEMA_GENERATED_H_
#include "tensorflow/compiler/mlir/lite/schema/schema_generated.h"
#endif // TENSORFLOW_LITE_SCHEMA_SCHEMA_GENERATED_H_
+20
View File
@@ -0,0 +1,20 @@
/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#ifndef TENSORFLOW_LITE_SCHEMA_SCHEMA_UTILS_H_
#define TENSORFLOW_LITE_SCHEMA_SCHEMA_UTILS_H_
#include "tensorflow/compiler/mlir/lite/schema/schema_utils.h" // IWYU pragma: keep
#endif // TENSORFLOW_LITE_SCHEMA_SCHEMA_UTILS_H_
+346
View File
@@ -0,0 +1,346 @@
# ==============================================================================
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Upgrade script to move from pre-release schema to new schema.
Usage examples:
bazel run tensorflow/lite/schema/upgrade_schema -- in.json out.json
bazel run tensorflow/lite/schema/upgrade_schema -- in.bin out.bin
bazel run tensorflow/lite/schema/upgrade_schema -- in.bin out.json
bazel run tensorflow/lite/schema/upgrade_schema -- in.json out.bin
bazel run tensorflow/lite/schema/upgrade_schema -- in.tflite out.tflite
"""
import argparse
import contextlib
import json
import os
import shutil
import subprocess
import sys
import tempfile
import tensorflow as tf
from tensorflow.python.platform import resource_loader
parser = argparse.ArgumentParser(
description="Script to move TFLite models from pre-release schema to "
"new schema.")
parser.add_argument(
"input",
type=str,
help="Input TensorFlow lite file in `.json`, `.bin` or `.tflite` format.")
parser.add_argument(
"output",
type=str,
help="Output json or bin TensorFlow lite model compliant with "
"the new schema. Extension must be `.json`, `.bin` or `.tflite`.")
# RAII Temporary Directory, because flatc doesn't allow direct use of tempfiles.
@contextlib.contextmanager
def TemporaryDirectoryResource():
temporary = tempfile.mkdtemp()
try:
yield temporary
finally:
shutil.rmtree(temporary)
class Converter:
"""Converts TensorFlow flatbuffer models from old to new version of schema.
This can convert between any version to the latest version. It uses
an incremental upgrade strategy to go from version to version.
Usage:
converter = Converter()
converter.Convert("a.tflite", "a.json")
converter.Convert("b.json", "b.tflite")
"""
def __init__(self):
# TODO(aselle): make this work in the open source version with better
# path.
paths_to_try = [
"../../../../flatbuffers/flatc", # not bazel
"../../../../external/flatbuffers/flatc" # bazel
]
for p in paths_to_try:
self._flatc_path = resource_loader.get_path_to_datafile(p)
if os.path.exists(self._flatc_path): break
def FindSchema(base_name):
return resource_loader.get_path_to_datafile("%s" % base_name)
# Supported schemas for upgrade.
self._schemas = [
(0, FindSchema("schema_v0.fbs"), True, self._Upgrade0To1),
(1, FindSchema("schema_v1.fbs"), True, self._Upgrade1To2),
(2, FindSchema("schema_v2.fbs"), True, self._Upgrade2To3),
(3, FindSchema("schema_v3.fbs"), False, None) # Non-callable by design.
]
# Ensure schemas are sorted, and extract latest version and upgrade
# dispatch function table.
self._schemas.sort()
self._new_version, self._new_schema = self._schemas[-1][:2]
self._upgrade_dispatch = {
version: dispatch
for version, unused1, unused2, dispatch in self._schemas}
def _Read(self, input_file, schema, raw_binary=False):
"""Read a tflite model assuming the given flatbuffer schema.
If `input_file` is in bin, then we must use flatc to convert the schema
from binary to json.
Args:
input_file: a binary (flatbuffer) or json file to read from. Extension
must be `.tflite`, `.bin`, or `.json` for FlatBuffer Binary or
FlatBuffer JSON.
schema: which schema to use for reading
raw_binary: whether to assume raw_binary (versions previous to v3)
that lacked file_identifier require this.
Raises:
RuntimeError: 1. When flatc cannot be invoked.
2. When json file does not exists.
ValueError: When the extension is not json or bin.
Returns:
A dictionary representing the read tflite model.
"""
raw_binary = ["--raw-binary"] if raw_binary else []
with TemporaryDirectoryResource() as tempdir:
basename = os.path.basename(input_file)
basename_no_extension, extension = os.path.splitext(basename)
if extension in [".bin", ".tflite"]:
# Convert to json using flatc
returncode = subprocess.call([
self._flatc_path,
"-t",
"--strict-json",
"--defaults-json",
] + raw_binary + ["-o", tempdir, schema, "--", input_file])
if returncode != 0:
raise RuntimeError("flatc failed to convert from binary to json.")
json_file = os.path.join(tempdir, basename_no_extension + ".json")
if not os.path.exists(json_file):
raise RuntimeError("Could not find %r" % json_file)
elif extension == ".json":
json_file = input_file
else:
raise ValueError("Invalid extension on input file %r" % input_file)
return json.load(open(json_file))
def _Write(self, data, output_file):
"""Output a json or bin version of the flatbuffer model.
Args:
data: Dict representing the TensorFlow Lite model to write.
output_file: filename to write the converted flatbuffer to. (json,
tflite, or bin extension is required).
Raises:
ValueError: When the extension is not json or bin
RuntimeError: When flatc fails to convert json data to binary.
"""
_, extension = os.path.splitext(output_file)
with TemporaryDirectoryResource() as tempdir:
if extension == ".json":
json.dump(data, open(output_file, "w"), sort_keys=True, indent=2)
elif extension in [".tflite", ".bin"]:
input_json = os.path.join(tempdir, "temp.json")
with open(input_json, "w") as fp:
json.dump(data, fp, sort_keys=True, indent=2)
returncode = subprocess.call([
self._flatc_path, "-b", "--defaults-json", "--strict-json", "-o",
tempdir, self._new_schema, input_json
])
if returncode != 0:
raise RuntimeError("flatc failed to convert upgraded json to binary.")
shutil.copy(os.path.join(tempdir, "temp.tflite"), output_file)
else:
raise ValueError("Invalid extension on output file %r" % output_file)
def _Upgrade0To1(self, data):
"""Upgrade data from Version 0 to Version 1.
Changes: Added subgraphs (which contains a subset of formally global
entries).
Args:
data: Dictionary representing the TensorFlow lite data to be upgraded.
This will be modified in-place to be an upgraded version.
"""
subgraph = {}
for key_to_promote in ["tensors", "operators", "inputs", "outputs"]:
subgraph[key_to_promote] = data[key_to_promote]
del data[key_to_promote]
data["subgraphs"] = [subgraph]
def _Upgrade1To2(self, data):
"""Upgrade data from Version 1 to Version 2.
Changes: Rename operators to Conform to NN API.
Args:
data: Dictionary representing the TensorFlow lite data to be upgraded.
This will be modified in-place to be an upgraded version.
Raises:
ValueError: Throws when model builtins are numeric rather than symbols.
"""
def RemapOperator(opcode_name):
"""Go from old schema op name to new schema op name.
Args:
opcode_name: String representing the ops (see :schema.fbs).
Returns:
Converted opcode_name from V1 to V2.
"""
old_name_to_new_name = {
"CONVOLUTION": "CONV_2D",
"DEPTHWISE_CONVOLUTION": "DEPTHWISE_CONV_2D",
"AVERAGE_POOL": "AVERAGE_POOL_2D",
"MAX_POOL": "MAX_POOL_2D",
"L2_POOL": "L2_POOL_2D",
"SIGMOID": "LOGISTIC",
"L2NORM": "L2_NORMALIZATION",
"LOCAL_RESPONSE_NORM": "LOCAL_RESPONSE_NORMALIZATION",
"Basic_RNN": "RNN",
}
return (old_name_to_new_name[opcode_name]
if opcode_name in old_name_to_new_name else opcode_name)
def RemapOperatorType(operator_type):
"""Remap operator structs from old names to new names.
Args:
operator_type: String representing the builtin operator data type
string. (see :schema.fbs).
Raises:
ValueError: When the model has consistency problems.
Returns:
Upgraded builtin operator data type as a string.
"""
old_to_new = {
"PoolOptions": "Pool2DOptions",
"DepthwiseConvolutionOptions": "DepthwiseConv2DOptions",
"ConvolutionOptions": "Conv2DOptions",
"LocalResponseNormOptions": "LocalResponseNormalizationOptions",
"BasicRNNOptions": "RNNOptions",
}
return (old_to_new[operator_type]
if operator_type in old_to_new else operator_type)
for subgraph in data["subgraphs"]:
for ops in subgraph["operators"]:
ops["builtin_options_type"] = RemapOperatorType(
ops["builtin_options_type"])
# Upgrade the operator codes
for operator_code in data["operator_codes"]:
# Check if builtin_code is the appropriate string type
# use type("") instead of str or unicode. for py2and3
if not isinstance(operator_code["builtin_code"], type(u"")):
raise ValueError("builtin_code %r is non-string. this usually means "
"your model has consistency problems." %
(operator_code["builtin_code"]))
operator_code["builtin_code"] = (RemapOperator(
operator_code["builtin_code"]))
def _Upgrade2To3(self, data):
"""Upgrade data from Version 2 to Version 3.
Changed actual read-only tensor data to be in a buffers table instead
of inline with the tensor.
Args:
data: Dictionary representing the TensorFlow lite data to be upgraded.
This will be modified in-place to be an upgraded version.
"""
buffers = [{"data": []}] # Start with 1 empty buffer
for subgraph in data["subgraphs"]:
if "tensors" not in subgraph:
continue
for tensor in subgraph["tensors"]:
if "data_buffer" not in tensor:
tensor["buffer"] = 0
else:
if tensor["data_buffer"]:
tensor[u"buffer"] = len(buffers)
buffers.append({"data": tensor["data_buffer"]})
else:
tensor["buffer"] = 0
del tensor["data_buffer"]
data["buffers"] = buffers
def _PerformUpgrade(self, data):
"""Manipulate the `data` (parsed JSON) based on changes in format.
This incrementally will upgrade from version to version within data.
Args:
data: Dictionary representing the TensorFlow data. This will be upgraded
in place.
"""
while data["version"] < self._new_version:
self._upgrade_dispatch[data["version"]](data)
data["version"] += 1
def Convert(self, input_file, output_file):
"""Perform schema conversion from input_file to output_file.
Args:
input_file: Filename of TensorFlow Lite data to convert from. Must
be `.json` or `.bin` extension files for JSON or Binary forms of
the TensorFlow FlatBuffer schema.
output_file: Filename to write to. Extension also must be `.json`
or `.bin`.
Raises:
RuntimeError: Generated when none of the upgrader supported schemas
matche the `input_file` data.
"""
# Read data in each schema (since they are incompatible). Version is
# always present. Use the read data that matches the version of the
# schema.
for version, schema, raw_binary, _ in self._schemas:
try:
data_candidate = self._Read(input_file, schema, raw_binary)
except RuntimeError:
continue # Skip and hope another schema works
if "version" not in data_candidate: # Assume version 1 if not present.
data_candidate["version"] = 1
elif data_candidate["version"] == 0: # Version 0 doesn't exist in wild.
data_candidate["version"] = 1
if data_candidate["version"] == version:
self._PerformUpgrade(data_candidate)
self._Write(data_candidate, output_file)
return
raise RuntimeError("No schema that the converter understands worked with "
"the data file you provided.")
def main(argv):
del argv
Converter().Convert(FLAGS.input, FLAGS.output)
if __name__ == "__main__":
FLAGS, unparsed = parser.parse_known_args()
tf.compat.v1.app.run(main=main, argv=[sys.argv[0]] + unparsed)
@@ -0,0 +1,318 @@
# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""Testing for updating TensorFlow lite schema."""
import json
import tempfile
from tensorflow.lite.schema import upgrade_schema as upgrade_schema_lib
from tensorflow.python.framework import test_util
from tensorflow.python.platform import test as test_lib
EMPTY_TEST_SCHEMA_V1 = {
"version": 1,
"operator_codes": [],
"subgraphs": [],
}
EMPTY_TEST_SCHEMA_V3 = {
"version": 3,
"operator_codes": [],
"subgraphs": [],
"buffers": [{
"data": []
}]
}
TEST_SCHEMA_V0 = {
"operator_codes": [],
"tensors": [],
"inputs": [],
"outputs": [],
"operators": [],
"version": 0
}
TEST_SCHEMA_V3 = {
"operator_codes": [],
"buffers": [{
"data": []
}],
"subgraphs": [{
"tensors": [],
"inputs": [],
"outputs": [],
"operators": [],
}],
"version":
3
}
FULL_TEST_SCHEMA_V1 = {
"version":
1,
"operator_codes": [
{
"builtin_code": "CONVOLUTION"
},
{
"builtin_code": "DEPTHWISE_CONVOLUTION"
},
{
"builtin_code": "AVERAGE_POOL"
},
{
"builtin_code": "MAX_POOL"
},
{
"builtin_code": "L2_POOL"
},
{
"builtin_code": "SIGMOID"
},
{
"builtin_code": "L2NORM"
},
{
"builtin_code": "LOCAL_RESPONSE_NORM"
},
{
"builtin_code": "ADD"
},
{
"builtin_code": "Basic_RNN"
},
],
"subgraphs": [{
"operators": [
{
"builtin_options_type": "PoolOptions"
},
{
"builtin_options_type": "DepthwiseConvolutionOptions"
},
{
"builtin_options_type": "ConvolutionOptions"
},
{
"builtin_options_type": "LocalResponseNormOptions"
},
{
"builtin_options_type": "BasicRNNOptions"
},
],
}],
"description":
"",
}
FULL_TEST_SCHEMA_V3 = {
"version":
3,
"operator_codes": [
{
"builtin_code": "CONV_2D"
},
{
"builtin_code": "DEPTHWISE_CONV_2D"
},
{
"builtin_code": "AVERAGE_POOL_2D"
},
{
"builtin_code": "MAX_POOL_2D"
},
{
"builtin_code": "L2_POOL_2D"
},
{
"builtin_code": "LOGISTIC"
},
{
"builtin_code": "L2_NORMALIZATION"
},
{
"builtin_code": "LOCAL_RESPONSE_NORMALIZATION"
},
{
"builtin_code": "ADD"
},
{
"builtin_code": "RNN"
},
],
"subgraphs": [{
"operators": [
{
"builtin_options_type": "Pool2DOptions"
},
{
"builtin_options_type": "DepthwiseConv2DOptions"
},
{
"builtin_options_type": "Conv2DOptions"
},
{
"builtin_options_type": "LocalResponseNormalizationOptions"
},
{
"builtin_options_type": "RNNOptions"
},
],
}],
"description":
"",
"buffers": [{
"data": []
}]
}
BUFFER_TEST_V2 = {
"operator_codes": [],
"buffers": [],
"subgraphs": [{
"tensors": [
{
"data_buffer": [1, 2, 3, 4]
},
{
"data_buffer": [1, 2, 3, 4, 5, 6, 7, 8]
},
{
"data_buffer": []
},
],
"inputs": [],
"outputs": [],
"operators": [],
}],
"version":
2
}
BUFFER_TEST_V3 = {
"operator_codes": [],
"subgraphs": [{
"tensors": [
{
"buffer": 1
},
{
"buffer": 2
},
{
"buffer": 0
},
],
"inputs": [],
"outputs": [],
"operators": [],
}],
"buffers": [
{
"data": []
},
{
"data": [1, 2, 3, 4]
},
{
"data": [1, 2, 3, 4, 5, 6, 7, 8]
},
],
"version":
3
}
def JsonDumpAndFlush(data, fp):
"""Write the dictionary `data` to a JSON file `fp` (and flush).
Args:
data: in a dictionary that is JSON serializable.
fp: File-like object
"""
json.dump(data, fp)
fp.flush()
class TestSchemaUpgrade(test_util.TensorFlowTestCase):
def testNonExistentFile(self):
converter = upgrade_schema_lib.Converter()
_, non_existent = tempfile.mkstemp(suffix=".json") # safe to ignore fd
with self.assertRaisesRegex(IOError, "No such file or directory"):
converter.Convert(non_existent, non_existent)
def testInvalidExtension(self):
converter = upgrade_schema_lib.Converter()
_, invalid_extension = tempfile.mkstemp(suffix=".foo") # safe to ignore fd
with self.assertRaisesRegex(ValueError, "Invalid extension on input"):
converter.Convert(invalid_extension, invalid_extension)
with tempfile.NamedTemporaryFile(suffix=".json", mode="w+") as in_json:
JsonDumpAndFlush(EMPTY_TEST_SCHEMA_V1, in_json)
with self.assertRaisesRegex(ValueError, "Invalid extension on output"):
converter.Convert(in_json.name, invalid_extension)
def CheckConversion(self, data_old, data_expected):
"""Given a data dictionary, test upgrading to current version.
Args:
data_old: TFLite model as a dictionary (arbitrary version).
data_expected: TFLite model as a dictionary (upgraded).
"""
converter = upgrade_schema_lib.Converter()
with tempfile.NamedTemporaryFile(suffix=".json", mode="w+") as in_json, \
tempfile.NamedTemporaryFile(
suffix=".json", mode="w+") as out_json, \
tempfile.NamedTemporaryFile(
suffix=".bin", mode="w+b") as out_bin, \
tempfile.NamedTemporaryFile(
suffix=".tflite", mode="w+b") as out_tflite:
JsonDumpAndFlush(data_old, in_json)
# Test JSON output
converter.Convert(in_json.name, out_json.name)
# Test binary output
# Convert to .tflite and then to .bin and check if binary is equal
converter.Convert(in_json.name, out_tflite.name)
converter.Convert(out_tflite.name, out_bin.name)
self.assertEqual(
open(out_bin.name, "rb").read(),
open(out_tflite.name, "rb").read())
# Test that conversion actually produced successful new json.
converted_schema = json.load(out_json)
self.assertEqual(converted_schema, data_expected)
def testAlreadyUpgraded(self):
"""A file already at version 3 should stay at version 3."""
self.CheckConversion(EMPTY_TEST_SCHEMA_V3, EMPTY_TEST_SCHEMA_V3)
self.CheckConversion(TEST_SCHEMA_V3, TEST_SCHEMA_V3)
self.CheckConversion(BUFFER_TEST_V3, BUFFER_TEST_V3)
# Disable this while we have incorrectly versioned structures around.
# def testV0Upgrade_IntroducesSubgraphs(self):
# """V0 did not have subgraphs; check to make sure they get introduced."""
# self.CheckConversion(TEST_SCHEMA_V0, TEST_SCHEMA_V3)
def testV1Upgrade_RenameOps(self):
"""V1 had many different names for ops; check to make sure they rename."""
self.CheckConversion(EMPTY_TEST_SCHEMA_V1, EMPTY_TEST_SCHEMA_V3)
self.CheckConversion(FULL_TEST_SCHEMA_V1, FULL_TEST_SCHEMA_V3)
def testV2Upgrade_CreateBuffers(self):
"""V2 did not have buffers; check to make sure they are created."""
self.CheckConversion(BUFFER_TEST_V2, BUFFER_TEST_V3)
if __name__ == "__main__":
test_lib.main()