public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Diego Herrera <dherrera@redhat.com>
To: git-commits@fedoraproject.org
Subject: [rpms/onnx] test-1.21.0: Disable tests that depend on python-parameterized
Date: Mon, 08 Jun 2026 15:18:27 GMT [thread overview]
Message-ID: <178093190724.1.1640843290736511251.rpms-onnx-8f9af18ab5ad@fedoraproject.org> (raw)
A new commit has been pushed.
Repo : rpms/onnx
Branch : test-1.21.0
Commit : 8f9af18ab5adc738cb55ab43512e8c94bcc7e16f
Author : Diego Herrera <dherrera@redhat.com>
Date : 2026-01-15T20:17:01-03:00
Stats : +5823/-207 in 11 file(s)
URL : https://src.fedoraproject.org/rpms/onnx/c/8f9af18ab5adc738cb55ab43512e8c94bcc7e16f?branch=test-1.21.0
Log:
Disable tests that depend on python-parameterized
---
diff --git a/.gitignore b/.gitignore
index 7a219dd..7102235 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+results_*
+*.rpm
/onnx-1.13.0.tar.gz
/onnx-1.14.0.tar.gz
/onnx-1.14.1.tar.gz
diff --git a/0000-Build-shared-libraries-and-fix-install-location.patch b/0000-Build-shared-libraries-and-fix-install-location.patch
index 6ba8967..39511d1 100644
--- a/0000-Build-shared-libraries-and-fix-install-location.patch
+++ b/0000-Build-shared-libraries-and-fix-install-location.patch
@@ -8,10 +8,10 @@ Subject: [PATCH 0/6] Build shared libraries and fix install location
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 4dd56b6e..7f79cc9a 100644
+index d15d97edc..d6e04d2e9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
-@@ -367,7 +367,7 @@ list(REMOVE_ITEM __tmp_srcs "${ONNX_ROOT}/onnx/cpp2py_export.cc")
+@@ -466,7 +466,7 @@ list(REMOVE_ITEM __tmp_srcs "${ONNX_ROOT}/onnx/cpp2py_export.cc")
list(REMOVE_ITEM __tmp_srcs ${onnx_gtests_src})
list(APPEND ONNX_SRCS ${__tmp_srcs})
@@ -20,7 +20,7 @@ index 4dd56b6e..7f79cc9a 100644
add_dependencies(onnx_proto gen_onnx_operators_proto gen_onnx_data_proto)
target_include_directories(onnx_proto PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
-@@ -400,6 +400,8 @@ else()
+@@ -499,6 +499,8 @@ else()
set(ONNX_API_DEFINE "-DONNX_API=__attribute__\(\(__visibility__\(\"default\"\)\)\)")
set_target_properties(onnx_proto PROPERTIES CXX_VISIBILITY_PRESET hidden)
set_target_properties(onnx_proto PROPERTIES VISIBILITY_INLINES_HIDDEN 1)
@@ -29,7 +29,7 @@ index 4dd56b6e..7f79cc9a 100644
endif()
target_compile_definitions(onnx_proto PRIVATE ${ONNX_API_DEFINE})
-@@ -423,7 +425,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
+@@ -522,7 +524,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
# So, create a object library
add_library(onnx OBJECT ${ONNX_SRCS})
else()
@@ -40,7 +40,7 @@ index 4dd56b6e..7f79cc9a 100644
endif()
target_include_directories(onnx PUBLIC
-@@ -606,6 +610,17 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/onnx
+@@ -689,6 +693,17 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/onnx
FILES_MATCHING
PATTERN "*.h")
@@ -58,7 +58,7 @@ index 4dd56b6e..7f79cc9a 100644
configure_file(
${PROJECT_SOURCE_DIR}/cmake/ONNXConfigVersion.cmake.in
${PROJECT_BINARY_DIR}/ONNXConfigVersion.cmake
-@@ -623,6 +638,9 @@ install(EXPORT ONNXTargets DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ONNX")
+@@ -747,6 +762,9 @@ endif()
install(TARGETS
onnx onnx_proto
EXPORT ONNXTargets DESTINATION ${CMAKE_INSTALL_LIBDIR})
@@ -69,5 +69,5 @@ index 4dd56b6e..7f79cc9a 100644
if(ONNX_BUILD_TESTS)
include(${ONNX_ROOT}/cmake/unittest.cmake)
--
-2.43.0
+2.52.0
diff --git a/0001-Use-system-protobuf-and-require-parameterized.patch b/0001-Use-system-protobuf-and-require-parameterized.patch
new file mode 100644
index 0000000..76d5007
--- /dev/null
+++ b/0001-Use-system-protobuf-and-require-parameterized.patch
@@ -0,0 +1,21 @@
+From 30745ee623fb1fe7531d6399e54b5ffe411446f5 Mon Sep 17 00:00:00 2001
+From: Alejandro Alvarez Ayllon <a.alvarezayllon@gmail.com>
+Date: Sat, 24 Feb 2024 14:52:25 +0100
+Subject: [PATCH 2/4] Use system protobuf and require parameterized
+
+---
+ requirements.txt | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/requirements.txt b/requirements.txt
+index 7f3a9ad03..46dd7f7fd 100644
+--- a/requirements.txt
++++ b/requirements.txt
+@@ -1,2 +1,3 @@
+ numpy>=1.20
+-protobuf>=3.20.2
++protobuf >= 3.14.0, < 4
++parameterized >= 0.8.1, < 1
+--
+2.52.0
+
diff --git a/0002-Build-shared-libraries-and-fix-install-location.patch b/0002-Build-shared-libraries-and-fix-install-location.patch
deleted file mode 100644
index 0d140bf..0000000
--- a/0002-Build-shared-libraries-and-fix-install-location.patch
+++ /dev/null
@@ -1,73 +0,0 @@
-From 057080c775b2dedcbc6308b04efe8bed8cdd27c7 Mon Sep 17 00:00:00 2001
-From: Alejandro Alvarez Ayllon <a.alvarezayllon@gmail.com>
-Date: Sat, 24 Feb 2024 14:48:45 +0100
-Subject: [PATCH 1/4] Build shared libraries and fix install location
-
----
- CMakeLists.txt | 22 ++++++++++++++++++++--
- 1 file changed, 20 insertions(+), 2 deletions(-)
-
-diff --git a/CMakeLists.txt b/CMakeLists.txt
-index d15d97ed..d6e04d2e 100644
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -466,7 +466,7 @@ list(REMOVE_ITEM __tmp_srcs "${ONNX_ROOT}/onnx/cpp2py_export.cc")
- list(REMOVE_ITEM __tmp_srcs ${onnx_gtests_src})
- list(APPEND ONNX_SRCS ${__tmp_srcs})
-
--add_library(onnx_proto ${ONNX_PROTO_SRCS} ${ONNX_PROTO_HDRS})
-+add_library(onnx_proto SHARED ${ONNX_PROTO_SRCS} ${ONNX_PROTO_HDRS})
- add_dependencies(onnx_proto gen_onnx_operators_proto gen_onnx_data_proto)
- target_include_directories(onnx_proto PUBLIC
- $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
-@@ -499,6 +499,8 @@ else()
- set(ONNX_API_DEFINE "-DONNX_API=__attribute__\(\(__visibility__\(\"default\"\)\)\)")
- set_target_properties(onnx_proto PROPERTIES CXX_VISIBILITY_PRESET hidden)
- set_target_properties(onnx_proto PROPERTIES VISIBILITY_INLINES_HIDDEN 1)
-+ set_target_properties(onnx_proto PROPERTIES VERSION ${ONNX_VERSION}
-+ SOVERSION ${ONNX_VERSION})
- endif()
- target_compile_definitions(onnx_proto PRIVATE ${ONNX_API_DEFINE})
-
-@@ -522,7 +524,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
- # So, create a object library
- add_library(onnx OBJECT ${ONNX_SRCS})
- else()
-- add_library(onnx ${ONNX_SRCS})
-+ add_library(onnx SHARED ${ONNX_SRCS})
-+ set_target_properties(onnx PROPERTIES VERSION ${ONNX_VERSION}
-+ SOVERSION ${ONNX_VERSION})
- endif()
-
- target_include_directories(onnx PUBLIC
-@@ -689,6 +693,17 @@ install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/onnx
- FILES_MATCHING
- PATTERN "*.h")
-
-+install(DIRECTORY ${ONNX_ROOT}/onnx
-+ DESTINATION "${PY_SITEARCH}"
-+ FILES_MATCHING
-+ PATTERN "*.py"
-+ PATTERN "test/*" EXCLUDE )
-+install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/onnx
-+ DESTINATION "${PY_SITEARCH}"
-+ FILES_MATCHING
-+ PATTERN "*.py"
-+ PATTERN "test/*" EXCLUDE )
-+
- configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/ONNXConfigVersion.cmake.in
- ${PROJECT_BINARY_DIR}/ONNXConfigVersion.cmake
-@@ -747,6 +762,9 @@ endif()
- install(TARGETS
- onnx onnx_proto
- EXPORT ONNXTargets DESTINATION ${CMAKE_INSTALL_LIBDIR})
-+install(TARGETS
-+ onnx_cpp2py_export
-+ DESTINATION "${PY_SITEARCH}/onnx")
-
- if(ONNX_BUILD_TESTS)
- include(${ONNX_ROOT}/cmake/unittest.cmake)
---
-2.46.2
-
diff --git a/0002-Let-pyproject_wheel-use-binaries-from-cmake_build.patch b/0002-Let-pyproject_wheel-use-binaries-from-cmake_build.patch
new file mode 100644
index 0000000..c125320
--- /dev/null
+++ b/0002-Let-pyproject_wheel-use-binaries-from-cmake_build.patch
@@ -0,0 +1,33 @@
+From 75e1082f2d17c2c2ccb3c38b429fa24a4b45bbea Mon Sep 17 00:00:00 2001
+From: Alejandro Alvarez Ayllon <a.alvarezayllon@gmail.com>
+Date: Sat, 24 Feb 2024 14:53:10 +0100
+Subject: [PATCH 3/4] Let pyproject_wheel use binaries from cmake_build
+
+---
+ setup.py | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/setup.py b/setup.py
+index 7d2cb9e50..af9049a1e 100644
+--- a/setup.py
++++ b/setup.py
+@@ -27,7 +27,7 @@ import setuptools.command.build_py
+ import setuptools.command.develop
+
+ TOP_DIR = os.path.realpath(os.path.dirname(__file__))
+-CMAKE_BUILD_DIR = os.path.join(TOP_DIR, ".setuptools-cmake-build")
++CMAKE_BUILD_DIR = os.path.join(TOP_DIR, "redhat-linux-build")
+
+ WINDOWS = os.name == "nt"
+
+@@ -151,6 +151,7 @@ class CmakeBuild(setuptools.Command):
+ self.jobs = multiprocessing.cpu_count() if self.jobs is None else int(self.jobs)
+
+ def run(self):
++ return
+ os.makedirs(CMAKE_BUILD_DIR, exist_ok=True)
+
+ with cd(CMAKE_BUILD_DIR):
+--
+2.52.0
+
diff --git a/0002-Use-system-protobuf-and-require-parameterized.patch b/0002-Use-system-protobuf-and-require-parameterized.patch
deleted file mode 100644
index 6fe771f..0000000
--- a/0002-Use-system-protobuf-and-require-parameterized.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-From 30745ee623fb1fe7531d6399e54b5ffe411446f5 Mon Sep 17 00:00:00 2001
-From: Alejandro Alvarez Ayllon <a.alvarezayllon@gmail.com>
-Date: Sat, 24 Feb 2024 14:52:25 +0100
-Subject: [PATCH 2/4] Use system protobuf and require parameterized
-
----
- requirements.txt | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/requirements.txt b/requirements.txt
-index 7f3a9ad0..46dd7f7f 100644
---- a/requirements.txt
-+++ b/requirements.txt
-@@ -1,2 +1,3 @@
- numpy>=1.20
--protobuf>=3.20.2
-+protobuf >= 3.14.0, < 4
-+parameterized >= 0.8.1, < 1
---
-2.46.2
-
diff --git a/0003-Add-fixes-for-use-with-onnxruntime.patch b/0003-Add-fixes-for-use-with-onnxruntime.patch
new file mode 100644
index 0000000..41bc68e
--- /dev/null
+++ b/0003-Add-fixes-for-use-with-onnxruntime.patch
@@ -0,0 +1,68 @@
+From 9809f77792517d0ace2874a84a181e8fe3766d8d Mon Sep 17 00:00:00 2001
+From: Alejandro Alvarez Ayllon <a.alvarezayllon@gmail.com>
+Date: Sat, 24 Feb 2024 14:53:33 +0100
+Subject: [PATCH 4/4] Add fixes for use with onnxruntime
+
+---
+ onnx/defs/schema.cc | 14 ++++++++++++++
+ onnx/onnxruntime_fix.h | 14 ++++++++++++++
+ 2 files changed, 28 insertions(+)
+ create mode 100644 onnx/onnxruntime_fix.h
+
+diff --git a/onnx/defs/schema.cc b/onnx/defs/schema.cc
+index 74bd0a630..573d09018 100644
+--- a/onnx/defs/schema.cc
++++ b/onnx/defs/schema.cc
+@@ -21,8 +21,19 @@
+
+ #include "onnx/common/assertions.h"
+ #include "onnx/defs/parser.h"
++#include "onnx/onnxruntime_fix.h"
+
+ namespace ONNX_NAMESPACE {
++
++bool ONNXRuntimeFix::_static_registration_disabled = false;
++bool ONNXRuntimeFix::isStaticRegistrationDisabled() {
++ return _static_registration_disabled;
++}
++
++void ONNXRuntimeFix::disableStaticRegistration() {
++ _static_registration_disabled = true;
++}
++
+ // -1 means ONNX schema hasn't been loaded yet
+ // 0 means all versions of ONNX schema have been loaded
+ // Other positive integer means the ONNX schemas for the specified version have been loaded
+@@ -1091,6 +1102,9 @@ OpName_Domain_Version_Schema_Map& OpSchemaRegistry::map() {
+ class SchemasRegisterer {
+ public:
+ SchemasRegisterer() {
++ // Check if static registration is actually disabled
++ if(ONNXRuntimeFix::isStaticRegistrationDisabled()) return;
++
+ // In debug builds, the number of schema registered in this constructor
+ // is compared against the number of calls to schema registration macros.
+ #ifndef NDEBUG
+diff --git a/onnx/onnxruntime_fix.h b/onnx/onnxruntime_fix.h
+new file mode 100644
+index 000000000..2495b9310
+--- /dev/null
++++ b/onnx/onnxruntime_fix.h
+@@ -0,0 +1,14 @@
++#pragma once
++
++namespace ONNX_NAMESPACE {
++
++class ONNXRuntimeFix {
++public:
++ static bool isStaticRegistrationDisabled();
++ static void disableStaticRegistration();
++
++private:
++ static bool _static_registration_disabled;
++};
++
++} // namespace ONNX_NAMESPACE
+--
+2.52.0
+
diff --git a/0003-Let-pyproject_wheel-use-binaries-from-cmake_build.patch b/0003-Let-pyproject_wheel-use-binaries-from-cmake_build.patch
deleted file mode 100644
index 269169b..0000000
--- a/0003-Let-pyproject_wheel-use-binaries-from-cmake_build.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 75e1082f2d17c2c2ccb3c38b429fa24a4b45bbea Mon Sep 17 00:00:00 2001
-From: Alejandro Alvarez Ayllon <a.alvarezayllon@gmail.com>
-Date: Sat, 24 Feb 2024 14:53:10 +0100
-Subject: [PATCH 3/4] Let pyproject_wheel use binaries from cmake_build
-
----
- setup.py | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/setup.py b/setup.py
-index 7d2cb9e5..af9049a1 100644
---- a/setup.py
-+++ b/setup.py
-@@ -27,7 +27,7 @@ import setuptools.command.build_py
- import setuptools.command.develop
-
- TOP_DIR = os.path.realpath(os.path.dirname(__file__))
--CMAKE_BUILD_DIR = os.path.join(TOP_DIR, ".setuptools-cmake-build")
-+CMAKE_BUILD_DIR = os.path.join(TOP_DIR, "redhat-linux-build")
-
- WINDOWS = os.name == "nt"
-
-@@ -151,6 +151,7 @@ class CmakeBuild(setuptools.Command):
- self.jobs = multiprocessing.cpu_count() if self.jobs is None else int(self.jobs)
-
- def run(self):
-+ return
- os.makedirs(CMAKE_BUILD_DIR, exist_ok=True)
-
- with cd(CMAKE_BUILD_DIR):
---
-2.46.2
-
diff --git a/0004-Add-fixes-for-use-with-onnxruntime.patch b/0004-Add-fixes-for-use-with-onnxruntime.patch
deleted file mode 100644
index 68b4c6d..0000000
--- a/0004-Add-fixes-for-use-with-onnxruntime.patch
+++ /dev/null
@@ -1,68 +0,0 @@
-From 9809f77792517d0ace2874a84a181e8fe3766d8d Mon Sep 17 00:00:00 2001
-From: Alejandro Alvarez Ayllon <a.alvarezayllon@gmail.com>
-Date: Sat, 24 Feb 2024 14:53:33 +0100
-Subject: [PATCH 4/4] Add fixes for use with onnxruntime
-
----
- onnx/defs/schema.cc | 14 ++++++++++++++
- onnx/onnxruntime_fix.h | 14 ++++++++++++++
- 2 files changed, 28 insertions(+)
- create mode 100644 onnx/onnxruntime_fix.h
-
-diff --git a/onnx/defs/schema.cc b/onnx/defs/schema.cc
-index 74bd0a63..573d0901 100644
---- a/onnx/defs/schema.cc
-+++ b/onnx/defs/schema.cc
-@@ -21,8 +21,19 @@
-
- #include "onnx/common/assertions.h"
- #include "onnx/defs/parser.h"
-+#include "onnx/onnxruntime_fix.h"
-
- namespace ONNX_NAMESPACE {
-+
-+bool ONNXRuntimeFix::_static_registration_disabled = false;
-+bool ONNXRuntimeFix::isStaticRegistrationDisabled() {
-+ return _static_registration_disabled;
-+}
-+
-+void ONNXRuntimeFix::disableStaticRegistration() {
-+ _static_registration_disabled = true;
-+}
-+
- // -1 means ONNX schema hasn't been loaded yet
- // 0 means all versions of ONNX schema have been loaded
- // Other positive integer means the ONNX schemas for the specified version have been loaded
-@@ -1091,6 +1102,9 @@ OpName_Domain_Version_Schema_Map& OpSchemaRegistry::map() {
- class SchemasRegisterer {
- public:
- SchemasRegisterer() {
-+ // Check if static registration is actually disabled
-+ if(ONNXRuntimeFix::isStaticRegistrationDisabled()) return;
-+
- // In debug builds, the number of schema registered in this constructor
- // is compared against the number of calls to schema registration macros.
- #ifndef NDEBUG
-diff --git a/onnx/onnxruntime_fix.h b/onnx/onnxruntime_fix.h
-new file mode 100644
-index 00000000..2495b931
---- /dev/null
-+++ b/onnx/onnxruntime_fix.h
-@@ -0,0 +1,14 @@
-+#pragma once
-+
-+namespace ONNX_NAMESPACE {
-+
-+class ONNXRuntimeFix {
-+public:
-+ static bool isStaticRegistrationDisabled();
-+ static void disableStaticRegistration();
-+
-+private:
-+ static bool _static_registration_disabled;
-+};
-+
-+} // namespace ONNX_NAMESPACE
---
-2.46.2
-
diff --git a/0004-Remove-python-parameterized-dependency.patch b/0004-Remove-python-parameterized-dependency.patch
new file mode 100644
index 0000000..40e2c85
--- /dev/null
+++ b/0004-Remove-python-parameterized-dependency.patch
@@ -0,0 +1,5681 @@
+From 31560ea9f50d6ccb816e5fef537ba3e477201aa1 Mon Sep 17 00:00:00 2001
+From: Diego Herrera <dherrera@fedoraproject.org>
+Date: Thu, 15 Jan 2026 17:32:58 -0300
+Subject: [PATCH 4/4] Remove python-parameterized dependency
+
+---
+ onnx/test/basic_test.py | 92 -
+ onnx/test/helper_test.py | 100 -
+ onnx/test/numpy_helper_test.py | 63 -
+ onnx/test/parser_test.py | 182 --
+ onnx/test/reference_evaluator_ml_test.py | 130 -
+ onnx/test/reference_evaluator_test.py | 771 -----
+ onnx/test/schema_test.py | 194 --
+ onnx/test/shape_inference_test.py | 2589 +----------------
+ onnx/test/test_backend_reference.py | 9 +
+ onnx/test/test_external_data.py | 627 ----
+ onnx/test/tools_test.py | 117 -
+ .../automatic_downgrade_test.py | 30 -
+ onnx/test/version_converter_test.py | 164 --
+ requirements-dev.txt | 1 -
+ requirements-release.txt | 1 -
+ requirements.txt | 1 -
+ 16 files changed, 130 insertions(+), 4941 deletions(-)
+
+diff --git a/onnx/test/basic_test.py b/onnx/test/basic_test.py
+index 3de8a91d6..ca5719ba6 100644
+--- a/onnx/test/basic_test.py
++++ b/onnx/test/basic_test.py
+@@ -11,7 +11,6 @@ import unittest
+
+ import google.protobuf.message
+ import google.protobuf.text_format
+-import parameterized
+
+ import onnx
+ from onnx import serialization
+@@ -35,97 +34,6 @@ def _simple_tensor() -> onnx.TensorProto:
+ return tensor
+
+
+-@parameterized.parameterized_class(
+- [
+- {"format": "protobuf"},
+- {"format": "textproto"},
+- {"format": "json"},
+- {"format": "onnxtxt"},
+- ]
+-)
+-class TestIO(unittest.TestCase):
+- format: str
+-
+- def test_load_model_when_input_is_bytes(self) -> None:
+- proto = _simple_model()
+- proto_string = serialization.registry.get(self.format).serialize_proto(proto)
+- loaded_proto = onnx.load_model_from_string(proto_string, format=self.format)
+- self.assertEqual(proto, loaded_proto)
+-
+- def test_save_and_load_model_when_input_has_read_function(self) -> None:
+- proto = _simple_model()
+- # When the proto is a bytes representation provided to `save_model`,
+- # it should always be a serialized binary protobuf representation. Aka. format="protobuf"
+- # The saved file format is specified by the `format` argument.
+- proto_string = serialization.registry.get("protobuf").serialize_proto(proto)
+- f = io.BytesIO()
+- onnx.save_model(proto_string, f, format=self.format)
+- loaded_proto = onnx.load_model(io.BytesIO(f.getvalue()), format=self.format)
+- self.assertEqual(proto, loaded_proto)
+-
+- def test_save_and_load_model_when_input_is_file_name(self) -> None:
+- proto = _simple_model()
+- with tempfile.TemporaryDirectory() as temp_dir:
+- model_path = os.path.join(temp_dir, "model.onnx")
+- onnx.save_model(proto, model_path, format=self.format)
+- loaded_proto = onnx.load_model(model_path, format=self.format)
+- self.assertEqual(proto, loaded_proto)
+-
+- def test_save_and_load_model_when_input_is_pathlike(self) -> None:
+- proto = _simple_model()
+- with tempfile.TemporaryDirectory() as temp_dir:
+- model_path = pathlib.Path(temp_dir, "model.onnx")
+- onnx.save_model(proto, model_path, format=self.format)
+- loaded_proto = onnx.load_model(model_path, format=self.format)
+- self.assertEqual(proto, loaded_proto)
+-
+-
+-@parameterized.parameterized_class(
+- [
+- {"format": "protobuf"},
+- {"format": "textproto"},
+- {"format": "json"},
+- # The onnxtxt format does not support saving/loading tensors yet
+- ]
+-)
+-class TestIOTensor(unittest.TestCase):
+- """Test loading and saving of TensorProto."""
+-
+- format: str
+-
+- def test_load_tensor_when_input_is_bytes(self) -> None:
+- proto = _simple_tensor()
+- proto_string = serialization.registry.get(self.format).serialize_proto(proto)
+- loaded_proto = onnx.load_tensor_from_string(proto_string, format=self.format)
+- self.assertEqual(proto, loaded_proto)
+-
+- def test_save_and_load_tensor_when_input_has_read_function(self) -> None:
+- # Test if input has a read function
+- proto = _simple_tensor()
+- f = io.BytesIO()
+- onnx.save_tensor(proto, f, format=self.format)
+- loaded_proto = onnx.load_tensor(io.BytesIO(f.getvalue()), format=self.format)
+- self.assertEqual(proto, loaded_proto)
+-
+- def test_save_and_load_tensor_when_input_is_file_name(self) -> None:
+- # Test if input is a file name
+- proto = _simple_tensor()
+- with tempfile.TemporaryDirectory() as temp_dir:
+- model_path = os.path.join(temp_dir, "model.onnx")
+- onnx.save_tensor(proto, model_path, format=self.format)
+- loaded_proto = onnx.load_tensor(model_path, format=self.format)
+- self.assertEqual(proto, loaded_proto)
+-
+- def test_save_and_load_tensor_when_input_is_pathlike(self) -> None:
+- # Test if input is a file name
+- proto = _simple_tensor()
+- with tempfile.TemporaryDirectory() as temp_dir:
+- model_path = pathlib.Path(temp_dir, "model.onnx")
+- onnx.save_tensor(proto, model_path, format=self.format)
+- loaded_proto = onnx.load_tensor(model_path, format=self.format)
+- self.assertEqual(proto, loaded_proto)
+-
+-
+ class TestSaveAndLoadFileExtensions(unittest.TestCase):
+ def test_save_model_picks_correct_format_from_extension(self) -> None:
+ proto = _simple_model()
+diff --git a/onnx/test/helper_test.py b/onnx/test/helper_test.py
+index 2b38e52c7..ecb3d34e7 100644
+--- a/onnx/test/helper_test.py
++++ b/onnx/test/helper_test.py
+@@ -11,7 +11,6 @@ import unittest
+ from typing import Any
+
+ import numpy as np
+-import parameterized
+ import pytest
+ import version_utils
+
+@@ -656,83 +655,6 @@ class TestHelperTensorFunctions(unittest.TestCase):
+ ynp = numpy_helper.to_array(y)
+ np.testing.assert_equal(Cast.eval(expected, to=TensorProto.FLOAT8E5M2FNUZ), ynp) # type: ignore[arg-type]
+
+- @parameterized.parameterized.expand(
+- itertools.product(
+- (TensorProto.UINT4, TensorProto.INT4),
+- ((5, 4, 6), (4, 6, 5), (3, 3), (1,), (2**10,)),
+- )
+- )
+- @unittest.skipIf(
+- version_utils.numpy_older_than("1.22.0"),
+- "The test requires numpy 1.22.0 or later",
+- )
+- def test_make_4bit_tensor(self, dtype, dims) -> None:
+- type_range = {
+- TensorProto.UINT4: (0, 15),
+- TensorProto.INT4: (-8, 7),
+- }
+- data = np.random.randint(
+- type_range[dtype][0], high=type_range[dtype][1] + 1, size=dims
+- )
+- y = helper.make_tensor("y", dtype, data.shape, data)
+-
+- # Check the expected size of int32_data in bytes
+- expected_data_size = math.ceil(np.prod(data.shape) / 2.0)
+- actual_data_size = len(bytes(y.int32_data))
+- np.testing.assert_equal(actual_data_size, expected_data_size)
+-
+- # Check the expected data values.
+- ynp = to_array_extended(y)
+- np.testing.assert_equal(data, ynp)
+-
+- @parameterized.parameterized.expand(
+- itertools.product(
+- ((5, 4, 6), (4, 6, 5), (3, 3), (1,), (2**10,)),
+- )
+- )
+- @unittest.skipIf(
+- version_utils.numpy_older_than("1.22.0"),
+- "The test requires numpy 1.22.0 or later",
+- )
+- def test_4bit_tensor_size(self, dims) -> None:
+- # A bug caused negative int4 values to inflate tensor size.
+- # So, test negative values here.
+- num_elems = np.prod(dims)
+- data = np.array([-4] * num_elems, dtype=np.int8).reshape(dims)
+- y = helper.make_tensor("y", TensorProto.INT4, data.shape, data)
+-
+- # Check the expected size of int32_data in bytes
+- expected_data_size = math.ceil(num_elems / 2.0)
+- actual_data_size = len(bytes(y.int32_data))
+- np.testing.assert_equal(actual_data_size, expected_data_size)
+-
+- @parameterized.parameterized.expand(
+- itertools.product(
+- (TensorProto.UINT4, TensorProto.INT4), ((5, 4, 6), (4, 6, 5), (3, 3), (1,))
+- )
+- )
+- @unittest.skipIf(
+- version_utils.numpy_older_than("1.26.0"),
+- "The test requires numpy 1.26.0 or later",
+- )
+- def test_make_4bit_raw_tensor(self, dtype, dims) -> None:
+- type_range = {
+- TensorProto.UINT4: (0, 15),
+- TensorProto.INT4: (-8, 7),
+- }
+- data = np.random.randint(
+- type_range[dtype][0], high=type_range[dtype][1] + 1, size=dims
+- ).astype(np.float32)
+- packed_data = helper.pack_float32_to_4bit(
+- data, signed=(dtype == TensorProto.INT4)
+- )
+-
+- y = helper.make_tensor(
+- "packed_int4", dtype, dims, packed_data.tobytes(), raw=True
+- )
+- ynp = numpy_helper.to_array(y)
+- np.testing.assert_equal(data, ynp)
+-
+ def test_make_sparse_tensor(self) -> None:
+ values = [1.1, 2.2, 3.3, 4.4, 5.5]
+ values_tensor = helper.make_tensor(
+@@ -1018,28 +940,6 @@ class TestHelperMappingFunctions(unittest.TestCase):
+
+
+ class TestAttrTypeToStr(unittest.TestCase):
+- @parameterized.parameterized.expand(
+- [
+- (AttributeProto.AttributeType.FLOAT, "FLOAT"), # type: ignore[attr-defined]
+- (AttributeProto.AttributeType.INT, "INT"), # type: ignore[attr-defined]
+- (AttributeProto.AttributeType.STRING, "STRING"), # type: ignore[attr-defined]
+- (AttributeProto.AttributeType.TENSOR, "TENSOR"), # type: ignore[attr-defined]
+- (AttributeProto.AttributeType.GRAPH, "GRAPH"), # type: ignore[attr-defined]
+- (AttributeProto.AttributeType.SPARSE_TENSOR, "SPARSE_TENSOR"), # type: ignore[attr-defined]
+- (AttributeProto.AttributeType.TYPE_PROTO, "TYPE_PROTO"), # type: ignore[attr-defined]
+- (AttributeProto.AttributeType.FLOATS, "FLOATS"), # type: ignore[attr-defined]
+- (AttributeProto.AttributeType.INTS, "INTS"), # type: ignore[attr-defined]
+- (AttributeProto.AttributeType.STRINGS, "STRINGS"), # type: ignore[attr-defined]
+- (AttributeProto.AttributeType.TENSORS, "TENSORS"), # type: ignore[attr-defined]
+- (AttributeProto.AttributeType.GRAPHS, "GRAPHS"), # type: ignore[attr-defined]
+- (AttributeProto.AttributeType.SPARSE_TENSORS, "SPARSE_TENSORS"), # type: ignore[attr-defined]
+- (AttributeProto.AttributeType.TYPE_PROTOS, "TYPE_PROTOS"), # type: ignore[attr-defined]
+- ]
+- )
+- def test_attr_type_to_str(self, attr_type, expected_str):
+- result = helper._attr_type_to_str(attr_type)
+- self.assertEqual(result, expected_str)
+-
+ def test_attr_type_to_str_undefined(self):
+ result = helper._attr_type_to_str(9999)
+ self.assertEqual(result, "UNDEFINED")
+diff --git a/onnx/test/numpy_helper_test.py b/onnx/test/numpy_helper_test.py
+index f642cc87f..621a8b8a2 100644
+--- a/onnx/test/numpy_helper_test.py
++++ b/onnx/test/numpy_helper_test.py
+@@ -7,7 +7,6 @@ import unittest
+ from typing import Any
+
+ import numpy as np
+-import parameterized
+
+ import onnx
+ import onnx.reference
+@@ -147,29 +146,6 @@ class TestNumpyHelper(unittest.TestCase):
+ def test_complex128(self) -> None:
+ self._test_numpy_helper_float_type(np.complex128)
+
+- @parameterized.parameterized.expand(
+- [
+- (1,),
+- (0.100097656,),
+- (130048,),
+- (1.2993813e-5,),
+- (np.nan,),
+- (np.inf,),
+- ]
+- )
+- def test_bfloat16_to_float32(self, f):
+- f32 = np.float32(f)
+- bf16 = helper.float32_to_bfloat16(f32)
+- assert isinstance(bf16, int)
+- f32_1 = numpy_helper.bfloat16_to_float32(np.array([bf16]))[0]
+- f32_2 = bfloat16_to_float32(bf16)
+- if np.isnan(f32):
+- assert np.isnan(f32_1)
+- assert np.isnan(f32_2)
+- else:
+- self.assertEqual(f32, f32_1)
+- self.assertEqual(f32, f32_2)
+-
+ def test_float8e4m3_to_float32(self):
+ self.assertEqual(numpy_helper.float8e4m3_to_float32(int("1111110", 2)), 448)
+ self.assertEqual(numpy_helper.float8e4m3_to_float32(int("1000", 2)), 2 ** (-6))
+@@ -208,26 +184,6 @@ class TestNumpyHelper(unittest.TestCase):
+ self.assertEqual(f32, f32_1)
+ self.assertEqual(f32, f32_2)
+
+- @parameterized.parameterized.expand(
+- [
+- (0.00439453125, 0.00390625),
+- (0.005859375, 0.005859375),
+- (0.005759375, 0.005859375),
+- (0.0046875, 0.00390625),
+- (0.001953125, 0.001953125),
+- (0.0029296875, 0.00390625),
+- (0.002053125, 0.001953125),
+- (0.00234375, 0.001953125),
+- (0.0087890625, 0.0078125),
+- (0.001171875, 0.001953125),
+- (1.8131605, 1.875),
+- ]
+- )
+- def test_float8e4m3_to_float32_round(self, val, expected):
+- f8 = helper.float32_to_float8e4m3(val)
+- f32 = numpy_helper.float8e4m3_to_float32(f8)
+- self.assertEqual(f32, expected)
+-
+ def test_float8e5m2_to_float32(self):
+ self.assertEqual(numpy_helper.float8e5m2_to_float32(int("1111011", 2)), 57344)
+ self.assertEqual(numpy_helper.float8e5m2_to_float32(int("100", 2)), 2 ** (-14))
+@@ -625,25 +581,6 @@ class TestNumpyHelper(unittest.TestCase):
+ self.assertEqual(tp.SerializeToString(), again.SerializeToString())
+ self.assertEqual(tp.data_type, helper.np_dtype_to_tensor_dtype(back.dtype))
+
+- @parameterized.parameterized.expand([(att,) for att in dir(onnx.TensorProto)])
+- def test_to_array_from_array(self, att):
+- if att in {
+- "INT4",
+- "UINT4",
+- "STRING",
+- "UNDEFINED",
+- "DEFAULT",
+- "NAME_FIELD_NUMBER",
+- }:
+- return
+- if att[0] < "A" or att[0] > "Z":
+- return
+- value = getattr(onnx.TensorProto, att)
+- if not isinstance(value, int):
+- return
+-
+- self._to_array_from_array(value)
+-
+ def test_to_array_from_array_subtype(self):
+ self._to_array_from_array(onnx.TensorProto.INT4)
+ self._to_array_from_array(onnx.TensorProto.UINT4)
+diff --git a/onnx/test/parser_test.py b/onnx/test/parser_test.py
+index c117d379b..967d29390 100644
+--- a/onnx/test/parser_test.py
++++ b/onnx/test/parser_test.py
+@@ -5,8 +5,6 @@ from __future__ import annotations
+
+ import unittest
+
+-from parameterized import parameterized
+-
+ import onnx
+ from onnx import GraphProto, OperatorSetIdProto, TensorProto, checker
+
+@@ -120,94 +118,6 @@ class TestBasicFunctions(unittest.TestCase):
+ model = onnx.parser.parse_model(input)
+ checker.check_model(model)
+
+- @parameterized.expand(
+- [
+- (
+- "agraph (float[N] x) => (float[N] out) { out = custom_domain.Selu(x) }",
+- {},
+- ),
+- (
+- "agraph (float[N] x) => (float[N] out) { out = custom_domain.Selu<alpha=2.0>(x) }",
+- {"alpha": 2.0},
+- ),
+- (
+- "agraph (float[N] x) => (float[N] out) { out = custom_domain.Selu<gamma=3.0>(x) }",
+- {"gamma": 3.0},
+- ),
+- (
+- "agraph (float[N] x) => (float[N] out) { out = custom_domain.Selu<alpha=2.0, gamma=3.0>(x) }",
+- {"alpha": 2.0, "gamma": 3.0},
+- ),
+- ]
+- )
+- def test_composite_parse_function_with_attributes(
+- self, graph_text: str, expected_attribute: dict
+- ) -> None:
+- default_alpha = 1.67326319217681884765625
+- default_gamma = 1.05070102214813232421875
+-
+- def expect_custom_node_attribute(node, attributes):
+- for key in attributes:
+- match_attr = [attr for attr in node.attribute if attr.name == key]
+- assert len(match_attr) == 1
+- assert match_attr[0].f == attributes[key]
+-
+- def expect_model_function_attribute(model):
+- assert len(model.functions[0].attribute_proto) == 2
+- attr_proto_alpha = [
+- attr_proto
+- for attr_proto in model.functions[0].attribute_proto
+- if attr_proto.name == "alpha"
+- ]
+- assert len(attr_proto_alpha) == 1 and attr_proto_alpha[0].f == default_alpha
+- attr_proto_gamma = [
+- attr_proto
+- for attr_proto in model.functions[0].attribute_proto
+- if attr_proto.name == "gamma"
+- ]
+- assert len(attr_proto_gamma) == 1 and attr_proto_gamma[0].f == default_gamma
+-
+- function_text = f"""
+- <
+- domain: "custom_domain",
+- opset_import: [ "" : 15],
+- doc_string: "Test function proto"
+- >
+- Selu
+- <alpha: float={default_alpha}, gamma: float={default_gamma}>
+- (X) => (C)
+- {{
+- constant_alpha = Constant<value_float: float=@alpha>()
+- constant_gamma = Constant<value_float: float=@gamma>()
+- alpha_x = CastLike(constant_alpha, X)
+- gamma_x = CastLike(constant_gamma, X)
+- exp_x = Exp(X)
+- alpha_x_exp_x = Mul(alpha_x, exp_x)
+- alpha_x_exp_x_ = Sub(alpha_x_exp_x, alpha_x)
+- neg = Mul(gamma_x, alpha_x_exp_x_)
+- pos = Mul(gamma_x, X)
+- _zero = Constant<value_float=0.0>()
+- zero = CastLike(_zero, X)
+- less_eq = LessOrEqual(X, zero)
+- C = Where(less_eq, neg, pos)
+- }}
+- """
+-
+- functions = [onnx.parser.parse_function(function_text)]
+- graph = onnx.parser.parse_graph(graph_text)
+- opset_imports = [
+- OperatorSetIdProto(domain="", version=15),
+- OperatorSetIdProto(domain="custom_domain", version=1),
+- ]
+-
+- model = onnx.helper.make_model(
+- graph, functions=functions, opset_imports=opset_imports
+- )
+- checker.check_model(model)
+-
+- expect_model_function_attribute(model)
+- expect_custom_node_attribute(model.graph.node[0], expected_attribute)
+-
+ def test_parse_node(self):
+ node = onnx.parser.parse_node(
+ "out1, out2 = SomeDomain.SomeOp <attr1 = 1> (in1, in2)"
+@@ -220,98 +130,6 @@ class TestBasicFunctions(unittest.TestCase):
+ self.assertEqual(node.domain, "SomeDomain")
+ self.assertEqual(node.op_type, "SomeOp")
+
+- @parameterized.expand(
+- [
+- ("not_a_good_float", True),
+- ("inf1", True),
+- ("-inf1", True),
+- ("nan0", True),
+- ("-nan0", True),
+- ("naninf", True),
+- ("inf", False),
+- ("-inf", False),
+- ("infinity", False),
+- ("-infinity", False),
+- ("nan", False),
+- ("-NaN", False),
+- ]
+- )
+- def test_parse_various_float_values(self, test_literal, expect_exception):
+- model_text = f"""
+- <
+- ir_version: 8,
+- opset_import: ["" : 18, "this" : 1],
+- producer_name: "FunctionProtoTest",
+- producer_version: "1.0"
+- >
+- _func () => ()
+- {{
+- tmp = Constant <value_float = {test_literal}>()
+- }}
+- """
+- if expect_exception:
+- self.assertRaises(
+- onnx.parser.ParseError, lambda: onnx.parser.parse_model(model_text)
+- )
+- else:
+- model = onnx.parser.parse_model(model_text)
+- self.assertEqual(model.ir_version, 8)
+- self.assertEqual(model.producer_name, "FunctionProtoTest")
+- self.assertEqual(model.producer_version, "1.0")
+- self.assertEqual(len(model.graph.node), 1)
+- self.assertEqual(len(model.graph.node[0].attribute), 1)
+- self.assertEqual(model.graph.node[0].attribute[0].name, "value_float")
+- self.assertEqual(
+- model.graph.node[0].attribute[0].type, onnx.AttributeProto.FLOAT
+- )
+- self.assertEqual(
+- str(model.graph.node[0].attribute[0].f), str(float(test_literal))
+- )
+-
+- @parameterized.expand(
+- [
+- ("bfloat16", TensorProto.BFLOAT16),
+- ("bool", TensorProto.BOOL),
+- ("complex64", TensorProto.COMPLEX64),
+- ("complex128", TensorProto.COMPLEX128),
+- ("double", TensorProto.DOUBLE),
+- ("float16", TensorProto.FLOAT16),
+- ("float", TensorProto.FLOAT),
+- ("float8e4m3fn", TensorProto.FLOAT8E4M3FN),
+- ("float8e4m3fnuz", TensorProto.FLOAT8E4M3FNUZ),
+- ("float8e5m2", TensorProto.FLOAT8E5M2),
+- ("float8e5m2fnuz", TensorProto.FLOAT8E5M2FNUZ),
+- ("int4", TensorProto.INT4),
+- ("int8", TensorProto.INT8),
+- ("int16", TensorProto.INT16),
+- ("int32", TensorProto.INT32),
+- ("int64", TensorProto.INT64),
+- ("string", TensorProto.STRING),
+- ("uint4", TensorProto.UINT4),
+- ("uint8", TensorProto.UINT8),
+- ("uint16", TensorProto.UINT16),
+- ("uint32", TensorProto.UINT32),
+- ("uint64", TensorProto.UINT64),
+- ]
+- )
+- def test_parse_graph_types(self, name, itype) -> None:
+- w = '{"0"}' if itype == TensorProto.STRING else "{0}"
+- text_graph = f"""
+- <
+- ir_version: 10,
+- opset_import: [ "" : 19]
+- >
+- agraph (float[N] X) => ({name}[N] C)
+- <
+- {name}[1] weight = {w}
+- >
+- {{
+- C = Cast<to={itype}>(X)
+- }}
+- """
+- graph = onnx.parser.parse_model(text_graph)
+- self.assertEqual(len(graph.graph.node), 1)
+-
+
+ if __name__ == "__main__":
+ unittest.main(verbosity=2)
+diff --git a/onnx/test/reference_evaluator_ml_test.py b/onnx/test/reference_evaluator_ml_test.py
+index 3b05da303..10058f9e7 100644
+--- a/onnx/test/reference_evaluator_ml_test.py
++++ b/onnx/test/reference_evaluator_ml_test.py
+@@ -11,7 +11,6 @@ from os import getenv
+
+ import numpy as np # type: ignore
+ from numpy.testing import assert_allclose # type: ignore
+-from parameterized import parameterized
+
+ import onnx
+ from onnx import ONNX_ML, TensorProto, TypeProto, ValueInfoProto
+@@ -907,118 +906,6 @@ class TestReferenceEvaluatorAiOnnxMl(unittest.TestCase):
+ check_model(onx)
+ return onx
+
+- @parameterized.expand(
+- tuple(
+- itertools.chain.from_iterable(
+- (
+- (
+- AggregationFunction.SUM if opset5 else "SUM",
+- np.array(
+- [[0.576923], [0.576923], [0.576923]], dtype=np.float32
+- ),
+- opset5,
+- ),
+- (
+- AggregationFunction.AVERAGE if opset5 else "AVERAGE",
+- np.array(
+- [[0.288462], [0.288462], [0.288462]], dtype=np.float32
+- ),
+- opset5,
+- ),
+- (
+- AggregationFunction.MIN if opset5 else "MIN",
+- np.array(
+- [[0.076923], [0.076923], [0.076923]], dtype=np.float32
+- ),
+- opset5,
+- ),
+- (
+- AggregationFunction.MAX if opset5 else "MAX",
+- np.array([[0.5], [0.5], [0.5]], dtype=np.float32),
+- opset5,
+- ),
+- )
+- for opset5 in [True, False]
+- )
+- )
+- )
+- @unittest.skipIf(not ONNX_ML, reason="onnx not compiled with ai.onnx.ml")
+- def test_tree_ensemble_regressor_aggregation_functions(
+- self, aggregate_function, expected_result, opset5
+- ):
+- x = np.arange(9).reshape((-1, 3)).astype(np.float32) / 10 - 0.5
+- model_factory = (
+- self._get_test_tree_ensemble_opset_latest
+- if opset5
+- else self._get_test_tree_ensemble_regressor
+- )
+- model_proto = model_factory(
+- aggregate_function,
+- )
+- sess = ReferenceEvaluator(model_proto)
+- (actual,) = sess.run(None, {"X": x})
+- assert_allclose(expected_result, actual, atol=1e-6)
+-
+- @parameterized.expand(
+- tuple(
+- itertools.chain.from_iterable(
+- (
+- (
+- Mode.LEQ if opset5 else "BRANCH_LEQ",
+- np.array(
+- [[0.576923], [0.576923], [0.576923]], dtype=np.float32
+- ),
+- opset5,
+- ),
+- (
+- Mode.GT if opset5 else "BRANCH_GT",
+- np.array([[0.5], [0.5], [0.5]], dtype=np.float32),
+- opset5,
+- ),
+- (
+- Mode.LT if opset5 else "BRANCH_LT",
+- np.array(
+- [[0.576923], [0.576923], [0.576923]], dtype=np.float32
+- ),
+- opset5,
+- ),
+- (
+- Mode.GTE if opset5 else "BRANCH_GTE",
+- np.array([[0.5], [0.5], [0.5]], dtype=np.float32),
+- opset5,
+- ),
+- (
+- Mode.EQ if opset5 else "BRANCH_EQ",
+- np.array([[1.0], [1.0], [1.0]], dtype=np.float32),
+- opset5,
+- ),
+- (
+- Mode.NEQ if opset5 else "BRANCH_NEQ",
+- np.array(
+- [[0.076923], [0.076923], [0.076923]], dtype=np.float32
+- ),
+- opset5,
+- ),
+- )
+- for opset5 in [True, False]
+- )
+- )
+- )
+- @unittest.skipIf(not ONNX_ML, reason="onnx not compiled with ai.onnx.ml")
+- def test_tree_ensemble_regressor_rule(self, rule, expected, opset5):
+- x = np.arange(9).reshape((-1, 3)).astype(np.float32) / 10 - 0.5
+- model_factory = (
+- self._get_test_tree_ensemble_opset_latest
+- if opset5
+- else self._get_test_tree_ensemble_regressor
+- )
+- aggregate_function = AggregationFunction.SUM if opset5 else "SUM"
+-
+- model_proto = model_factory(aggregate_function, rule)
+- sess = ReferenceEvaluator(model_proto)
+- (actual,) = sess.run(None, {"X": x})
+- assert_allclose(expected, actual, atol=1e-6)
+-
+ @unittest.skipIf(not ONNX_ML, reason="onnx not compiled with ai.onnx.ml")
+ def test_tree_ensemble_regressor_2_targets_opset3(self):
+ X = make_tensor_value_info("X", TensorProto.FLOAT, [None, None])
+@@ -1132,23 +1019,6 @@ class TestReferenceEvaluatorAiOnnxMl(unittest.TestCase):
+ assert_allclose(expected, got[0], atol=1e-6)
+ self.assertIn("op_type=TreeEnsembleRegressor", str(sess.rt_nodes_[0]))
+
+- @unittest.skipIf(not ONNX_ML, reason="onnx not compiled with ai.onnx.ml")
+- @parameterized.expand(
+- [(input_type,) for input_type in [TensorProto.FLOAT, TensorProto.DOUBLE]]
+- )
+- def test_tree_ensemble_missing_opset5(self, input_type):
+- model = self._get_test_tree_ensemble_opset_latest(
+- AggregationFunction.SUM, Mode.LEQ, True, input_type
+- )
+- np_dtype = onnx.helper.tensor_dtype_to_np_dtype(input_type)
+- x = np.arange(9).reshape((-1, 3)).astype(np_dtype) / 10 - 0.5
+- x[2, 0] = 5
+- x[1, :] = np.nan
+- expected = np.array([[100001.0], [100100.0], [100100.0]], dtype=np_dtype)
+- session = ReferenceEvaluator(model)
+- (actual,) = session.run(None, {"X": x})
+- assert_allclose(expected, actual, atol=1e-6)
+-
+ @unittest.skipIf(not ONNX_ML, reason="onnx not compiled with ai.onnx.ml")
+ def test_tree_ensemble_regressor_missing_opset5_float16(self):
+ model = self._get_test_tree_ensemble_opset_latest(
+diff --git a/onnx/test/reference_evaluator_test.py b/onnx/test/reference_evaluator_test.py
+index c805e1d7b..42a2fbeae 100644
+--- a/onnx/test/reference_evaluator_test.py
++++ b/onnx/test/reference_evaluator_test.py
+@@ -24,7 +24,6 @@ from textwrap import dedent
+ from typing import Sequence
+
+ import numpy as np
+-import parameterized
+ import version_utils
+ from numpy.testing import assert_allclose, assert_almost_equal
+
+@@ -2962,163 +2961,6 @@ class TestReferenceEvaluator(unittest.TestCase):
+ onnx_model = make_model(graph, opset_imports=[make_opsetid("", opset)])
+ return onnx_model
+
+- @parameterized.parameterized.expand(
+- itertools.product(
+- [
+- (
+- "ReduceMin",
+- [
+- np.array(
+- [[np.nan, np.nan], [14.422706, 18.80527]], dtype=np.float32
+- ),
+- np.array([[2, 15], [10, 4]], dtype=np.int64),
+- ],
+- ),
+- (
+- "ReduceL1",
+- [
+- np.array(
+- [[2.2367053, 2.3516612], [4.076292, 4.2970634]],
+- dtype=np.float32,
+- ),
+- np.array([[18, 6], [13, 6]], dtype=np.int64),
+- ],
+- ),
+- (
+- "ReduceL2",
+- [
+- np.array(
+- [[1.80155, 1.8169948], [2.9928076, 3.1205883]],
+- dtype=np.float32,
+- ),
+- np.array([[11, 18], [13, 6]], dtype=np.int64),
+- ],
+- ),
+- (
+- "ReduceLogSum",
+- [
+- np.array(
+- [[0.9497848, 1.1872643], [1.6764175, 1.70759]],
+- dtype=np.float32,
+- ),
+- np.array([[6, 18], [13, 6]], dtype=np.int64),
+- ],
+- ),
+- (
+- "ReduceLogSumExp",
+- [
+- np.array(
+- [[1.6005973, 1.7445935], [2.5616229, 2.6539795]],
+- dtype=np.float32,
+- ),
+- np.array([[13, 6], [13, 6]], dtype=np.int64),
+- ],
+- ),
+- (
+- "ReduceMax",
+- [
+- np.array(
+- [[1.4217108, 1.5069536], [2.453826, 2.5041783]],
+- dtype=np.float32,
+- ),
+- np.array([[13, 11], [13, 11]], dtype=np.int64),
+- ],
+- ),
+- (
+- "ReduceMean",
+- [
+- np.array(
+- [[0.39247903, 0.78497636], [2.038146, 2.1485317]],
+- dtype=np.float32,
+- ),
+- np.array([[13, 6], [13, 6]], dtype=np.int64),
+- ],
+- ),
+- (
+- "ReduceSumSquare",
+- [
+- np.array(
+- [[3.2455828, 3.3014696], [8.956896, 9.7380705]],
+- dtype=np.float32,
+- ),
+- np.array([[11, 18], [13, 6]], dtype=np.int64),
+- ],
+- ),
+- (
+- "ReduceProd",
+- [
+- np.array(
+- [[np.nan, np.nan], [14.422706, 18.80527]], dtype=np.float32
+- ),
+- np.array([[2, 15], [13, 6]], dtype=np.int64),
+- ],
+- ),
+- ],
+- [17, 18],
+- )
+- )
+- def test_op_reduce(self, reduce_op_expected, opset: int):
+- reduce_op, expected = reduce_op_expected
+- X = np.arange(8).reshape((-1, 4)).astype(np.float32)
+-
+- results = {}
+-
+- model = self._cdist_model(opset, reduce_op)
+- sess = ReferenceEvaluator(model)
+- got = sess.run(None, {"input": X})
+- results["ref", opset] = got
+-
+- cl = [
+- n
+- for n in sess.rt_nodes_[0].body.rt_nodes_
+- if n.__class__.__name__.startswith(reduce_op)
+- ]
+- schema = cl[0]._schema
+- new_cl = type(reduce_op, (cl[0].__class__,), {"op_schema": schema})
+- sess = ReferenceEvaluator(model, new_ops=[new_cl])
+- got = sess.run(None, {"input": X})
+- results["ref_cl", opset] = got
+-
+- baseline = "constant"
+- for k, v in results.items():
+- for a, b in zip(reversed(expected), reversed(v)):
+- if a.shape != b.shape:
+- raise AssertionError(
+- f"Shape mismatch for {reduce_op!r}, {baseline}:{a.shape} != {k}:{b.shape}."
+- )
+- diff = np.abs(a - b).max()
+- if diff > 1e-6:
+- raise AssertionError(
+- f"Discrepancies (max={diff}) for {reduce_op!r}, {baseline} != {k}\n{a}\n!=\n{b}"
+- )
+-
+- @parameterized.parameterized.expand(
+- [
+- (13,),
+- (17,),
+- (18,),
+- ]
+- )
+- def test_mvn(self, opset: int, ref_opset: int = 13):
+- X = make_tensor_value_info("X", TensorProto.FLOAT, [None, None, None, None])
+- Y = make_tensor_value_info("Y", TensorProto.FLOAT, [None, None, None, None])
+- nodes = [
+- make_node("MeanVarianceNormalization", ["X"], ["Y"]),
+- ]
+- graph = make_graph(nodes, "g", [X], [Y])
+- x = np.random.rand(3, 3, 3, 1).astype(np.float32)
+-
+- onnx_model = make_model(graph, opset_imports=[make_opsetid("", opset)])
+- ref = ReferenceEvaluator(onnx_model)
+- got = ref.run(None, {"X": x})[0]
+-
+- ref_onnx_model = make_model(graph, opset_imports=[make_opsetid("", ref_opset)])
+- ref_expected = ReferenceEvaluator(ref_onnx_model)
+- expected = ref_expected.run(None, {"X": x})[0]
+-
+- self.assertEqual(expected.shape, got.shape)
+- assert_allclose(expected, got)
+-
+ def test_concat_in_a_function(self):
+ def create_model():
+ nodes = []
+@@ -3800,211 +3642,6 @@ class TestReferenceEvaluator(unittest.TestCase):
+ got = ref.run(None, {"X": data})
+ assert_allclose(expected, got[0])
+
+- @parameterized.parameterized.expand(
+- [
+- (
+- 4 * np.arange(12).reshape(3, 4),
+- np.arange(1, 7).reshape(3, 2),
+- np.zeros((3, 2)),
+- 1,
+- 2,
+- [[0, 4, 4, 6], [5, 7, 6, 7], [6, 7, 7, 7]],
+- ),
+- (
+- 4 * np.arange(12).reshape(3, 4),
+- np.arange(1, 7).reshape(3, 2),
+- np.ones((3, 2)),
+- 1,
+- 2,
+- [[1, 5, 5, 7], [6, 8, 7, 8], [7, 8, 8, 8]],
+- ),
+- (
+- np.arange(24).reshape(3, 8),
+- [[0.25, 0.5, 1], [0.25, 0.5, 1], [0.25, 0.5, 1]],
+- np.zeros((3, 3)),
+- 1,
+- 3,
+- [
+- [0, 4, 8, 6, 8, 10, 6, 7],
+- [32, 36, 40, 22, 24, 26, 14, 15],
+- [64, 68, 72, 38, 40, 42, 22, 23],
+- ],
+- ),
+- (
+- np.arange(6),
+- [0.25, 0.5],
+- [-1, -2],
+- 0,
+- 3,
+- [-1, 3, 7, 4, 6, 8],
+- ),
+- (
+- np.ones((9, 12)),
+- np.ones((3, 4)),
+- np.zeros((3, 4)),
+- 0,
+- 3,
+- None, # Blocked quantization is defined for 1-D blocks only
+- ),
+- (
+- np.ones((3, 4, 5, 6)),
+- np.ones((3, 4)),
+- np.zeros((3, 4)),
+- 2,
+- 2,
+- None, # Scale and ZP must have the same rank as the input
+- ),
+- ]
+- )
+- def test_blocked_quantize_linear(
+- self, x, scale, zero_point, axis, block_size, expected
+- ):
+- X = make_tensor_value_info("X", TensorProto.FLOAT, [None])
+- Y = make_tensor_value_info("Y", TensorProto.INT8, [None])
+-
+- scale_data = np.array(scale, dtype=np.float32)
+- zp_data = np.array(zero_point, dtype=np.int8)
+- model = make_model(
+- make_graph(
+- [
+- make_node(
+- "QuantizeLinear",
+- ["X", "scale", "zero"],
+- ["Y"],
+- axis=axis,
+- block_size=block_size,
+- ),
+- ],
+- "g",
+- [X],
+- [Y],
+- [
+- make_tensor(
+- "scale", TensorProto.FLOAT, scale_data.shape, scale_data
+- ),
+- make_tensor("zero", TensorProto.INT8, scale_data.shape, zp_data),
+- ],
+- )
+- )
+- ref = ReferenceEvaluator(model)
+-
+- data = np.array(x, dtype=np.float32)
+-
+- if expected is not None:
+- expected = np.array(expected, dtype=np.int8)
+- got = ref.run(None, {"X": data})
+- assert_allclose(expected, got[0])
+- else:
+- with self.assertRaises(ValueError):
+- ref.run(None, {"X": data})
+-
+- @parameterized.parameterized.expand(
+- [
+- (
+- np.arange(12).reshape(3, 4),
+- np.arange(1, 7).reshape(3, 2),
+- np.zeros((3, 2)),
+- 1,
+- 2,
+- [[0, 1, 4, 6], [12, 15, 24, 28], [40, 45, 60, 66]],
+- ),
+- (
+- np.arange(12).reshape(3, 4),
+- np.arange(1, 7).reshape(3, 2),
+- np.ones((3, 2)),
+- 1,
+- 2,
+- [[-1, 0, 2, 4], [9, 12, 20, 24], [35, 40, 54, 60]],
+- ),
+- (
+- np.dstack([np.arange(4).reshape(2, 2)] * 4),
+- np.dstack([np.array([[1, 1], [2, 3]]), np.array([[4, 5], [6, 7]])]),
+- np.zeros((2, 2, 2)),
+- 2,
+- 2,
+- [[[0, 0, 0, 0], [1, 1, 5, 5]], [[4, 4, 12, 12], [9, 9, 21, 21]]],
+- ),
+- (
+- np.arange(24).reshape(3, 8),
+- [[2, 1, 3], [2, 1, 3], [2, 1, 3]],
+- np.zeros((3, 3)),
+- 1,
+- 3,
+- [
+- [0, 2, 4, 3, 4, 5, 18, 21],
+- [16, 18, 20, 11, 12, 13, 42, 45],
+- [32, 34, 36, 19, 20, 21, 66, 69],
+- ],
+- ),
+- (
+- np.arange(
+- 6,
+- ),
+- [2, 3],
+- [1, 2],
+- 0,
+- 3,
+- [-2, 0, 2, 3, 6, 9],
+- ),
+- (
+- np.ones((9, 12)),
+- np.ones((3, 4)),
+- np.zeros((3, 4)),
+- 0,
+- 3,
+- None, # Blocked quantization is defined for 1-D blocks only
+- ),
+- (
+- np.ones((3, 4, 5, 6)),
+- np.ones((3, 4)),
+- np.zeros((3, 4)),
+- 2,
+- 2,
+- None, # Scale and ZP must have the same rank as the input
+- ),
+- ]
+- )
+- def test_blocked_dequantize_linear(
+- self, x, scale, zero_point, axis, block_size, expected
+- ):
+- X = make_tensor_value_info("X", TensorProto.INT8, [None])
+- Y = make_tensor_value_info("Y", TensorProto.FLOAT, [None])
+-
+- scale_data = np.array(scale, dtype=np.float32)
+- zp_data = np.array(zero_point, dtype=np.int8)
+- model = make_model(
+- make_graph(
+- [
+- make_node(
+- "DequantizeLinear",
+- ["X", "scale", "zero"],
+- ["Y"],
+- axis=axis,
+- block_size=block_size,
+- ),
+- ],
+- "g",
+- [X],
+- [Y],
+- [
+- make_tensor(
+- "scale", TensorProto.FLOAT, scale_data.shape, scale_data
+- ),
+- make_tensor("zero", TensorProto.INT8, scale_data.shape, zp_data),
+- ],
+- )
+- )
+- ref = ReferenceEvaluator(model)
+- data = np.array(x, dtype=np.int8)
+-
+- if expected is not None:
+- expected = np.array(expected, dtype=np.float32)
+- got = ref.run(None, {"X": data})
+- assert_allclose(expected, got[0])
+- else:
+- with self.assertRaises(ValueError):
+- ref.run(None, {"X": data})
+-
+ def test_lrn(self):
+ def _expected(x, alpha, beta, bias, size):
+ square_sum = np.zeros((5, 5, 5, 5)).astype(np.float32)
+@@ -4189,52 +3826,6 @@ class TestReferenceEvaluator(unittest.TestCase):
+ got = _conv_implementation_im2col(**feeds, **kwargs)
+ assert_allclose(expected, got)
+
+- @parameterized.parameterized.expand(
+- [
+- ("ReduceSum",),
+- ("ReduceL1",),
+- ("ReduceL2",),
+- ("ReduceMin",),
+- ("ReduceMax",),
+- ("ReduceProd",),
+- ("ReduceSumSquare",),
+- ]
+- )
+- def test_reduce_op_no_axis(self, op):
+- X = make_tensor_value_info("X", TensorProto.FLOAT, None)
+- Y = make_tensor_value_info("Y", TensorProto.FLOAT, None)
+- data = np.arange(6).reshape((1, 3, 2)).astype(np.float32)
+- nodes = [make_node(op, ["X"], ["Y"], keepdims=0)]
+- model = make_model(make_graph(nodes, "g", [X], [Y]))
+- ref = ReferenceEvaluator(model)
+- got = ref.run(None, {"X": data})
+- r = got[0]
+- self.assertIsInstance(r, np.ndarray)
+- self.assertEqual(r.shape, ())
+-
+- @parameterized.parameterized.expand([(1,), (2,), (3,), (4,), (5,), (6,)])
+- def test_pad(self, dim):
+- X = make_tensor_value_info("X", TensorProto.FLOAT, None)
+- P = make_tensor_value_info("P", TensorProto.INT64, None)
+- V = make_tensor_value_info("V", TensorProto.FLOAT, None)
+- Y = make_tensor_value_info("Y", TensorProto.FLOAT, None)
+- value = np.array([-5], dtype=np.float32)
+-
+- node = make_node("Pad", inputs=["X", "P", "V"], outputs=["Y"], mode="constant")
+- model = make_model(make_graph([node], "g", [X, P, V], [Y]))
+- ref = ReferenceEvaluator(model)
+- x = np.array([1], dtype=np.float32).reshape((1,) * dim)
+-
+- p = np.array([1, 1] * dim, dtype=np.int64)
+- got = ref.run(None, {"X": x, "P": p, "V": value})[0]
+- self.assertEqual(got.shape, (3,) * dim)
+- self.assertEqual(got.dtype, np.float32)
+-
+- p = np.repeat([7, 3], dim).astype(np.int64)
+- got = ref.run(None, {"X": x, "P": p, "V": value})[0]
+- self.assertEqual(got.shape, (11,) * dim)
+- self.assertEqual(got.dtype, np.float32)
+-
+ def test_constant_of_shape(self):
+ X = make_tensor_value_info("X", TensorProto.FLOAT, None)
+ Y = make_tensor_value_info("Y", TensorProto.FLOAT, None)
+@@ -5345,124 +4936,6 @@ class TestReferenceEvaluator(unittest.TestCase):
+ for i in range(2, -1, -1):
+ assert_allclose(expected[i], got[i])
+
+- @parameterized.parameterized.expand(
+- [
+- (["abc", "def"], [".com", ".net"], ["abc.com", "def.net"], (2,)),
+- (["cat", "dog", "snake"], ["s"], ["cats", "dogs", "snakes"], (3,)),
+- ("cat", "s", "cats", ()),
+- (["a", "ß", "y"], ["a", "ß", "y"], ["aa", "ßß", "yy"], (3,)),
+- ]
+- )
+- def test_string_concat(self, a, b, expected, expected_shape):
+- A = make_tensor_value_info("A", TensorProto.STRING, None)
+- B = make_tensor_value_info("B", TensorProto.STRING, None)
+- Y = make_tensor_value_info("Y", TensorProto.STRING, None)
+- node = make_node("StringConcat", inputs=["A", "B"], outputs=["Y"])
+- model = make_model(make_graph([node], "g", [A, B], [Y]))
+- ref = ReferenceEvaluator(model)
+- result, *_ = ref.run(None, {"A": np.array(a), "B": np.array(b)})
+- np.testing.assert_array_equal(result, expected)
+- self.assertIn(result.dtype.kind, {"O", "U"})
+- self.assertEqual(result.shape, expected_shape)
+-
+- @parameterized.parameterized.expand(
+- [
+- (
+- ["1,2,3", "4,5,6"],
+- ",",
+- None,
+- [["1", "2", "3"], ["4", "5", "6"]],
+- [3, 3],
+- ),
+- (
+- ["1,", "4,6", ""],
+- ",",
+- None,
+- [["1", ""], ["4", "6"], ["", ""]],
+- [2, 2, 1],
+- ),
+- (
+- ["1", "4,6", "4,5,6"],
+- ",",
+- 1,
+- [["1", ""], ["4", "6"], ["4", "5,6"]],
+- [1, 2, 2],
+- ),
+- (
+- [["1,", "4,6", "4,5,6"], ["1,", "4,6", "4,5,6"]],
+- ",",
+- None,
+- [
+- [["1", "", ""], ["4", "6", ""], ["4", "5", "6"]],
+- [["1", "", ""], ["4", "6", ""], ["4", "5", "6"]],
+- ],
+- [[2, 2, 3], [2, 2, 3]],
+- ),
+- (
+- ["hello world !", " hello world !", " hello world ! "],
+- None,
+- None,
+- [
+- ["hello", "world", "!"],
+- ["hello", "world", "!"],
+- ["hello", "world", "!"],
+- ],
+- [3, 3, 3],
+- ),
+- (
+- ["hello world !", " hello world !", " hello world ! "],
+- "",
+- None,
+- [
+- ["hello", "world", "!"],
+- ["hello", "world", "!"],
+- ["hello", "world", "!"],
+- ],
+- [3, 3, 3],
+- ),
+- (
+- ["o-n-n--x-", "o-n----nx"],
+- "-",
+- None,
+- [["o", "n", "n", "", "x", ""], ["o", "n", "", "", "", "nx"]],
+- [6, 6],
+- ),
+- (
+- [],
+- " ",
+- 2,
+- np.array([]).reshape((0, 0)),
+- [],
+- ),
+- ]
+- )
+- def test_string_split(
+- self,
+- x,
+- delimiter,
+- maxsplit,
+- expected_split,
+- expected_num_splits,
+- ):
+- X = make_tensor_value_info("X", TensorProto.STRING, (None))
+- Splits = make_tensor_value_info("Splits", TensorProto.STRING, (None))
+- MaxSplits = make_tensor_value_info("MaxSplits", TensorProto.INT32, (None))
+- node = make_node(
+- "StringSplit",
+- inputs=["X"],
+- outputs=["Splits", "MaxSplits"],
+- delimiter=delimiter,
+- maxsplit=maxsplit,
+- )
+- model = make_model(make_graph([node], "g", [X], [Splits, MaxSplits]))
+- ref = ReferenceEvaluator(model)
+- x = np.array(x, dtype=object)
+- result, num_splits, *_ = ref.run(None, {"X": x})
+- np.testing.assert_array_equal(result, np.array(expected_split, dtype=object))
+- np.testing.assert_array_equal(
+- num_splits, np.array(expected_num_splits, dtype=np.int64)
+- )
+-
+ def test_qlinearconv_int8(self):
+ node = make_node(
+ "QLinearMatMul",
+@@ -5533,47 +5006,6 @@ class TestReferenceEvaluator(unittest.TestCase):
+ np.array([[41, -12, -9], [1, -75, 20]], dtype=np.int8), got[0]
+ )
+
+- @parameterized.parameterized.expand(
+- [
+- (
+- ["www.google.com", "www.facebook.com", "www.bbc.co.uk"],
+- r"www\.[\w.-]+\.\bcom\b",
+- [True, True, False],
+- (3,),
+- ),
+- (
+- [["Onnx", "tensorflow", "Numpy"], ["Pytorch", "Cython", "numba"]],
+- r"^[A-Z][a-z]*$",
+- [[True, False, True], [True, True, False]],
+- (2, 3),
+- ),
+- (
+- [
+- "account@gmail.com",
+- "account@hotmail.com",
+- "not email",
+- "account2@yahoo.com",
+- ],
+- r"(\W|^)[\w.\-]{0,25}@(yahoo|gmail)\.com(\W|$)",
+- [True, False, False, True],
+- (4,),
+- ),
+- ]
+- )
+- @unittest.skipIf(
+- sys.platform == "win32", "google-re2 package is not built for win32"
+- )
+- def test_regex_full_match(self, x, pattern, expected, expected_shape):
+- X = make_tensor_value_info("X", TensorProto.STRING, None)
+- Y = make_tensor_value_info("Y", TensorProto.BOOL, None)
+- node = make_node("RegexFullMatch", inputs=["X"], outputs=["Y"], pattern=pattern)
+- model = make_model(make_graph([node], "g", [X], [Y]))
+- ref = ReferenceEvaluator(model)
+- result, *_ = ref.run(None, {"X": np.array(x)})
+- np.testing.assert_array_equal(result, expected)
+- self.assertEqual(result.dtype.kind, "b")
+- self.assertEqual(result.shape, expected_shape)
+-
+ @unittest.skipIf(
+ sys.platform == "win32", "google-re2 package is not built for win32"
+ )
+@@ -5586,118 +5018,6 @@ class TestReferenceEvaluator(unittest.TestCase):
+ with self.assertRaises(ValueError):
+ ref.run(None, {"X": np.array(["x"])})
+
+- @parameterized.parameterized.expand(
+- [
+- (
+- TensorProto.UINT4,
+- [-1, 0, 1.5, 2, 3.3, 10, 20, 40],
+- [0, 0, 2, 2, 4, 10, 20, 30],
+- ),
+- (TensorProto.UINT4, [-1, 0, 1.5, 2, 3.3, 10, 40], [0, 0, 2, 2, 4, 10, 30]),
+- (TensorProto.UINT4, [0], [0]),
+- (
+- TensorProto.INT4,
+- [-20, -14.5, 0, 1.5, 2, 3.3, 10, 20],
+- [-16, -14, 0, 2, 2, 4, 10, 14],
+- ),
+- (
+- TensorProto.INT4,
+- [-20, -14.5, 0, 1.5, 2, 3.3, 10],
+- [-16, -14, 0, 2, 2, 4, 10],
+- ),
+- (TensorProto.INT4, [0], [0]),
+- ]
+- )
+- @unittest.skipIf(
+- version_utils.numpy_older_than("1.22.0"),
+- "The test requires numpy 1.22.0 or later",
+- )
+- def test_quantize_linear_int4(self, qtype, data, expected):
+- X = make_tensor_value_info("X", TensorProto.FLOAT, [None])
+- Y = make_tensor_value_info("Y", TensorProto.FLOAT, [None])
+- model = make_model(
+- make_graph(
+- [
+- make_node(
+- "Constant",
+- [],
+- ["scale"],
+- value=make_tensor("scale", TensorProto.FLOAT, [1], [2.0]),
+- ),
+- make_node(
+- "Constant",
+- [],
+- ["zero"],
+- value=make_tensor("zero", qtype, [1], [0]),
+- ),
+- make_node("QuantizeLinear", ["X", "scale", "zero"], ["T"]),
+- make_node("DequantizeLinear", ["T", "scale"], ["Y"], axis=0),
+- ],
+- "g",
+- [X],
+- [Y],
+- )
+- )
+- ref = ReferenceEvaluator(model)
+- got = ref.run(None, {"X": np.asarray(data)})
+- assert_allclose(expected, got[0])
+-
+- @parameterized.parameterized.expand(
+- itertools.product(
+- (TensorProto.FLOAT, TensorProto.FLOAT16),
+- (TensorProto.UINT4, TensorProto.INT4),
+- )
+- )
+- def test_cast_int4_output(self, cast_from, cast_to):
+- X = make_tensor_value_info("X", cast_from, [None])
+- Y = make_tensor_value_info("Y", cast_to, [None])
+- model = make_model(
+- make_graph(
+- [
+- make_node("Cast", ["X"], ["Y"], to=cast_to),
+- ],
+- "g",
+- [X],
+- [Y],
+- )
+- )
+- ref = ReferenceEvaluator(model)
+- data = np.array([0, 1, 2.4, 2.6, 4, 10], dtype=np.float32)
+- signed = cast_to == TensorProto.INT4
+- expected1 = np.array(
+- [subbyte.float32_to_4bit_unpacked(x, signed=signed) for x in data]
+- )
+- got = ref.run(None, {"X": data})
+- self.assertEqual(expected1.tolist(), got[0].tolist())
+-
+- @parameterized.parameterized.expand(
+- itertools.product(
+- (TensorProto.UINT4, TensorProto.INT4),
+- (TensorProto.FLOAT, TensorProto.FLOAT16),
+- )
+- )
+- def test_cast_int4_input(self, cast_from, cast_to):
+- X = make_tensor_value_info("X", cast_from, [None])
+- Y = make_tensor_value_info("Y", cast_to, [None])
+- model = make_model(
+- make_graph(
+- [
+- make_node("Cast", ["X"], ["Y"], to=TensorProto.FLOAT),
+- ],
+- "g",
+- [X],
+- [Y],
+- )
+- )
+- ref = ReferenceEvaluator(model)
+- data = np.array(range(7), dtype=np.float32)
+- cast_from_np = custom.uint4 if cast_from == TensorProto.UINT4 else custom.int4
+- expected1 = np.array(
+- [subbyte.float32_to_4bit_unpacked(x, cast_from_np) for x in data]
+- )
+- got = ref.run(None, {"X": data})
+- self.assertEqual(expected1.tolist(), got[0].tolist())
+-
+ def test_a_function_calling_a_function_once(self):
+ X = make_tensor_value_info("X", TensorProto.FLOAT, ["N"])
+ output = make_tensor_value_info("output", TensorProto.FLOAT, ["N"])
+@@ -5930,97 +5250,6 @@ class TestReferenceEvaluator(unittest.TestCase):
+ for v in oinf.functions_.values():
+ self.assertIsInstance(v, MyReferenceEvaluator)
+
+- @parameterized.parameterized.expand(
+- [
+- ("UINT4", 0.84),
+- ("INT4", 0.84),
+- ("FLOAT8E4M3FN", 0.23),
+- ("FLOAT8E4M3FNUZ", 0.23),
+- ("FLOAT8E5M2", 0.85),
+- ("FLOAT8E5M2FNUZ", 0.85),
+- ("DOUBLE", 0),
+- ("FLOAT", 0),
+- ("FLOAT16", 2e-3),
+- ("BFLOAT16", 2e-2),
+- ]
+- )
+- @skip_if_no_ml_dtypes
+- def test_add_custom_dtype(self, stype, atol):
+- itype = getattr(TensorProto, stype)
+- model = make_model(
+- make_graph(
+- [
+- make_node("Cast", ["X"], ["Xc"], to=itype),
+- make_node("Cast", ["Y"], ["Yc"], to=itype),
+- make_node("Add", ["Xc", "Yc"], ["Zc"]),
+- make_node("Cast", ["Zc"], ["Z"], to=TensorProto.FLOAT),
+- ],
+- "nd",
+- [
+- make_tensor_value_info("X", TensorProto.FLOAT, [None, None, None]),
+- make_tensor_value_info("Y", TensorProto.FLOAT, [None, None, None]),
+- ],
+- [make_tensor_value_info("Z", TensorProto.FLOAT, [None, None, None])],
+- ),
+- opset_imports=[make_opsetid("", 18)],
+- ir_version=9,
+- )
+-
+- ref = ReferenceEvaluator(model, verbose=0)
+-
+- x = (np.arange(18) / 6).reshape((2, 3, 3)).astype(np.float32)
+- y = (np.arange(18) / 9).reshape((2, 3, 3)).astype(np.float32)
+- feeds = dict(X=x, Y=y)
+- expected = x + y
+- got = ref.run(None, feeds)[0]
+- assert_allclose(expected, got, atol=atol)
+-
+- @parameterized.parameterized.expand(
+- [
+- ("DOUBLE",),
+- ("FLOAT",),
+- ("FLOAT16",),
+- ("BFLOAT16",),
+- # Comparison fails with ml_dtypes
+- # ("FLOAT8E4M3FN", ),
+- # ("FLOAT8E4M3FNUZ", ),
+- # ("FLOAT8E5M2", ),
+- # ("FLOAT8E5M2FNUZ", ),
+- # ("INT4", ),
+- # ("UINT4", ),
+- ]
+- )
+- @skip_if_no_ml_dtypes
+- def test_cmp_custom_dtype(self, stype):
+- itype = getattr(TensorProto, stype)
+- model = make_model(
+- make_graph(
+- [
+- make_node("Cast", ["X"], ["Xc"], to=itype),
+- make_node("Cast", ["Y"], ["Yc"], to=itype),
+- make_node("Greater", ["Xc", "Yc"], ["Zc"]),
+- make_node("Cast", ["Zc"], ["Z"], to=TensorProto.BOOL),
+- ],
+- "nd",
+- [
+- make_tensor_value_info("X", TensorProto.FLOAT, [None, None, None]),
+- make_tensor_value_info("Y", TensorProto.FLOAT, [None, None, None]),
+- ],
+- [make_tensor_value_info("Z", TensorProto.FLOAT, [None, None, None])],
+- ),
+- opset_imports=[make_opsetid("", 18)],
+- ir_version=9,
+- )
+-
+- ref = ReferenceEvaluator(model)
+-
+- x = (np.arange(18) / 18).reshape((2, 3, 3)).astype(np.float32)
+- y = ((np.arange(18) - 9) / 18).reshape((2, 3, 3)).astype(np.float32)
+- feeds = dict(X=x, Y=y)
+- expected = x >= y
+- got = ref.run(None, feeds)[0]
+- assert_almost_equal(expected, got)
+-
+ def test_scatter_elements_4d(self):
+ model = make_model(
+ make_graph(
+diff --git a/onnx/test/schema_test.py b/onnx/test/schema_test.py
+index b40f933f7..1d74fcda4 100644
+--- a/onnx/test/schema_test.py
++++ b/onnx/test/schema_test.py
+@@ -7,8 +7,6 @@ import contextlib
+ import unittest
+ from typing import Sequence
+
+-import parameterized
+-
+ import onnx
+ from onnx import defs
+
+@@ -211,34 +209,6 @@ class TestFormalParameter(unittest.TestCase):
+ )
+
+
+-class TestTypeConstraintParam(unittest.TestCase):
+- @parameterized.parameterized.expand(
+- [
+- ("single_type", "T", ["tensor(float)"], "Test description"),
+- (
+- "double_types",
+- "T",
+- ["tensor(float)", "tensor(int64)"],
+- "Test description",
+- ),
+- ("tuple", "T", ("tensor(float)", "tensor(int64)"), "Test description"),
+- ]
+- )
+- def test_init(
+- self,
+- _: str,
+- type_param_str: str,
+- allowed_types: Sequence[str],
+- description: str,
+- ) -> None:
+- type_constraint = defs.OpSchema.TypeConstraintParam(
+- type_param_str, allowed_types, description
+- )
+- self.assertEqual(type_constraint.description, description)
+- self.assertEqual(type_constraint.allowed_type_strs, list(allowed_types))
+- self.assertEqual(type_constraint.type_param_str, type_param_str)
+-
+-
+ class TestAttribute(unittest.TestCase):
+ def test_init(self):
+ name = "test_attr"
+@@ -261,169 +231,5 @@ class TestAttribute(unittest.TestCase):
+ self.assertEqual("attr1 description", attribute.description)
+
+
+-@parameterized.parameterized_class(
+- [
+- # register to exist domain
+- {
+- "op_type": "CustomOp",
+- "op_version": 5,
+- "op_domain": "",
+- "trap_op_version": [1, 2, 6, 7],
+- },
+- # register to new domain
+- {
+- "op_type": "CustomOp",
+- "op_version": 5,
+- "op_domain": "test",
+- "trap_op_version": [1, 2, 6, 7],
+- },
+- ]
+-)
+-class TestOpSchemaRegister(unittest.TestCase):
+- op_type: str
+- op_version: int
+- op_domain: str
+- # register some fake schema to check behavior
+- trap_op_version: list[int]
+-
+- def setUp(self) -> None:
+- # Ensure the schema is unregistered
+- self.assertFalse(onnx.defs.has(self.op_type, self.op_domain))
+-
+- def tearDown(self) -> None:
+- # Clean up the registered schema
+- for version in [*self.trap_op_version, self.op_version]:
+- with contextlib.suppress(onnx.defs.SchemaError):
+- onnx.defs.deregister_schema(self.op_type, version, self.op_domain)
+-
+- def test_register_multi_schema(self):
+- for version in [*self.trap_op_version, self.op_version]:
+- op_schema = defs.OpSchema(
+- self.op_type,
+- self.op_domain,
+- version,
+- )
+- onnx.defs.register_schema(op_schema)
+- self.assertTrue(onnx.defs.has(self.op_type, version, self.op_domain))
+- for version in [*self.trap_op_version, self.op_version]:
+- # Also make sure the `op_schema` is accessible after register
+- registered_op = onnx.defs.get_schema(
+- op_schema.name, version, op_schema.domain
+- )
+- op_schema = defs.OpSchema(
+- self.op_type,
+- self.op_domain,
+- version,
+- )
+- self.assertEqual(str(registered_op), str(op_schema))
+-
+- def test_using_the_specified_version_in_onnx_check(self):
+- input = f"""
+- <
+- ir_version: 7,
+- opset_import: [
+- "{self.op_domain}" : {self.op_version}
+- ]
+- >
+- agraph (float[N, 128] X, int32 Y) => (float[N] Z)
+- {{
+- Z = {self.op_domain}.{self.op_type}<attr1=[1,2]>(X, Y)
+- }}
+- """
+- model = onnx.parser.parse_model(input)
+- op_schema = defs.OpSchema(
+- self.op_type,
+- self.op_domain,
+- self.op_version,
+- inputs=[
+- defs.OpSchema.FormalParameter("input1", "T"),
+- defs.OpSchema.FormalParameter("input2", "int32"),
+- ],
+- outputs=[
+- defs.OpSchema.FormalParameter("output1", "T"),
+- ],
+- type_constraints=[("T", ["tensor(float)"], "")],
+- attributes=[
+- defs.OpSchema.Attribute(
+- "attr1", defs.OpSchema.AttrType.INTS, "attr1 description"
+- )
+- ],
+- )
+- with self.assertRaises(onnx.checker.ValidationError):
+- onnx.checker.check_model(model, check_custom_domain=True)
+- onnx.defs.register_schema(op_schema)
+- # The fake schema will raise check exception if selected in checker
+- for version in self.trap_op_version:
+- onnx.defs.register_schema(
+- defs.OpSchema(
+- self.op_type,
+- self.op_domain,
+- version,
+- outputs=[
+- defs.OpSchema.FormalParameter("output1", "int32"),
+- ],
+- )
+- )
+- onnx.checker.check_model(model, check_custom_domain=True)
+-
+- def test_register_schema_raises_error_when_registering_a_schema_twice(self):
+- op_schema = defs.OpSchema(
+- self.op_type,
+- self.op_domain,
+- self.op_version,
+- )
+- onnx.defs.register_schema(op_schema)
+- with self.assertRaises(onnx.defs.SchemaError):
+- onnx.defs.register_schema(op_schema)
+-
+- def test_deregister_the_specified_schema(self):
+- for version in [*self.trap_op_version, self.op_version]:
+- op_schema = defs.OpSchema(
+- self.op_type,
+- self.op_domain,
+- version,
+- )
+- onnx.defs.register_schema(op_schema)
+- self.assertTrue(onnx.defs.has(op_schema.name, version, op_schema.domain))
+- onnx.defs.deregister_schema(op_schema.name, self.op_version, op_schema.domain)
+- for version in self.trap_op_version:
+- self.assertTrue(onnx.defs.has(op_schema.name, version, op_schema.domain))
+- # Maybe has lesser op version in trap list
+- if onnx.defs.has(op_schema.name, self.op_version, op_schema.domain):
+- schema = onnx.defs.get_schema(
+- op_schema.name, self.op_version, op_schema.domain
+- )
+- self.assertLess(schema.since_version, self.op_version)
+-
+- def test_deregister_schema_raises_error_when_opschema_does_not_exist(self):
+- with self.assertRaises(onnx.defs.SchemaError):
+- onnx.defs.deregister_schema(self.op_type, self.op_version, self.op_domain)
+-
+- def test_legacy_schema_accessible_after_deregister(self):
+- op_schema = defs.OpSchema(
+- self.op_type,
+- self.op_domain,
+- self.op_version,
+- )
+- onnx.defs.register_schema(op_schema)
+- schema_a = onnx.defs.get_schema(
+- op_schema.name, op_schema.since_version, op_schema.domain
+- )
+- schema_b = onnx.defs.get_schema(op_schema.name, op_schema.domain)
+-
+- def filter_schema(schemas):
+- return [op for op in schemas if op.name == op_schema.name]
+-
+- schema_c = filter_schema(onnx.defs.get_all_schemas())
+- schema_d = filter_schema(onnx.defs.get_all_schemas_with_history())
+- self.assertEqual(len(schema_c), 1)
+- self.assertEqual(len(schema_d), 1)
+- # Avoid memory residue and access storage as much as possible
+- self.assertEqual(str(schema_a), str(op_schema))
+- self.assertEqual(str(schema_b), str(op_schema))
+- self.assertEqual(str(schema_c[0]), str(op_schema))
+- self.assertEqual(str(schema_d[0]), str(op_schema))
+-
+-
+ if __name__ == "__main__":
+ unittest.main()
+diff --git a/onnx/test/shape_inference_test.py b/onnx/test/shape_inference_test.py
+index 9e6b96b5b..2425bc339 100644
+--- a/onnx/test/shape_inference_test.py
++++ b/onnx/test/shape_inference_test.py
+@@ -10,7 +10,6 @@ from typing import Any, Sequence
+
+ import numpy as np
+ import pytest
+-from parameterized import parameterized
+
+ import onnx.shape_inference
+ from onnx import (
+@@ -238,86 +237,6 @@ class TestShapeInference(TestShapeInferenceHelper):
+ graph, [make_tensor_value_info("y", TensorProto.FLOAT, (30, 4, 5))]
+ )
+
+- @parameterized.expand(all_versions_for("Transpose"))
+- def test_transpose(self, _, version) -> None:
+- graph = self._make_graph(
+- [("X", TensorProto.FLOAT, (2, 3, 4))],
+- [make_node("Transpose", ["X"], ["Y"], perm=[1, 0, 2])],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("Y", TensorProto.FLOAT, (3, 2, 4))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Transpose"))
+- def test_transpose_preexisting(self, _, version) -> None:
+- graph = self._make_graph(
+- [("X", TensorProto.FLOAT, (2, 3, 4))],
+- [make_node("Transpose", ["X"], ["Y"], perm=[1, 0, 2])],
+- [make_tensor_value_info("Y", TensorProto.FLOAT, None)],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("Y", TensorProto.FLOAT, (3, 2, 4))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Transpose"))
+- def test_transpose_scalar(self, _, version) -> None:
+- graph = self._make_graph(
+- [("X", TensorProto.FLOAT, ())],
+- [make_node("Transpose", ["X"], ["Y"])],
+- [],
+- )
+-
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("Y", TensorProto.FLOAT, ())],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Transpose"))
+- def test_transpose_partial(self, _, version) -> None:
+- graph = self._make_graph(
+- [("X", TensorProto.FLOAT, (2, 3, 4))],
+- [make_node("Transpose", ["X"], ["Y"], perm=[1, 0, 2])],
+- [make_tensor_value_info("Y", TensorProto.UNDEFINED, (3, "a", "b"))],
+- ) # type: ignore
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("Y", TensorProto.FLOAT, (3, 2, 4))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Transpose"))
+- def test_transpose_preexisting_incorrect_shape(self, *_) -> None:
+- graph = self._make_graph(
+- [("X", TensorProto.FLOAT, (2, 3, 4))],
+- [make_node("Transpose", ["X"], ["Y"], perm=[1, 0, 2])],
+- [make_tensor_value_info("Y", TensorProto.FLOAT, (5, 5, 5))],
+- )
+- self.assertRaises(onnx.shape_inference.InferenceError, self._inferred, graph)
+-
+- @parameterized.expand(all_versions_for("Transpose"))
+- def test_transpose_preexisting_incorrect_type(self, *_) -> None:
+- graph = self._make_graph(
+- [("X", TensorProto.FLOAT, (2, 3, 4))],
+- [make_node("Transpose", ["X"], ["Y"], perm=[1, 0, 2])],
+- [make_tensor_value_info("Y", TensorProto.STRING, (3, 2, 4))],
+- )
+- self.assertRaises(onnx.shape_inference.InferenceError, self._inferred, graph)
+-
+- @parameterized.expand(all_versions_for("Transpose"))
+- def test_transpose_incorrect_repeated_perm(self, *_) -> None:
+- graph = self._make_graph(
+- [("X", TensorProto.FLOAT, (2, 3, 4))],
+- [make_node("Transpose", ["X"], ["Y"], perm=[1, 0, 1])],
+- [],
+- )
+- self.assertRaises(onnx.shape_inference.InferenceError, self._inferred, graph)
+-
+ def _make_matmul_test_all_dims_known(
+ self, version, shape1: Sequence[int], shape2: Sequence[int]
+ ) -> None:
+@@ -327,1343 +246,59 @@ class TestShapeInference(TestShapeInferenceHelper):
+ ).shape
+ graph = self._make_graph(
+ [("x", TensorProto.FLOAT, shape1), ("y", TensorProto.FLOAT, shape2)],
+- [make_node("MatMul", ["x", "y"], ["z"])],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("z", TensorProto.FLOAT, expected_out_shape)],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("MatMul"))
+- def test_matmul_all_dims_known(self, _, version) -> None:
+- self._make_matmul_test_all_dims_known(version, (2,), (2,))
+-
+- self._make_matmul_test_all_dims_known(version, (4, 2), (2, 4))
+- self._make_matmul_test_all_dims_known(version, (5, 2), (2, 4))
+- self._make_matmul_test_all_dims_known(version, (5, 2), (2, 1))
+- self._make_matmul_test_all_dims_known(version, (1, 2), (2, 3))
+- self._make_matmul_test_all_dims_known(version, (2,), (2, 3))
+- self._make_matmul_test_all_dims_known(version, (4, 2), (2,))
+- self._make_matmul_test_all_dims_known(version, (1, 4, 2), (3, 2, 3))
+- self._make_matmul_test_all_dims_known(version, (3, 4, 2), (3, 2, 3))
+- self._make_matmul_test_all_dims_known(version, (5, 1, 4, 2), (1, 3, 2, 3))
+- self._make_matmul_test_all_dims_known(version, (4, 2), (3, 2, 3))
+-
+- def _make_matmul_test_allow_unknown(
+- self, version, shape1: Any, shape2: Any, expected_out_shape: Any
+- ) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, shape1), ("y", TensorProto.FLOAT, shape2)],
+- [make_node("MatMul", ["x", "y"], ["z"])],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("z", TensorProto.FLOAT, expected_out_shape)],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("MatMul"))
+- def test_matmul_allow_unknown(self, _, version) -> None:
+- self._make_matmul_test_allow_unknown(version, (None,), (None,), ())
+- self._make_matmul_test_allow_unknown(version, (3,), (None,), ())
+- self._make_matmul_test_allow_unknown(version, (2,), (2, "a"), ("a",))
+- self._make_matmul_test_allow_unknown(version, (4, 2), (2, "a"), (4, "a"))
+- self._make_matmul_test_allow_unknown(version, (4, None), (2, "a"), (4, "a"))
+- self._make_matmul_test_allow_unknown(version, (4, None), (None, "a"), (4, "a"))
+- self._make_matmul_test_allow_unknown(
+- version, (1, 4, 2), ("a", 2, 5), ("a", 4, 5)
+- )
+- self._make_matmul_test_allow_unknown(
+- version, (1, 3, 4, 2), ("a", 2, 5), (1, 3, 4, 5)
+- )
+- self._make_matmul_test_allow_unknown(version, (3,), None, None)
+- self._make_matmul_test_allow_unknown(version, None, None, None)
+-
+- @parameterized.expand(all_versions_for("Cast"))
+- def test_cast(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (2, 4, 3))],
+- [make_node("Cast", ["x"], ["y"], to=TensorProto.UINT8)],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.UINT8, (2, 4, 3))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Cast"))
+- @unittest.skip(
+- "Issue #5960"
+- ) # FIXME(#5960) propagateElemTypeFromAttributeToOutput does not validate against output type constraints
+- def test_cast_to_complex(self, _, version) -> None: # noqa: ARG002
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (2, 4, 3))],
+- [make_node("Cast", ["x"], ["y"], to=TensorProto.COMPLEX128)],
+- [],
+- )
+-
+- self.assertRaises(onnx.shape_inference.InferenceError, self._inferred, graph)
+-
+- @parameterized.expand(all_versions_for("CastLike"))
+- def test_cast_like(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (2, 4, 3)), ("t", TensorProto.FLOAT16, ("N",))],
+- [make_node("CastLike", ["x", "t"], ["y"])],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.FLOAT16, (2, 4, 3))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Col2Im"))
+- def test_col2im(self, _, version) -> None:
+- graph = self._make_graph(
+- [
+- ("input", TensorProto.FLOAT, (1, 5, 5)),
+- ("output_shape", TensorProto.INT64, (2,)),
+- ("kernel_shape", TensorProto.INT64, (2,)),
+- ],
+- [
+- make_node(
+- "Col2Im", ["input", "output_shape", "kernel_shape"], ["output"]
+- )
+- ],
+- [],
+- initializer=[
+- make_tensor("output_shape", TensorProto.INT64, (2,), (5, 5)),
+- make_tensor("kernel_shape", TensorProto.INT64, (2,), (1, 5)),
+- ],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("output", TensorProto.FLOAT, (1, 1, 5, 5))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Col2Im"))
+- def test_col2im_strides(self, _, version) -> None:
+- graph = self._make_graph(
+- [
+- ("input", TensorProto.FLOAT, (1, 9, 4)),
+- ("output_shape", TensorProto.INT64, (2,)),
+- ("kernel_shape", TensorProto.INT64, (2,)),
+- ],
+- [
+- make_node(
+- "Col2Im",
+- ["input", "output_shape", "kernel_shape"],
+- ["output"],
+- strides=[2, 2],
+- )
+- ],
+- [],
+- initializer=[
+- make_tensor("output_shape", TensorProto.INT64, (2,), (5, 5)),
+- make_tensor("kernel_shape", TensorProto.INT64, (2,), (3, 3)),
+- ],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("output", TensorProto.FLOAT, (1, 1, 5, 5))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Col2Im"))
+- def test_col2im_pads(self, _, version) -> None:
+- graph = self._make_graph(
+- [
+- ("input", TensorProto.FLOAT, (1, 5, 15)),
+- ("output_shape", TensorProto.INT64, (2,)),
+- ("kernel_shape", TensorProto.INT64, (2,)),
+- ],
+- [
+- make_node(
+- "Col2Im",
+- ["input", "output_shape", "kernel_shape"],
+- ["output"],
+- pads=[0, 1, 0, 1],
+- )
+- ],
+- [],
+- initializer=[
+- make_tensor("output_shape", TensorProto.INT64, (2,), (5, 5)),
+- make_tensor("kernel_shape", TensorProto.INT64, (2,), (1, 5)),
+- ],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("output", TensorProto.FLOAT, (1, 1, 5, 5))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Col2Im"))
+- def test_col2im_dilations(self, _, version) -> None:
+- graph = self._make_graph(
+- [
+- ("input", TensorProto.FLOAT, (1, 4, 5)),
+- ("output_shape", TensorProto.INT64, (2,)),
+- ("kernel_shape", TensorProto.INT64, (2,)),
+- ],
+- [
+- make_node(
+- "Col2Im",
+- ["input", "output_shape", "kernel_shape"],
+- ["output"],
+- dilations=[1, 5],
+- )
+- ],
+- [],
+- initializer=[
+- make_tensor("output_shape", TensorProto.INT64, (2,), (6, 6)),
+- make_tensor("kernel_shape", TensorProto.INT64, (2,), (2, 2)),
+- ],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("output", TensorProto.FLOAT, (1, 1, 6, 6))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Col2Im"))
+- def test_col2im_5d(self, _, version) -> None:
+- graph = self._make_graph(
+- [
+- ("input", TensorProto.FLOAT, (1, 10, 12)),
+- ("output_shape", TensorProto.INT64, (3,)),
+- ("kernel_shape", TensorProto.INT64, (3,)),
+- ],
+- [
+- make_node(
+- "Col2Im", ["input", "output_shape", "kernel_shape"], ["output"]
+- )
+- ],
+- [],
+- initializer=[
+- make_tensor("output_shape", TensorProto.INT64, (3,), (3, 4, 5)),
+- make_tensor("kernel_shape", TensorProto.INT64, (3,), (1, 1, 5)),
+- ],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("output", TensorProto.FLOAT, (1, 2, 3, 4, 5))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Concat"))
+- def test_concat(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (2, 4, 3)), ("y", TensorProto.FLOAT, (7, 4, 3))],
+- [make_node("Concat", ["x", "y"], ["z"], axis=0)],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("z", TensorProto.FLOAT, (9, 4, 3))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Concat"))
+- def test_concat_missing_shape(self, *_) -> None:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.FLOAT, (2, 4, 3)),
+- "y",
+- ("z", TensorProto.FLOAT, (None, None, None)),
+- ],
+- [make_node("Concat", ["x", "y", "z"], ["out"], axis=0)],
+- [],
+- )
+- self.assertRaises(onnx.shape_inference.InferenceError, self._inferred, graph)
+-
+- @parameterized.expand(all_versions_for("Concat"))
+- def test_concat_3d_axis_2(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (2, 2, 2)), ("y", TensorProto.FLOAT, (2, 2, 2))],
+- [make_node("Concat", ["x", "y"], ["z"], axis=2)],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("z", TensorProto.FLOAT, (2, 2, 4))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Concat"))
+- def test_concat_param(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, ("a", 2)), ("y", TensorProto.FLOAT, ("a", 3))],
+- [make_node("Concat", ["x", "y"], ["z"], axis=1)],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("z", TensorProto.FLOAT, ("a", 5))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Concat"))
+- def test_concat_param_single_input(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, ("a", 2))],
+- [make_node("Concat", ["x"], ["z"], axis=0)],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("z", TensorProto.FLOAT, ("a", 2))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Reshape"))
+- def test_reshape_dynamic_shape_known_rank(self, _, version) -> None:
+- self.skipIf(version < 14, "Rank inference is added from Version 14")
+- graph = self._make_graph(
+- [("x", TensorProto.UINT8, (2, 4, 3)), ("shape", TensorProto.INT64, (2,))],
+- [make_node("Reshape", ["x", "shape"], ["y"])],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.UINT8, (None, None))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Reshape"))
+- def test_reshape_dynamic_shape_symbolic(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.UINT8, (2, 4, 3)), ("shape", TensorProto.INT64, ("M",))],
+- [make_node("Reshape", ["x", "shape"], ["y"])],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.UINT8, None)],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Reshape"))
+- def test_reshape_dynamic_unknown_shape(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.UINT8, (2, 4, 3)), ("shape", TensorProto.INT64, None)],
+- [make_node("Reshape", ["x", "shape"], ["y"])],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.UINT8, None)],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Reshape"))
+- def test_reshape_static_shape(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.UINT8, (2, 4, 3)), ("shape", TensorProto.INT64, (2,))],
+- [make_node("Reshape", ["x", "shape"], ["y"])],
+- [],
+- initializer=[make_tensor("shape", TensorProto.INT64, (2,), (3, 8))],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.UINT8, (3, 8))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Reshape"))
+- def test_reshape_static_shape_inferred(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.UINT8, (2, 4, 3)), ("shape", TensorProto.INT64, (3,))],
+- [make_node("Reshape", ["x", "shape"], ["y"])],
+- [],
+- initializer=[make_tensor("shape", TensorProto.INT64, (3,), (0, 3, -1))],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.UINT8, (2, 3, 4))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Reshape"))
+- def test_reshape_static_shape_zero(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.UINT8, (1, 1, 1)), ("shape", TensorProto.INT64, (3,))],
+- [make_node("Reshape", ["x", "shape"], ["y"])],
+- [],
+- initializer=[make_tensor("shape", TensorProto.INT64, (3,), (0, 1, 1))],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.UINT8, (1, 1, 1))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Reshape"))
+- def test_reshape_static_shape_allowzero(self, _, version) -> None:
+- self.skipIf(version < 14, "allowzero is added from Version 14")
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.UINT8, (1, 0, 0)),
+- ("shape", TensorProto.INT64, (3,)),
+- ],
+- [make_node("Reshape", ["x", "shape"], ["y"], allowzero=1)],
+- [],
+- initializer=[make_tensor("shape", TensorProto.INT64, (3,), (0, 1, 1))],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.UINT8, (0, 1, 1))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Reshape"))
+- def test_reshape_static_shape_constant(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.UINT8, (2, 4, 3))],
+- [
+- make_node(
+- "Constant",
+- [],
+- ["shape"],
+- value=make_tensor("shape", TensorProto.INT64, (2,), (3, 8)),
+- ),
+- make_node("Reshape", ["x", "shape"], ["y"]),
+- ],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [
+- make_tensor_value_info("shape", TensorProto.INT64, (2,)),
+- make_tensor_value_info("y", TensorProto.UINT8, (3, 8)),
+- ],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Upsample"))
+- def test_upsample(self, _, version) -> None:
+- if version == 7:
+- graph = self._make_graph(
+- [("x", TensorProto.INT32, (2, 4, 3, 5))],
+- [make_node("Upsample", ["x"], ["y"], scales=[1.0, 1.1, 1.3, 1.9])],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 4, 3, 9))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+- else:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (2, 4, 3, 5)),
+- ("scales", TensorProto.FLOAT, (4,)),
+- ],
+- [make_node("Upsample", ["x", "scales"], ["y"])],
+- [],
+- initializer=[
+- make_tensor("scales", TensorProto.FLOAT, (4,), (1.0, 1.1, 1.3, 1.9))
+- ],
+- )
+-
+- def call_inference():
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 4, 3, 9))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- if version == 9:
+- call_inference()
+- else:
+- # Upsample is deprecated since Version 10.
+- with self.assertRaises(onnx.checker.ValidationError) as cm:
+- call_inference()
+- exception = cm.exception
+- assert "Upsample is deprecated" in str(exception)
+-
+- @parameterized.expand(all_versions_for("Upsample"))
+- def test_upsample_raw_data(self, _, version) -> None:
+- if version == 7:
+- graph = self._make_graph(
+- [("x", TensorProto.INT32, (1, 3, 4, 5))],
+- [make_node("Upsample", ["x"], ["y"], scales=[2.0, 1.1, 2.3, 1.9])],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 3, 9, 9))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+- else:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (2, 4, 3, 5)),
+- ("scales", TensorProto.FLOAT, (4,)),
+- ],
+- [make_node("Upsample", ["x", "scales"], ["y"])],
+- [],
+- initializer=[
+- make_tensor(
+- "scales",
+- TensorProto.FLOAT,
+- (4,),
+- vals=np.array([1.0, 1.1, 1.3, 1.9], dtype="<f4").tobytes(),
+- raw=True,
+- )
+- ],
+- ) # Feed raw bytes (force little endian ordering like onnx standard) for test purpose
+-
+- def call_inference():
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 4, 3, 9))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- if version == 9:
+- call_inference()
+- else:
+- # Upsample is deprecated since Version 10.
+- with self.assertRaises(onnx.checker.ValidationError) as cm:
+- call_inference()
+- exception = cm.exception
+- assert "Upsample is deprecated" in str(exception)
+-
+- @parameterized.expand(all_versions_for("Expand"))
+- def test_expand(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.INT32, (3, 1)), ("shape", TensorProto.INT64, (3,))],
+- [make_node("Expand", ["x", "shape"], ["y"])],
+- [],
+- initializer=[make_tensor("shape", TensorProto.INT64, (3,), (2, 1, 6))],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 3, 6))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Expand"))
+- def test_expand_scalar_input(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.INT32, ()), ("shape", TensorProto.INT64, (2,))],
+- [make_node("Expand", ["x", "shape"], ["y"])],
+- [],
+- initializer=[make_tensor("shape", TensorProto.INT64, (2,), (4, 8))],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (4, 8))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Expand"))
+- def test_expand_raw_data(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.INT32, (3, 1)), ("shape", TensorProto.INT64, (2,))],
+- [make_node("Expand", ["x", "shape"], ["y"])],
+- [],
+- initializer=[
+- make_tensor(
+- "shape",
+- TensorProto.INT64,
+- (2,),
+- vals=np.array([3, 4], dtype="<i8").tobytes(),
+- raw=True,
+- )
+- ],
+- ) # Feed raw bytes (force little endian ordering like onnx standard) for test purpose
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (3, 4))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Expand"))
+- def test_expand_dynamic_shape(self, _, version) -> None:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (1, 2, None)),
+- ("shape", TensorProto.INT64, (3,)),
+- ],
+- [make_node("Expand", ["x", "shape"], ["y"])],
+- [],
+- initializer=[],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (None, 2, None))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Expand"))
+- def test_expand_symbolic_shape(self, _, version) -> None:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (1, 2, None)),
+- ("shape", TensorProto.INT64, ("unk__0",)),
+- ],
+- [make_node("Expand", ["x", "shape"], ["y"])],
+- [],
+- initializer=[],
+- )
+- # if giving a symbolic shape, Expand should not infer any shape or rank inference
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, None)],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Resize"))
+- def test_resize_size(self, _, version) -> None:
+- if version == 10:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (2, 4, 3, 5)),
+- ("scales", TensorProto.FLOAT, (4,)),
+- ],
+- [make_node("Resize", ["x", "scales"], ["y"])],
+- [],
+- initializer=[
+- make_tensor("scales", TensorProto.FLOAT, (4,), (1.0, 1.1, 1.3, 1.9))
+- ],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 4, 3, 9))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+- elif version == 11:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (2, 4, 3, 5)),
+- ("roi", TensorProto.FLOAT, (8,)),
+- ("scales", TensorProto.FLOAT, (4,)),
+- ("sizes", TensorProto.INT64, (4,)),
+- ],
+- [make_node("Resize", ["x", "roi", "scales", "sizes"], ["y"])],
+- [],
+- initializer=[
+- make_tensor("sizes", TensorProto.INT64, (4,), (3, 5, 6, 7))
+- ],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (3, 5, 6, 7))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+- else:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (2, 4, 3, 5)),
+- ("roi", TensorProto.FLOAT, (8,)),
+- ("sizes", TensorProto.INT64, (4,)),
+- ],
+- [make_node("Resize", ["x", "roi", "", "sizes"], ["y"])],
+- [],
+- initializer=[
+- make_tensor("sizes", TensorProto.INT64, (4,), (3, 5, 6, 7))
+- ],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (3, 5, 6, 7))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Resize"))
+- def test_resize_size_axes_2_3(self, _, version) -> None:
+- self.skipIf(version < 18, "axes is from Version 18")
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (2, 4, 3, 5)),
+- ("roi", TensorProto.FLOAT, (4,)),
+- ("sizes", TensorProto.INT64, (2,)),
+- ],
+- [make_node("Resize", ["x", "roi", "", "sizes"], ["y"], axes=(2, 3))],
+- [],
+- initializer=[make_tensor("sizes", TensorProto.INT64, (2,), (6, 7))],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 4, 6, 7))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Resize"))
+- def test_resize_size_axes_3_2(self, _, version) -> None:
+- self.skipIf(version < 18, "axes is from Version 18")
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (2, 4, 3, 5)),
+- ("roi", TensorProto.FLOAT, (4,)),
+- ("sizes", TensorProto.INT64, (2,)),
+- ],
+- [make_node("Resize", ["x", "roi", "", "sizes"], ["y"], axes=(3, 2))],
+- [],
+- initializer=[make_tensor("sizes", TensorProto.INT64, (2,), (6, 7))],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 4, 7, 6))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Resize"))
+- def test_resize_size_not_larger(self, _, version) -> None:
+- self.skipIf(
+- version < 18,
+- "keep_aspect_ratio_policy is from Version 18",
+- )
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (3, 5)),
+- ("roi", TensorProto.FLOAT, (4,)),
+- ("sizes", TensorProto.INT64, (2,)),
+- ],
+- [
+- make_node(
+- "Resize",
+- ["x", "roi", "", "sizes"],
+- ["y"],
+- keep_aspect_ratio_policy="not_larger",
+- )
+- ],
+- [],
+- initializer=[make_tensor("sizes", TensorProto.INT64, (2,), (6, 6))],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (4, 6))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Resize"))
+- def test_resize_size_axes_2_3_not_larger(self, _, version) -> None:
+- self.skipIf(
+- version < 18,
+- "axes & keep_aspect_ratio_policy are from Version 18",
+- )
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (2, 4, 3, 5)),
+- ("roi", TensorProto.FLOAT, (4,)),
+- ("sizes", TensorProto.INT64, (2,)),
+- ],
+- [
+- make_node(
+- "Resize",
+- ["x", "roi", "", "sizes"],
+- ["y"],
+- axes=(2, 3),
+- keep_aspect_ratio_policy="not_larger",
+- )
+- ],
+- [],
+- initializer=[make_tensor("sizes", TensorProto.INT64, (2,), (6, 6))],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 4, 4, 6))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Resize"))
+- def test_resize_size_not_smaller(self, _, version) -> None:
+- self.skipIf(
+- version < 18,
+- "keep_aspect_ratio_policy is from Version 18",
+- )
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (3, 5)),
+- ("roi", TensorProto.FLOAT, (4,)),
+- ("sizes", TensorProto.INT64, (2,)),
+- ],
+- [
+- make_node(
+- "Resize",
+- ["x", "roi", "", "sizes"],
+- ["y"],
+- keep_aspect_ratio_policy="not_smaller",
+- )
+- ],
+- [],
+- initializer=[make_tensor("sizes", TensorProto.INT64, (2,), (6, 6))],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (6, 10))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Resize"))
+- def test_resize_size_axes_2_3_not_smaller(self, _, version) -> None:
+- self.skipIf(
+- version < 18,
+- "axes & keep_aspect_ratio_policy are from Version 18",
+- )
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (2, 4, 3, 5)),
+- ("roi", TensorProto.FLOAT, (4,)),
+- ("sizes", TensorProto.INT64, (2,)),
+- ],
+- [
+- make_node(
+- "Resize",
+- ["x", "roi", "", "sizes"],
+- ["y"],
+- axes=(2, 3),
+- keep_aspect_ratio_policy="not_smaller",
+- )
+- ],
+- [],
+- initializer=[make_tensor("sizes", TensorProto.INT64, (2,), (6, 6))],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 4, 6, 10))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Resize"))
+- def test_resize_scale(self, _, version) -> None:
+- self.skipIf(version < 11, "roi input is from Version 11")
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (2, 4, 3, 5)),
+- ("roi", TensorProto.FLOAT, (8,)),
+- ("scales", TensorProto.FLOAT, (4,)),
+- ],
+- [make_node("Resize", ["x", "roi", "scales"], ["y"])],
+- [],
+- initializer=[
+- make_tensor("scales", TensorProto.FLOAT, (4,), (1.0, 1.1, 1.3, 1.9))
+- ],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 4, 3, 9))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Resize"))
+- def test_resize_scale_axes_2_3(self, _, version) -> None:
+- self.skipIf(version < 18, "axes is from Version 18")
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (2, 4, 3, 5)),
+- ("roi", TensorProto.FLOAT, (8,)),
+- ("scales", TensorProto.FLOAT, (2,)),
+- ],
+- [make_node("Resize", ["x", "roi", "scales"], ["y"], axes=(2, 3))],
+- [],
+- initializer=[make_tensor("scales", TensorProto.FLOAT, (2,), (1.3, 1.9))],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 4, 3, 9))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Resize"))
+- def test_resize_scale_axes_3_2(self, _, version) -> None:
+- self.skipIf(version < 18, "axes is from Version 18")
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (2, 4, 3, 5)),
+- ("roi", TensorProto.FLOAT, (8,)),
+- ("scales", TensorProto.FLOAT, (2,)),
+- ],
+- [make_node("Resize", ["x", "roi", "scales"], ["y"], axes=(3, 2))],
+- [],
+- initializer=[make_tensor("scales", TensorProto.FLOAT, (2,), (1.9, 1.3))],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 4, 3, 9))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Resize"))
+- def test_resize_scale_raw_data(self, _, version) -> None:
+- self.skipIf(version < 11, "roi input is from Version 11")
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (1, 3, 4, 5)),
+- ("roi", TensorProto.FLOAT, (8,)),
+- ("scales", TensorProto.FLOAT, (4,)),
+- ],
+- [make_node("Resize", ["x", "roi", "scales"], ["y"])],
+- [],
+- initializer=[
+- make_tensor(
+- "scales",
+- TensorProto.FLOAT,
+- (4,),
+- vals=np.array([2.0, 1.1, 2.3, 1.9], dtype="<f4").tobytes(),
+- raw=True,
+- )
+- ],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 3, 9, 9))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Resize"))
+- def test_resize_scale_and_size_but_one_is_empty(self, _, version) -> None:
+- self.skipIf(version < 11, "roi input is from Version 11")
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (1, 3, 4, 5)),
+- ("roi", TensorProto.FLOAT, (8,)),
+- ("scales", TensorProto.FLOAT, (4,)),
+- ("sizes", TensorProto.INT64, (0,)),
+- ],
+- [make_node("Resize", ["x", "roi", "scales", "sizes"], ["y"])],
+- [],
+- initializer=[
+- make_tensor(
+- "scales",
+- TensorProto.FLOAT,
+- (4,),
+- vals=np.array([2.0, 1.1, 2.3, 1.9], dtype="<f4").tobytes(),
+- raw=True,
+- ),
+- make_tensor(
+- "sizes",
+- TensorProto.INT64,
+- (0,),
+- vals=np.array([], dtype="<i8").tobytes(),
+- raw=True,
+- ),
+- ],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 3, 9, 9))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Resize"))
+- def test_resize_opset11_scales_is_empty(self, _, version) -> None:
+- self.skipIf(version != 11, "This test only works for Version 11")
+- # "scales" input in Resize in opset11 is not optional. It must be an empty tensor
+- # if sizes is needed. Shape inference for Resize shall handle this case.
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.INT32, (1, 3, 4, 5)),
+- ("roi", TensorProto.FLOAT, (8,)),
+- ("scales", TensorProto.FLOAT, (0,)),
+- ("sizes", TensorProto.INT64, (4,)),
+- ],
+- [make_node("Resize", ["x", "roi", "scales", "sizes"], ["y"])],
+- [],
+- initializer=[
+- make_tensor(
+- "sizes",
+- TensorProto.INT64,
+- (4,),
+- vals=np.array(
+- [2, 6, 8, 10], dtype="<i8"
+- ).tobytes(), # double in all dimensions
+- raw=True,
+- ),
+- ],
+- )
+-
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT32, (2, 6, 8, 10))],
+- opset_imports=[helper.make_opsetid("", version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Shape"))
+- def test_shape(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (2, 4, 3))],
+- [make_node("Shape", ["x"], ["y"])],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT64, (3,))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Shape"))
+- def test_shape_start_1(self, _, version) -> None:
+- self.skipIf(version < 15, "start and end are from Version 15")
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (2, 4, 3))],
+- [make_node("Shape", ["x"], ["y"], start=1)],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT64, (2,))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Shape"))
+- def test_shape_end_1(self, _, version) -> None:
+- self.skipIf(version < 15, "start and end are from Version 15")
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (2, 4, 3))],
+- [make_node("Shape", ["x"], ["y"], end=1)],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT64, (1,))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Shape"))
+- def test_shape_negative_start(self, _, version) -> None:
+- self.skipIf(version < 15, "start and end are from Version 15")
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (2, 4, 3))],
+- [make_node("Shape", ["x"], ["y"], start=-1)],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT64, (1,))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Shape"))
+- def test_shape_clip1(self, _, version) -> None:
+- self.skipIf(version < 15, "start and end are from Version 15")
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (2, 4, 3))],
+- [make_node("Shape", ["x"], ["y"], start=-5)],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT64, (3,))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Shape"))
+- def test_shape_clip2(self, _, version) -> None:
+- self.skipIf(version < 15, "start and end are from Version 15")
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (2, 4, 3))],
+- [make_node("Shape", ["x"], ["y"], end=10)],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT64, (3,))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Size"))
+- def test_size(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (2, 4, 3))], [make_node("Size", ["x"], ["y"])], []
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT64, ())],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Gather"))
+- def test_gather(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (4, 3)), ("i", TensorProto.INT64, (2,))],
+- [make_node("Gather", ["x", "i"], ["y"])],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.FLOAT, (2, 3))], # type: ignore
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Gather"))
+- def test_gather_axis1(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (4, 3, 5)), ("i", TensorProto.INT64, (1, 2))],
+- [make_node("Gather", ["x", "i"], ["y"], axis=1)],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.FLOAT, (4, 1, 2, 5))], # type: ignore
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Gather"))
+- def test_gather_into_scalar(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (3,)), ("i", TensorProto.INT64, ())],
+- [make_node("Gather", ["x", "i"], ["y"])],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.FLOAT, ())],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("GatherElements"))
+- def test_gather_elements(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (2, 2)), ("i", TensorProto.INT64, (2, 2))],
+- [make_node("GatherElements", ["x", "i"], ["y"], axis=1)],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.FLOAT, (2, 2))], # type: ignore
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("GatherElements"))
+- def test_gather_elements_axis0(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (3, 3)), ("i", TensorProto.INT64, (2, 3))],
+- [make_node("GatherElements", ["x", "i"], ["y"], axis=0)],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.FLOAT, (2, 3))], # type: ignore
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("Scatter"))
+- def test_scatter(self, _, version) -> None:
+- if version >= 11:
+- # Scatter is deprecated in domain_version of 11.
+- with self.assertRaises(onnx.checker.ValidationError) as cm:
+- self._test_scatter(version)
+- exception = cm.exception
+- assert "Scatter is deprecated" in str(exception)
+- else:
+- self._test_scatter(version)
+-
+- def _test_scatter(self, version) -> None:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.FLOAT, (3, 3)),
+- ("i", TensorProto.INT64, (2, 3)),
+- ("u", TensorProto.FLOAT, (2, 3)),
+- ],
+- [make_node("Scatter", ["x", "i", "u"], ["y"])],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.FLOAT, (3, 3))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- ) # type: ignore
+-
+- @parameterized.expand(all_versions_for("Scatter"))
+- def test_scatter_axis1(self, _, version) -> None:
+- if version >= 11:
+- # Scatter is deprecated in domain_version of 11.
+- with self.assertRaises(onnx.checker.ValidationError) as cm:
+- self._test_scatter_axis1(version)
+- exception = cm.exception
+- assert "Scatter is deprecated" in str(exception)
+- else:
+- self._test_scatter_axis1(version)
+-
+- def _test_scatter_axis1(self, version) -> None:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.FLOAT, (1, 5)),
+- ("i", TensorProto.INT64, (1, 2)),
+- ("u", TensorProto.FLOAT, (1, 2)),
+- ],
+- [make_node("Scatter", ["x", "i", "u"], ["y"], axis=1)],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.FLOAT, (1, 5))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- ) # type: ignore
+-
+- @parameterized.expand(all_versions_for("ScatterElements"))
+- def test_scatter_elements(self, _, version) -> None:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.FLOAT, (3, 3)),
+- ("i", TensorProto.INT64, (2, 3)),
+- ("u", TensorProto.FLOAT, (2, 3)),
+- ],
+- [make_node("ScatterElements", ["x", "i", "u"], ["y"])],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.FLOAT, (3, 3))], # type: ignore
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("ScatterElements"))
+- def test_scatter_elements_axis1(self, _, version) -> None:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.FLOAT, (1, 5)),
+- ("i", TensorProto.INT64, (1, 2)),
+- ("u", TensorProto.FLOAT, (1, 2)),
+- ],
+- [make_node("ScatterElements", ["x", "i", "u"], ["y"], axis=1)],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.FLOAT, (1, 5))], # type: ignore
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("ScatterND"))
+- def test_scatternd(self, _, version) -> None:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.FLOAT, (4, 5, 6)),
+- ("indices", TensorProto.INT64, (3, 3, 2)),
+- ("updates", TensorProto.FLOAT, (3, 3, 6)),
+- ],
+- [make_node("ScatterND", ["x", "indices", "updates"], ["y"])],
++ [make_node("MatMul", ["x", "y"], ["z"])],
+ [],
+ )
+ self._assert_inferred(
+ graph,
+- [make_tensor_value_info("y", TensorProto.FLOAT, (4, 5, 6))], # type: ignore
++ [make_tensor_value_info("z", TensorProto.FLOAT, expected_out_shape)],
+ opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+ )
+
+- @parameterized.expand(all_versions_for("ScatterND"))
+- def test_scatternd_noshape(self, _, version) -> None:
+- # The shape of 'x_reshaped' cannot be inferred, since it is the output of a dynamic reshape.
+- # Thus the shape of 'y' is also None.
++ def _make_matmul_test_allow_unknown(
++ self, version, shape1: Any, shape2: Any, expected_out_shape: Any
++ ) -> None:
+ graph = self._make_graph(
+- [
+- ("x", TensorProto.FLOAT, (4, 5, 6)),
+- ("indices", TensorProto.INT64, (3, 3, 2)),
+- ("updates", TensorProto.FLOAT, (3, 3, 6)),
+- ("shape", TensorProto.INT64, ("M",)),
+- ],
+- [
+- make_node("Reshape", ["x", "shape"], ["x_reshaped"]),
+- make_node("ScatterND", ["x_reshaped", "indices", "updates"], ["y"]),
+- ],
++ [("x", TensorProto.FLOAT, shape1), ("y", TensorProto.FLOAT, shape2)],
++ [make_node("MatMul", ["x", "y"], ["z"])],
+ [],
+ )
+ self._assert_inferred(
+ graph,
+- [
+- make_tensor_value_info("x_reshaped", TensorProto.FLOAT, None),
+- make_tensor_value_info("y", TensorProto.FLOAT, None),
+- ],
++ [make_tensor_value_info("z", TensorProto.FLOAT, expected_out_shape)],
+ opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- ) # type: ignore
+-
+- @parameterized.expand(all_versions_for("Squeeze"))
+- def test_squeeze(self, _, version) -> None:
+- if version == 11:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (1, 3, 1, 1, 2, 1))],
+- [make_node("Squeeze", "x", "y", axes=[0, 2, 3, 5])],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.FLOAT, (3, 2))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+- else:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.FLOAT, (1, 3, 1, 1, 2, 1)),
+- ("axes", TensorProto.INT64, (4,)),
+- ],
+- [make_node("Squeeze", ["x", "axes"], "y")],
+- [],
+- initializer=[
+- make_tensor("axes", TensorProto.INT64, (4,), (0, 2, 3, 5))
+- ],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.FLOAT, (3, 2))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
++ )
+
+- @parameterized.expand(all_versions_for("StringConcat"))
+- def test_stringconcat(self, _, version) -> None:
++ def _test_scatter(self, version) -> None:
+ graph = self._make_graph(
+ [
+- ("x", TensorProto.STRING, (2, 3, 4)),
+- ("y", TensorProto.STRING, (2, 3, 4)),
++ ("x", TensorProto.FLOAT, (3, 3)),
++ ("i", TensorProto.INT64, (2, 3)),
++ ("u", TensorProto.FLOAT, (2, 3)),
+ ],
+- [make_node("StringConcat", ["x", "y"], "z")],
++ [make_node("Scatter", ["x", "i", "u"], ["y"])],
+ [],
+ )
+ self._assert_inferred(
+ graph,
+- [make_tensor_value_info("z", TensorProto.STRING, (2, 3, 4))],
++ [make_tensor_value_info("y", TensorProto.FLOAT, (3, 3))],
+ opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("StringConcat"))
+- def test_stringconcat_broadcasting(self, _, version) -> None:
++ ) # type: ignore
++ def _test_scatter_axis1(self, version) -> None:
+ graph = self._make_graph(
+ [
+- ("x", TensorProto.STRING, (2, 3, 4)),
+- ("y", TensorProto.STRING, (1, 3, 1)),
++ ("x", TensorProto.FLOAT, (1, 5)),
++ ("i", TensorProto.INT64, (1, 2)),
++ ("u", TensorProto.FLOAT, (1, 2)),
+ ],
+- [make_node("StringConcat", ["x", "y"], "z")],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("z", TensorProto.STRING, (2, 3, 4))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("RegexFullMatch"))
+- def test_regex_full_match(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.STRING, (2, 4, 3, 9))],
+- [make_node("RegexFullMatch", ["x"], ["y"], pattern=r"^[A-Z][a-z]*$")],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.BOOL, (2, 4, 3, 9))],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("RegexFullMatch"))
+- def test_regex_full_match_empty_shape(self, _, version) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.STRING, ())],
+- [make_node("RegexFullMatch", ["x"], ["y"], pattern=r"^[A-Z][a-z]*$")],
++ [make_node("Scatter", ["x", "i", "u"], ["y"], axis=1)],
+ [],
+ )
+ self._assert_inferred(
+ graph,
+- [make_tensor_value_info("y", TensorProto.BOOL, ())],
++ [make_tensor_value_info("y", TensorProto.FLOAT, (1, 5))],
+ opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
++ ) # type: ignore
+
+ def test_squeeze_no_axes_opset11(self) -> None:
+ graph = self._make_graph(
+@@ -5304,23 +3939,6 @@ class TestShapeInference(TestShapeInferenceHelper):
+ self._make_matmulinteger_test((5, 1, 4, 2), (1, 3, 2, 3))
+ self._make_matmulinteger_test((4, 2), (3, 2, 3))
+
+- @parameterized.expand(
+- [onnx.TensorProto.FLOAT, onnx.TensorProto.FLOAT16, onnx.TensorProto.BFLOAT16]
+- )
+- def test_quantizelinear(self, elem_type) -> None:
+- graph = self._make_graph(
+- [
+- ("x", elem_type, (30, 4, 5)),
+- ("y_scale", elem_type, ()),
+- ("y_zero_point", TensorProto.UINT8, ()),
+- ],
+- [make_node("QuantizeLinear", ["x", "y_scale", "y_zero_point"], ["y"])],
+- [],
+- )
+- self._assert_inferred(
+- graph, [make_tensor_value_info("y", TensorProto.UINT8, (30, 4, 5))]
+- )
+-
+ def test_quantizelinear_default_zp(self) -> None:
+ graph = self._make_graph(
+ [("x", TensorProto.FLOAT, (30, 4, 5)), ("y_scale", TensorProto.FLOAT, ())],
+@@ -5426,23 +4044,6 @@ class TestShapeInference(TestShapeInferenceHelper):
+ graph,
+ )
+
+- @parameterized.expand(
+- [onnx.TensorProto.FLOAT, onnx.TensorProto.FLOAT16, onnx.TensorProto.BFLOAT16]
+- )
+- def test_dequantizelinear(self, elem_type) -> None:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.UINT8, (30, 4, 5)),
+- ("x_scale", elem_type, ()),
+- ("x_zero_point", TensorProto.UINT8, ()),
+- ],
+- [make_node("DequantizeLinear", ["x", "x_scale", "x_zero_point"], ["y"])],
+- [],
+- )
+- self._assert_inferred(
+- graph, [make_tensor_value_info("y", elem_type, (30, 4, 5))]
+- )
+-
+ def test_dynamicquantizelinear(self) -> None:
+ graph = self._make_graph(
+ [("x", TensorProto.FLOAT, (30, 4, 5))],
+@@ -5551,383 +4152,125 @@ class TestShapeInference(TestShapeInferenceHelper):
+ make_tensor(
+ "repeats",
+ TensorProto.INT64,
+- (3,),
+- vals=np.array([1, 2, 3], dtype="<i8").tobytes(),
+- raw=True,
+- )
+- ],
+- ) # Feed raw bytes (force little endian ordering like onnx standard) for test purpose
+- self._assert_inferred(
+- graph, [make_tensor_value_info("y", TensorProto.FLOAT, (4, 10, 18))]
+- )
+-
+- def test_tile_rank_inference(self) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (4, 5, 6)), ("repeats", TensorProto.INT64, (3,))],
+- [make_node("Tile", ["x", "repeats"], ["y"])],
+- [],
+- )
+- self._assert_inferred(graph, [make_tensor_value_info("y", TensorProto.FLOAT, (None, None, None))]) # type: ignore
+-
+- @unittest.skipUnless(ONNX_ML, "ONNX_ML required to test ai.onnx.ml operators")
+- def test_linearclassifier_1D_input(self) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (5,))],
+- [
+- make_node(
+- "LinearClassifier",
+- ["x"],
+- ["y", "z"],
+- domain=ONNX_ML_DOMAIN,
+- coefficients=[0.0008, -0.0008],
+- intercepts=[2.0, 2.0],
+- classlabels_ints=[1, 2],
+- )
+- ],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [
+- make_tensor_value_info("y", TensorProto.INT64, (1,)),
+- make_tensor_value_info("z", TensorProto.FLOAT, (1, 2)),
+- ],
+- opset_imports=[
+- make_opsetid(ONNX_ML_DOMAIN, 1),
+- make_opsetid(ONNX_DOMAIN, 11),
+- ],
+- )
+-
+- @unittest.skipUnless(ONNX_ML, "ONNX_ML required to test ai.onnx.ml operators")
+- def test_linearclassifier_2D_input(self) -> None:
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (4, 5))],
+- [
+- make_node(
+- "LinearClassifier",
+- ["x"],
+- ["y", "z"],
+- domain=ONNX_ML_DOMAIN,
+- coefficients=[0.1, 0.2, 0.3, 0.4, 0.5, 0.6],
+- intercepts=[2.0, 2.0, 3.0],
+- classlabels_ints=[1, 2, 3],
+- )
+- ],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [
+- make_tensor_value_info("y", TensorProto.INT64, (4,)),
+- make_tensor_value_info("z", TensorProto.FLOAT, (4, 3)),
+- ],
+- opset_imports=[
+- make_opsetid(ONNX_ML_DOMAIN, 1),
+- make_opsetid(ONNX_DOMAIN, 11),
+- ],
+- )
+-
+- def test_roialign_symbolic(self) -> None:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.FLOAT, ("N", "C", "H", "W")),
+- ("rois", TensorProto.FLOAT, ("num_rois", 4)),
+- ("batch_indices", TensorProto.INT64, ("num_rois",)),
+- ],
+- [
+- make_node(
+- "RoiAlign",
+- ["x", "rois", "batch_indices"],
+- ["y"],
+- output_height=10,
+- output_width=5,
+- )
+- ],
+- [],
+- )
+- self._assert_inferred(graph, [make_tensor_value_info("y", TensorProto.FLOAT, ("num_rois", "C", 10, 5))]) # type: ignore
+-
+- def test_roialign_symbolic_defaults(self) -> None:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.FLOAT, ("N", "C", "H", "W")),
+- ("rois", TensorProto.FLOAT, ("num_rois", 4)),
+- ("batch_indices", TensorProto.INT64, ("num_rois",)),
+- ],
+- [make_node("RoiAlign", ["x", "rois", "batch_indices"], ["y"])],
+- [],
+- )
+- self._assert_inferred(graph, [make_tensor_value_info("y", TensorProto.FLOAT, ("num_rois", "C", 1, 1))]) # type: ignore
+-
+- def test_roialign_num_rois(self) -> None:
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.FLOAT, ("N", "C", "H", "W")),
+- ("rois", TensorProto.FLOAT, ("num_rois", 4)),
+- ("batch_indices", TensorProto.INT64, (15,)),
+- ],
+- [make_node("RoiAlign", ["x", "rois", "batch_indices"], ["y"])],
+- [],
+- )
+- self._assert_inferred(graph, [make_tensor_value_info("y", TensorProto.FLOAT, (15, "C", 1, 1))]) # type: ignore
+-
+- @parameterized.expand(
+- all_versions_for("LabelEncoder") if ONNX_ML else [], skip_on_empty=True
+- )
+- def test_label_encoder_string_int64(self, _, version) -> None:
+- self.skipIf(
+- version < 2, "keys_* attributes were introduced in ai.onnx.ml opset 2"
+- )
+- string_list = ["A", "m", "y"]
+- float_list = [94.17, 36.00, -99.0]
+- int64_list = [12, 28, 86]
+- graph = self._make_graph(
+- [("x", TensorProto.STRING, (6, 1))],
+- [
+- make_node(
+- "LabelEncoder",
+- ["x"],
+- ["y"],
+- domain=ONNX_ML_DOMAIN,
+- keys_strings=string_list,
+- values_int64s=int64_list,
+- )
+- ],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT64, (6, 1))],
+- opset_imports=[
+- make_opsetid(ONNX_ML_DOMAIN, version),
+- make_opsetid(ONNX_DOMAIN, 11),
+- ],
+- )
+-
+- graph = self._make_graph(
+- [("x", TensorProto.INT64, (2, 3))],
+- [
+- make_node(
+- "LabelEncoder",
+- ["x"],
+- ["y"],
+- domain=ONNX_ML_DOMAIN,
+- keys_int64s=int64_list,
+- values_strings=string_list,
+- )
+- ],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.STRING, (2, 3))],
+- opset_imports=[
+- make_opsetid(ONNX_ML_DOMAIN, version),
+- make_opsetid(ONNX_DOMAIN, 11),
+- ],
+- )
+-
+- graph = self._make_graph(
+- [("x", TensorProto.FLOAT, (2,))],
+- [
+- make_node(
+- "LabelEncoder",
+- ["x"],
+- ["y"],
+- domain=ONNX_ML_DOMAIN,
+- keys_floats=float_list,
+- values_int64s=int64_list,
+- )
+- ],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT64, (2,))],
+- opset_imports=[
+- make_opsetid(ONNX_ML_DOMAIN, version),
+- make_opsetid(ONNX_DOMAIN, 11),
++ (3,),
++ vals=np.array([1, 2, 3], dtype="<i8").tobytes(),
++ raw=True,
++ )
+ ],
++ ) # Feed raw bytes (force little endian ordering like onnx standard) for test purpose
++ self._assert_inferred(
++ graph, [make_tensor_value_info("y", TensorProto.FLOAT, (4, 10, 18))]
+ )
+
++ def test_tile_rank_inference(self) -> None:
+ graph = self._make_graph(
+- [("x", TensorProto.INT64, (8,))],
+- [
+- make_node(
+- "LabelEncoder",
+- ["x"],
+- ["y"],
+- domain=ONNX_ML_DOMAIN,
+- keys_int64s=int64_list,
+- values_floats=float_list,
+- )
+- ],
++ [("x", TensorProto.FLOAT, (4, 5, 6)), ("repeats", TensorProto.INT64, (3,))],
++ [make_node("Tile", ["x", "repeats"], ["y"])],
+ [],
+ )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.FLOAT, (8,))],
+- opset_imports=[
+- make_opsetid(ONNX_ML_DOMAIN, version),
+- make_opsetid(ONNX_DOMAIN, 11),
+- ],
+- )
++ self._assert_inferred(graph, [make_tensor_value_info("y", TensorProto.FLOAT, (None, None, None))]) # type: ignore
+
++ @unittest.skipUnless(ONNX_ML, "ONNX_ML required to test ai.onnx.ml operators")
++ def test_linearclassifier_1D_input(self) -> None:
+ graph = self._make_graph(
+- [("x", TensorProto.FLOAT, ())],
++ [("x", TensorProto.FLOAT, (5,))],
+ [
+ make_node(
+- "LabelEncoder",
++ "LinearClassifier",
+ ["x"],
+- ["y"],
++ ["y", "z"],
+ domain=ONNX_ML_DOMAIN,
+- keys_floats=float_list,
+- values_strings=string_list,
++ coefficients=[0.0008, -0.0008],
++ intercepts=[2.0, 2.0],
++ classlabels_ints=[1, 2],
+ )
+ ],
+ [],
+ )
+ self._assert_inferred(
+ graph,
+- [make_tensor_value_info("y", TensorProto.STRING, ())],
++ [
++ make_tensor_value_info("y", TensorProto.INT64, (1,)),
++ make_tensor_value_info("z", TensorProto.FLOAT, (1, 2)),
++ ],
+ opset_imports=[
+- make_opsetid(ONNX_ML_DOMAIN, version),
++ make_opsetid(ONNX_ML_DOMAIN, 1),
+ make_opsetid(ONNX_DOMAIN, 11),
+ ],
+ )
+
++ @unittest.skipUnless(ONNX_ML, "ONNX_ML required to test ai.onnx.ml operators")
++ def test_linearclassifier_2D_input(self) -> None:
+ graph = self._make_graph(
+- [("x", TensorProto.STRING, (1, 2))],
++ [("x", TensorProto.FLOAT, (4, 5))],
+ [
+ make_node(
+- "LabelEncoder",
++ "LinearClassifier",
+ ["x"],
+- ["y"],
++ ["y", "z"],
+ domain=ONNX_ML_DOMAIN,
+- keys_strings=string_list,
+- values_floats=float_list,
++ coefficients=[0.1, 0.2, 0.3, 0.4, 0.5, 0.6],
++ intercepts=[2.0, 2.0, 3.0],
++ classlabels_ints=[1, 2, 3],
+ )
+ ],
+ [],
+ )
+ self._assert_inferred(
+ graph,
+- [make_tensor_value_info("y", TensorProto.FLOAT, (1, 2))],
++ [
++ make_tensor_value_info("y", TensorProto.INT64, (4,)),
++ make_tensor_value_info("z", TensorProto.FLOAT, (4, 3)),
++ ],
+ opset_imports=[
+- make_opsetid(ONNX_ML_DOMAIN, version),
++ make_opsetid(ONNX_ML_DOMAIN, 1),
+ make_opsetid(ONNX_DOMAIN, 11),
+ ],
+ )
+
+- @parameterized.expand(
+- all_versions_for("LabelEncoder") if ONNX_ML else [], skip_on_empty=True
+- )
+- def test_label_encoder_tensor_attributes(self, _, version) -> None:
+- self.skipIf(
+- version < 4, "tensor attributes were introduced in ai.onnx.ml opset 4"
+- )
+- key_tensor = make_tensor(
+- "keys_tensor", TensorProto.STRING, [4], ["a", "b", "cc", "ddd"]
+- )
+- values_tensor = make_tensor(
+- "values_tensor", TensorProto.INT64, [4], [1, 2, 3, 4]
+- )
++ def test_roialign_symbolic(self) -> None:
+ graph = self._make_graph(
+- [("x", TensorProto.STRING, ("M", None, 3, 12))],
++ [
++ ("x", TensorProto.FLOAT, ("N", "C", "H", "W")),
++ ("rois", TensorProto.FLOAT, ("num_rois", 4)),
++ ("batch_indices", TensorProto.INT64, ("num_rois",)),
++ ],
+ [
+ make_node(
+- "LabelEncoder",
+- ["x"],
++ "RoiAlign",
++ ["x", "rois", "batch_indices"],
+ ["y"],
+- domain=ONNX_ML_DOMAIN,
+- keys_tensor=key_tensor,
+- values_tensor=values_tensor,
+- default_tensor=make_tensor(
+- "default_tensor", TensorProto.INT64, [1], [0]
+- ),
++ output_height=10,
++ output_width=5,
+ )
+ ],
+ [],
+ )
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", TensorProto.INT64, ("M", None, 3, 12))],
+- opset_imports=[
+- make_opsetid(ONNX_ML_DOMAIN, version),
+- make_opsetid(ONNX_DOMAIN, 11),
+- ],
+- )
+-
+- @parameterized.expand(
+- all_versions_for("LabelEncoder") if ONNX_ML else [], skip_on_empty=True
+- )
+- def test_label_encoder_tensor_attributes_invalid_configurations(
+- self, _, version
+- ) -> None:
+- self.skipIf(version < 4, "tensor attributes introduced in ai.onnx.ml opset 4")
+- key_tensor = make_tensor(
+- "keys_tensor", TensorProto.STRING, [4], ["a", "b", "cc", "ddd"]
+- )
+- values_tensor = make_tensor(
+- "values_tensor", TensorProto.INT64, [4], [1, 2, 3, 4]
+- )
+-
+- opset_imports = [
+- make_opsetid(ONNX_ML_DOMAIN, version),
+- make_opsetid(ONNX_DOMAIN, 11),
+- ]
++ self._assert_inferred(graph, [make_tensor_value_info("y", TensorProto.FLOAT, ("num_rois", "C", 10, 5))]) # type: ignore
+
+- # default_tensor should be INT64, same type as values_tensor
++ def test_roialign_symbolic_defaults(self) -> None:
+ graph = self._make_graph(
+- [("x", TensorProto.STRING, ("M", None, 3, 12))],
+ [
+- make_node(
+- "LabelEncoder",
+- ["x"],
+- ["y"],
+- domain=ONNX_ML_DOMAIN,
+- keys_tensor=key_tensor,
+- values_tensor=values_tensor,
+- default_tensor=make_tensor(
+- "default_tensor", TensorProto.STRING, [1], [0]
+- ),
+- )
++ ("x", TensorProto.FLOAT, ("N", "C", "H", "W")),
++ ("rois", TensorProto.FLOAT, ("num_rois", 4)),
++ ("batch_indices", TensorProto.INT64, ("num_rois",)),
+ ],
++ [make_node("RoiAlign", ["x", "rois", "batch_indices"], ["y"])],
+ [],
+ )
++ self._assert_inferred(graph, [make_tensor_value_info("y", TensorProto.FLOAT, ("num_rois", "C", 1, 1))]) # type: ignore
+
+- self.assertRaises(
+- onnx.shape_inference.InferenceError,
+- self._inferred,
+- graph,
+- opset_imports=opset_imports,
+- )
+-
+- # default_tensor should be a singleton of shape (1,)
++ def test_roialign_num_rois(self) -> None:
+ graph = self._make_graph(
+- [("x", TensorProto.STRING, ("M", None, 3, 12))],
+ [
+- make_node(
+- "LabelEncoder",
+- ["x"],
+- ["y"],
+- domain=ONNX_ML_DOMAIN,
+- keys_tensor=key_tensor,
+- values_strings=["a", "b", "cc", "ddd"],
+- default_tensor=make_tensor(
+- "default_tensor", TensorProto.STRING, [1, 2], [0, 0]
+- ),
+- )
++ ("x", TensorProto.FLOAT, ("N", "C", "H", "W")),
++ ("rois", TensorProto.FLOAT, ("num_rois", 4)),
++ ("batch_indices", TensorProto.INT64, (15,)),
+ ],
++ [make_node("RoiAlign", ["x", "rois", "batch_indices"], ["y"])],
+ [],
+ )
+-
+- self.assertRaises(
+- onnx.shape_inference.InferenceError,
+- self._inferred,
+- graph,
+- opset_imports=opset_imports,
+- )
++ self._assert_inferred(graph, [make_tensor_value_info("y", TensorProto.FLOAT, (15, "C", 1, 1))]) # type: ignore
+
+ def make_sparse(
+ self,
+@@ -8136,105 +6479,6 @@ class TestShapeInference(TestShapeInferenceHelper):
+ )
+ self._assert_inferred(graph, [output_tensor_val_info]) # type: ignore
+
+- @parameterized.expand(all_versions_for("StringSplit"))
+- def test_string_split_basic(self, _, version) -> None:
+- substrings = make_tensor_value_info(
+- "substrings",
+- TensorProto.STRING,
+- (2, None),
+- )
+- length = make_tensor_value_info("length", TensorProto.INT64, (2,))
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.STRING, (2,)),
+- ],
+- [make_node("StringSplit", ["x"], ["substrings", "length"])],
+- [substrings, length],
+- )
+- self._assert_inferred(
+- graph,
+- [substrings, length],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("StringSplit"))
+- def test_string_split_symbolic(self, _, version) -> None:
+- substrings = make_tensor_value_info(
+- "substrings",
+- TensorProto.STRING,
+- ("A", None),
+- )
+- length = make_tensor_value_info("length", TensorProto.INT64, ("A",))
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.STRING, ("A",)),
+- ],
+- [make_node("StringSplit", ["x"], ["substrings", "length"])],
+- [substrings, length],
+- )
+- self._assert_inferred(
+- graph,
+- [substrings, length],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("StringSplit"))
+- def test_string_split_nested(self, _, version) -> None:
+- substrings = make_tensor_value_info(
+- "substrings", TensorProto.STRING, (2, 4, 3, None)
+- )
+- length = make_tensor_value_info("length", TensorProto.INT64, (2, 4, 3))
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.STRING, (2, 4, 3)),
+- ],
+- [make_node("StringSplit", ["x"], ["substrings", "length"], maxsplit=2)],
+- [substrings, length],
+- )
+- self._assert_inferred(
+- graph,
+- [substrings, length],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("StringSplit"))
+- def test_string_split_zero_dimensional_input(self, _, version) -> None:
+- substrings = make_tensor_value_info("substrings", TensorProto.STRING, (None,))
+- length = make_tensor_value_info("length", TensorProto.INT64, ())
+-
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.STRING, ()),
+- ],
+- [make_node("StringSplit", ["x"], ["substrings", "length"], maxsplit=2)],
+- [substrings, length],
+- )
+- self._assert_inferred(
+- graph,
+- [substrings, length],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(all_versions_for("StringSplit"))
+- def test_string_split_empty_input(self, _, version) -> None:
+- substrings = make_tensor_value_info(
+- "substrings", TensorProto.STRING, ("M", 3, 0, None)
+- )
+- length = make_tensor_value_info("length", TensorProto.INT64, ("M", 3, 0))
+-
+- graph = self._make_graph(
+- [
+- ("x", TensorProto.STRING, ("M", 3, 0)),
+- ],
+- [make_node("StringSplit", ["x"], ["substrings", "length"], maxsplit=2)],
+- [substrings, length],
+- )
+- self._assert_inferred(
+- graph,
+- [substrings, length],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+ def test_optional_tensor_get_element(self) -> None:
+ tensor_type_proto = helper.make_tensor_type_proto(
+ elem_type=TensorProto.DOUBLE, shape=[2, 1, 4]
+@@ -8759,114 +7003,28 @@ class TestShapeInference(TestShapeInferenceHelper):
+ graph = self._make_graph(
+ [
+ ("input1", TensorProto.FLOAT, (220, 310, 3)),
+- ("input2", TensorProto.FLOAT, (110, 210, 3)),
+- ("input3", TensorProto.FLOAT, (90, 110, 3)),
+- ],
+- [
+- make_node(
+- "SequenceConstruct", ["input1", "input2", "input3"], ["in_sequence"]
+- ),
+- make_node("SequenceMap", ["in_sequence"], ["shapes"], body=body_graph),
+- ],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [
+- make_tensor_sequence_value_info(
+- "in_sequence", TensorProto.FLOAT, (None, None, 3)
+- ),
+- make_tensor_sequence_value_info("shapes", TensorProto.INT64, (3,)),
+- ],
+- ) # type: ignore
+-
+- def test_hammingwindow(self):
+- graph = self._make_graph(
+- [],
+- [
+- make_node(
+- "Constant",
+- [],
+- ["shape"],
+- value=make_tensor("shape", TensorProto.INT64, (), (10,)),
+- ),
+- make_node("HammingWindow", ["shape"], ["y"]),
+- ],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [
+- make_tensor_value_info("shape", TensorProto.INT64, ()),
+- make_tensor_value_info("y", TensorProto.FLOAT, (10,)),
+- ],
+- ) # type: ignore
+-
+- graph = self._make_graph(
+- [],
+- [
+- make_node(
+- "Constant",
+- [],
+- ["shape"],
+- value=make_tensor("shape", TensorProto.INT64, (), (10,)),
+- ),
+- make_node("HammingWindow", ["shape"], ["y"], periodic=0),
+- ],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [
+- make_tensor_value_info("shape", TensorProto.INT64, ()),
+- make_tensor_value_info("y", TensorProto.FLOAT, (10,)),
+- ],
+- ) # type: ignore
+-
+- def test_hannwindow(self):
+- graph = self._make_graph(
+- [],
+- [
+- make_node(
+- "Constant",
+- [],
+- ["shape"],
+- value=make_tensor("shape", TensorProto.INT64, (), (10,)),
+- ),
+- make_node("HannWindow", ["shape"], ["y"]),
+- ],
+- [],
+- )
+- self._assert_inferred(
+- graph,
+- [
+- make_tensor_value_info("shape", TensorProto.INT64, ()),
+- make_tensor_value_info("y", TensorProto.FLOAT, (10,)),
+- ],
+- ) # type: ignore
+-
+- graph = self._make_graph(
+- [],
++ ("input2", TensorProto.FLOAT, (110, 210, 3)),
++ ("input3", TensorProto.FLOAT, (90, 110, 3)),
++ ],
+ [
+ make_node(
+- "Constant",
+- [],
+- ["shape"],
+- value=make_tensor("shape", TensorProto.INT64, (), (10,)),
++ "SequenceConstruct", ["input1", "input2", "input3"], ["in_sequence"]
+ ),
+- make_node("HannWindow", ["shape"], ["y"], periodic=0),
++ make_node("SequenceMap", ["in_sequence"], ["shapes"], body=body_graph),
+ ],
+ [],
+ )
+ self._assert_inferred(
+ graph,
+ [
+- make_tensor_value_info("shape", TensorProto.INT64, ()),
+- make_tensor_value_info("y", TensorProto.FLOAT, (10,)),
++ make_tensor_sequence_value_info(
++ "in_sequence", TensorProto.FLOAT, (None, None, 3)
++ ),
++ make_tensor_sequence_value_info("shapes", TensorProto.INT64, (3,)),
+ ],
+ ) # type: ignore
+
+- def test_blackmanwindow(self):
++ def test_hammingwindow(self):
+ graph = self._make_graph(
+ [],
+ [
+@@ -8876,7 +7034,7 @@ class TestShapeInference(TestShapeInferenceHelper):
+ ["shape"],
+ value=make_tensor("shape", TensorProto.INT64, (), (10,)),
+ ),
+- make_node("BlackmanWindow", ["shape"], ["y"]),
++ make_node("HammingWindow", ["shape"], ["y"]),
+ ],
+ [],
+ )
+@@ -8897,7 +7055,7 @@ class TestShapeInference(TestShapeInferenceHelper):
+ ["shape"],
+ value=make_tensor("shape", TensorProto.INT64, (), (10,)),
+ ),
+- make_node("BlackmanWindow", ["shape"], ["y"], periodic=0),
++ make_node("HammingWindow", ["shape"], ["y"], periodic=0),
+ ],
+ [],
+ )
+@@ -8909,463 +7067,91 @@ class TestShapeInference(TestShapeInferenceHelper):
+ ],
+ ) # type: ignore
+
+- @parameterized.expand(
+- [
+- (
+- name,
+- version,
+- test_aspect,
+- input_shape,
+- axis,
+- onesided,
+- inverse,
+- expected_shape,
+- )
+- for (name, version), (
+- test_aspect,
+- input_shape,
+- axis,
+- onesided,
+- inverse,
+- expected_shape,
+- ) in itertools.product(
+- all_versions_for("DFT"),
+- (
+- ("reals_default_axis", (2, 5, 1), None, None, None, (2, 5, 2)),
+- ("reals_axis_0", (3, 5, 10, 1), 0, 0, 0, (3, 5, 10, 2)),
+- ("reals_axis_1", (3, 5, 10, 1), 1, 0, 0, (3, 5, 10, 2)),
+- ("reals_axis_2", (3, 5, 10, 1), 2, 0, 0, (3, 5, 10, 2)),
+- ("reals_axis_neg", (3, 5, 10, 1), -2, 0, 0, (3, 5, 10, 2)),
+- ("reals_axis_0_onesided", (3, 5, 10, 1), 0, 1, 0, (2, 5, 10, 2)),
+- ("reals_axis_1_onesided", (3, 5, 10, 1), 1, 1, 0, (3, 3, 10, 2)),
+- ("reals_axis_2_onesided", (3, 5, 10, 1), 2, 1, 0, (3, 5, 6, 2)),
+- ("reals_axis_neg_onesided", (3, 5, 10, 1), -2, 1, 0, (3, 5, 6, 2)),
+- ("complex_default_axis", (2, 5, 2), None, None, None, (2, 5, 2)),
+- ("complex_onesided", (2, 5, 2), 1, 1, None, (2, 3, 2)),
+- ("real_inverse", (2, 5, 1), 1, None, 1, (2, 5, 2)),
+- ("complex_inverse", (2, 5, 2), 1, None, 1, (2, 5, 2)),
+- ),
+- )
+- ]
+- )
+- def test_dft(
+- self,
+- _: str,
+- version: int,
+- _test_aspect: str,
+- input_shape: tuple[int],
+- axis: int | None,
+- onesided: int | None,
+- inverse: int | None,
+- expected_shape: tuple[int],
+- ) -> None:
+- # Build the attributes for different opset versions
+- attributes = {}
+- if onesided is not None:
+- attributes["onesided"] = onesided
+- if inverse is not None:
+- attributes["inverse"] = inverse
+-
+- if version < 20:
+- if axis is not None:
+- attributes["axis"] = axis
+- nodes = [make_node("DFT", ["input", ""], ["output"], **attributes)] # type: ignore[arg-type]
+- value_infos = []
+- else:
+- assert version >= 20
+- if axis is not None:
+- nodes = [
+- make_node(
+- "Constant",
+- [],
+- ["axis"],
+- value=make_tensor("axis", TensorProto.INT64, (), (axis,)),
+- ),
+- make_node("DFT", ["input", "", "axis"], ["output"], **attributes), # type: ignore[arg-type]
+- ]
+- value_infos = [make_tensor_value_info("axis", TensorProto.INT64, ())]
+- else:
+- nodes = [
+- make_node("DFT", ["input", "", ""], ["output"], **attributes), # type: ignore[arg-type]
+- ]
+- value_infos = []
+-
+- # Construct the graph
++ def test_hannwindow(self):
+ graph = self._make_graph(
+ [],
+ [
+ make_node(
+ "Constant",
+ [],
+- ["input"],
+- value=make_tensor(
+- "input",
+- TensorProto.FLOAT,
+- input_shape,
+- np.ones(input_shape, dtype=np.float32).flatten(),
+- ),
++ ["shape"],
++ value=make_tensor("shape", TensorProto.INT64, (), (10,)),
+ ),
+- *nodes,
++ make_node("HannWindow", ["shape"], ["y"]),
+ ],
+ [],
+ )
+ self._assert_inferred(
+ graph,
+ [
+- make_tensor_value_info("input", TensorProto.FLOAT, input_shape),
+- *value_infos,
+- make_tensor_value_info("output", TensorProto.FLOAT, expected_shape),
++ make_tensor_value_info("shape", TensorProto.INT64, ()),
++ make_tensor_value_info("y", TensorProto.FLOAT, (10,)),
+ ],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(
+- [
+- (
+- name,
+- version,
+- test_aspect,
+- input_shape,
+- axis,
+- onesided,
+- inverse,
+- expected_shape,
+- )
+- for (name, version), (
+- test_aspect,
+- input_shape,
+- axis,
+- onesided,
+- inverse,
+- expected_shape,
+- ) in itertools.product(
+- all_versions_for("DFT"),
+- (
+- ("reals_default_axis", (2, 5, 1), None, None, None, (2, 42, 2)),
+- ("reals_axis_0", (3, 5, 10, 1), 0, 0, 0, (42, 5, 10, 2)),
+- ("reals_axis_1", (3, 5, 10, 1), 1, 0, 0, (3, 42, 10, 2)),
+- ("reals_axis_2", (3, 5, 10, 1), 2, 0, 0, (3, 5, 42, 2)),
+- ("reals_axis_neg", (3, 5, 10, 1), -2, 0, 0, (3, 5, 42, 2)),
+- ("reals_axis_0_onesided", (3, 5, 10, 1), 0, 1, 0, (22, 5, 10, 2)),
+- ("reals_axis_1_onesided", (3, 5, 10, 1), 1, 1, 0, (3, 22, 10, 2)),
+- ("reals_axis_2_onesided", (3, 5, 10, 1), 2, 1, 0, (3, 5, 22, 2)),
+- ("reals_axis_neg_onesided", (3, 5, 10, 1), -2, 1, 0, (3, 5, 22, 2)),
+- ("complex_default_axis", (2, 5, 2), None, None, None, (2, 42, 2)),
+- ("complex_onesided", (2, 5, 2), 1, 1, None, (2, 22, 2)),
+- ("real_inverse", (2, 5, 1), 1, None, 1, (2, 42, 2)),
+- ("complex_inverse", (2, 5, 2), 1, None, 1, (2, 42, 2)),
+- ),
+- )
+- ]
+- )
+- def test_dft_dft_length(
+- self,
+- _: str,
+- version: int,
+- _test_aspect: str,
+- input_shape: tuple[int],
+- axis: int | None,
+- onesided: int | None,
+- inverse: int | None,
+- expected_shape: tuple[int],
+- ) -> None:
+- # Build the attributes for different opset versions
+- attributes = {}
+- if onesided is not None:
+- attributes["onesided"] = onesided
+- if inverse is not None:
+- attributes["inverse"] = inverse
+-
+- dft_length = 42
+-
+- if version < 20:
+- if axis is not None:
+- attributes["axis"] = axis
+- nodes = [
+- make_node(
+- "Constant",
+- [],
+- ["dft_length"],
+- value=make_tensor(
+- "dft_length", TensorProto.INT64, (), (dft_length,)
+- ),
+- ),
+- make_node("DFT", ["input", "dft_length"], ["output"], **attributes), # type: ignore[arg-type]
+- ]
+- value_infos = [make_tensor_value_info("dft_length", TensorProto.INT64, ())]
+- else:
+- assert version >= 20
+- if axis is not None:
+- nodes = [
+- make_node(
+- "Constant",
+- [],
+- ["axis"],
+- value=make_tensor("axis", TensorProto.INT64, (), (axis,)),
+- ),
+- make_node(
+- "Constant",
+- [],
+- ["dft_length"],
+- value=make_tensor(
+- "dft_length", TensorProto.INT64, (), (dft_length,)
+- ),
+- ),
+- make_node("DFT", ["input", "dft_length", "axis"], ["output"], **attributes), # type: ignore[arg-type]
+- ]
+- value_infos = [
+- make_tensor_value_info("dft_length", TensorProto.INT64, ()),
+- make_tensor_value_info("axis", TensorProto.INT64, ()),
+- ]
+- else:
+- nodes = [
+- make_node(
+- "Constant",
+- [],
+- ["dft_length"],
+- value=make_tensor(
+- "dft_length", TensorProto.INT64, (), (dft_length,)
+- ),
+- ),
+- make_node("DFT", ["input", "dft_length", ""], ["output"], **attributes), # type: ignore[arg-type]
+- ]
+- value_infos = [
+- make_tensor_value_info("dft_length", TensorProto.INT64, ())
+- ]
++ ) # type: ignore
+
+- # Construct the graph
+ graph = self._make_graph(
+ [],
+ [
+ make_node(
+ "Constant",
+ [],
+- ["input"],
+- value=make_tensor(
+- "input",
+- TensorProto.FLOAT,
+- input_shape,
+- np.ones(input_shape, dtype=np.float32).flatten(),
+- ),
++ ["shape"],
++ value=make_tensor("shape", TensorProto.INT64, (), (10,)),
+ ),
+- *nodes,
++ make_node("HannWindow", ["shape"], ["y"], periodic=0),
+ ],
+ [],
+ )
+ self._assert_inferred(
+ graph,
+ [
+- make_tensor_value_info("input", TensorProto.FLOAT, input_shape),
+- *value_infos,
+- make_tensor_value_info("output", TensorProto.FLOAT, expected_shape),
+- ],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, version)],
+- )
+-
+- @parameterized.expand(
+- [
+- ("last", 3),
+- ("last_negative", -1),
+- ("out_of_range", 4),
+- ("out_of_range_negative", -5),
+- ]
+- )
+- def test_dft_invalid_axis_opset17(self, _: str, axis: int) -> None:
+- graph = self._make_graph(
+- [],
+- [
+- make_node(
+- "Constant",
+- [],
+- ["input"],
+- value=make_tensor(
+- "input",
+- TensorProto.FLOAT,
+- (2, 5, 5, 2),
+- np.ones((2, 5, 5, 2), dtype=np.float32).flatten(),
+- ),
+- ),
+- make_node("DFT", ["input", ""], ["output"], onesided=1, axis=axis),
++ make_tensor_value_info("shape", TensorProto.INT64, ()),
++ make_tensor_value_info("y", TensorProto.FLOAT, (10,)),
+ ],
+- [],
+- )
+- with self.assertRaises(onnx.shape_inference.InferenceError):
+- self._assert_inferred(
+- graph,
+- [
+- make_tensor_value_info("input", TensorProto.FLOAT, (2, 5, 5, 2)),
+- make_tensor_value_info("output", TensorProto.FLOAT, (2, 3, 5, 2)),
+- ],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, 17)],
+- )
++ ) # type: ignore
+
+- @parameterized.expand(
+- [
+- ("last", 3),
+- ("last_negative", -1),
+- ("out_of_range", 4),
+- ("out_of_range_negative", -5),
+- ]
+- )
+- def test_dft_invalid_axis_opset20(self, _: str, axis: int) -> None:
++ def test_blackmanwindow(self):
+ graph = self._make_graph(
+ [],
+ [
+ make_node(
+ "Constant",
+ [],
+- ["input"],
+- value=make_tensor(
+- "input",
+- TensorProto.FLOAT,
+- (2, 5, 5, 2),
+- np.ones((2, 5, 5, 2), dtype=np.float32).flatten(),
+- ),
+- ),
+- make_node(
+- "Constant",
+- [],
+- ["axis"],
+- value=make_tensor("axis", TensorProto.INT64, (), (axis,)),
+- ),
+- make_node("DFT", ["input", "", "axis"], ["output"]),
+- ],
+- [],
+- )
+- with self.assertRaises(onnx.shape_inference.InferenceError):
+- self._assert_inferred(
+- graph,
+- [
+- make_tensor_value_info("input", TensorProto.FLOAT, (2, 5, 5, 2)),
+- make_tensor_value_info("axis", TensorProto.INT64, ()),
+- make_tensor_value_info("output", TensorProto.FLOAT, (2, 3, 5, 2)),
+- ],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, 20)],
+- )
+-
+- @parameterized.expand(
+- [
+- ("real", (2, 5, 5, 1)),
+- ("complex", (2, 5, 5, 2)),
+- ]
+- )
+- def test_dft_dynamic_axis_opset20(self, _: str, shape: tuple[int, ...]) -> None:
+- graph = self._make_graph(
+- [("axis", TensorProto.INT64, ())],
+- [
+- make_node(
+- "Constant",
+- [],
+- ["input"],
+- value=make_tensor(
+- "input",
+- TensorProto.FLOAT,
+- shape,
+- np.ones(shape, dtype=np.float32).flatten(),
+- ),
++ ["shape"],
++ value=make_tensor("shape", TensorProto.INT64, (), (10,)),
+ ),
+- make_node("DFT", ["input", "", "axis"], ["output"]),
++ make_node("BlackmanWindow", ["shape"], ["y"]),
+ ],
+ [],
+ )
+ self._assert_inferred(
+ graph,
+ [
+- make_tensor_value_info("input", TensorProto.FLOAT, shape),
+- make_tensor_value_info("output", TensorProto.FLOAT, (2, 5, 5, 2)),
++ make_tensor_value_info("shape", TensorProto.INT64, ()),
++ make_tensor_value_info("y", TensorProto.FLOAT, (10,)),
+ ],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, 20)],
+- )
++ ) # type: ignore
+
+- @parameterized.expand(
+- [
+- ("real", (2, 5, 5, 1)),
+- ("complex", (2, 5, 5, 2)),
+- ]
+- )
+- def test_dft_dynamic_axis_onesided_dft_length_opset20(
+- self, _: str, shape: tuple[int, ...]
+- ) -> None:
+ graph = self._make_graph(
+- [("axis", TensorProto.INT64, ())],
+- [
+- make_node(
+- "Constant",
+- [],
+- ["input"],
+- value=make_tensor(
+- "input",
+- TensorProto.FLOAT,
+- shape,
+- np.ones(shape, dtype=np.float32).flatten(),
+- ),
+- ),
+- make_node(
+- "Constant",
+- [],
+- ["dft_length"],
+- value=make_tensor(
+- "dft_length",
+- TensorProto.INT64,
+- (),
+- np.array([42], dtype=np.int64),
+- ),
+- ),
+- make_node(
+- "DFT", ["input", "dft_length", "axis"], ["output"], onesided=1
+- ),
+- ],
+ [],
+- )
+- self._assert_inferred(
+- graph,
+- [
+- make_tensor_value_info("input", TensorProto.FLOAT, shape),
+- make_tensor_value_info("dft_length", TensorProto.INT64, ()),
+- make_tensor_value_info(
+- "output", TensorProto.FLOAT, (None, None, None, 2)
+- ),
+- ],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, 20)],
+- )
+-
+- @parameterized.expand(
+- [
+- ("real", (2, 5, 5, 1)),
+- ("complex", (2, 5, 5, 2)),
+- ]
+- )
+- def test_dft_dynamic_axis_onesided_opset20(
+- self, _: str, shape: tuple[int, ...]
+- ) -> None:
+- graph = self._make_graph(
+- [("axis", TensorProto.INT64, ())],
+ [
+ make_node(
+ "Constant",
+ [],
+- ["input"],
+- value=make_tensor(
+- "input",
+- TensorProto.FLOAT,
+- shape,
+- np.ones(shape, dtype=np.float32).flatten(),
+- ),
++ ["shape"],
++ value=make_tensor("shape", TensorProto.INT64, (), (10,)),
+ ),
+- make_node("DFT", ["input", "", "axis"], ["output"], onesided=1),
++ make_node("BlackmanWindow", ["shape"], ["y"], periodic=0),
+ ],
+ [],
+ )
+ self._assert_inferred(
+ graph,
+ [
+- make_tensor_value_info("input", TensorProto.FLOAT, shape),
+- make_tensor_value_info(
+- "output", TensorProto.FLOAT, (None, None, None, 2)
+- ),
++ make_tensor_value_info("shape", TensorProto.INT64, ()),
++ make_tensor_value_info("y", TensorProto.FLOAT, (10,)),
+ ],
+- opset_imports=[helper.make_opsetid(ONNX_DOMAIN, 20)],
+- )
++ ) # type: ignore
+
+ def test_dft_onesided_default_axis_opset17(self) -> None:
+ # Opset 17 sets default axis to be 1.
+@@ -9846,139 +7632,6 @@ class TestShapeInference(TestShapeInferenceHelper):
+ ],
+ )
+
+- @parameterized.expand([TensorProto.FLOAT, TensorProto.DOUBLE, TensorProto.FLOAT16])
+- @unittest.skipUnless(ONNX_ML, "ONNX_ML required to test ai.onnx.ml operators")
+- def test_tree_ensemble(self, dtype) -> None:
+- interior_nodes = 5
+- leaves = 9
+- tree = make_node(
+- "TreeEnsemble",
+- ["x"],
+- ["y"],
+- domain=ONNX_ML_DOMAIN,
+- n_targets=5,
+- nodes_featureids=[0] * interior_nodes,
+- nodes_splits=make_tensor(
+- "nodes_splits",
+- dtype,
+- (interior_nodes,),
+- list(range(interior_nodes)),
+- ),
+- nodes_modes=make_tensor(
+- "nodes_modes",
+- TensorProto.UINT8,
+- (interior_nodes,),
+- [0] * interior_nodes,
+- ),
+- nodes_truenodeids=[0] * interior_nodes,
+- nodes_falsenodeids=[0] * interior_nodes,
+- nodes_trueleafs=[0] * interior_nodes,
+- nodes_falseleafs=[0] * interior_nodes,
+- membership_values=make_tensor(
+- "membership_values",
+- dtype,
+- (7,),
+- [0.0, 0.1, 0.2, np.nan, 0.4, 0.5, 1.0],
+- ),
+- leaf_targetids=[0] * leaves,
+- leaf_weights=make_tensor("leaf_weights", dtype, (leaves,), [1] * leaves),
+- tree_roots=[0],
+- )
+-
+- graph = self._make_graph(
+- [("x", dtype, ("Batch Size", "Features"))],
+- [tree],
+- [],
+- )
+-
+- self._assert_inferred(
+- graph,
+- [make_tensor_value_info("y", dtype, ("Batch Size", 5))],
+- opset_imports=[
+- make_opsetid(ONNX_ML_DOMAIN, 5),
+- make_opsetid(ONNX_DOMAIN, 11),
+- ],
+- )
+-
+- @parameterized.expand(
+- [
+- {
+- "nodes_truenodeids": [0] * 6,
+- "leaf_weights": make_tensor(
+- "leaf_weights", TensorProto.DOUBLE, (9,), [1] * 9
+- ),
+- "nodes_splits": make_tensor(
+- "nodes_splits", TensorProto.DOUBLE, (5,), [1] * 5
+- ),
+- },
+- {
+- "nodes_truenodeids": [0] * 5,
+- "leaf_weights": make_tensor(
+- "leaf_weights", TensorProto.FLOAT, (9,), [1] * 9
+- ),
+- "nodes_splits": make_tensor(
+- "nodes_splits", TensorProto.DOUBLE, (5,), [1] * 5
+- ),
+- },
+- {
+- "nodes_truenodeids": [0] * 5,
+- "leaf_weights": make_tensor(
+- "leaf_weights", TensorProto.DOUBLE, (18,), [1] * 18
+- ),
+- "nodes_splits": make_tensor(
+- "nodes_splits", TensorProto.DOUBLE, (5,), [1] * 5
+- ),
+- },
+- {
+- "nodes_truenodeids": [0] * 5,
+- "leaf_weights": make_tensor(
+- "leaf_weights", TensorProto.DOUBLE, (9,), [1] * 9
+- ),
+- "nodes_splits": make_tensor(
+- "nodes_splits", TensorProto.FLOAT, (5,), [1] * 5
+- ),
+- },
+- ]
+- )
+- @unittest.skipUnless(ONNX_ML, "ONNX_ML required to test ai.onnx.ml operators")
+- def test_tree_ensemble_fails_if_invalid_attributes(
+- self,
+- nodes_truenodeids,
+- leaf_weights,
+- nodes_splits,
+- ) -> None:
+- interior_nodes = 5
+- leaves = 9
+- tree = make_node(
+- "TreeEnsemble",
+- ["x"],
+- ["y"],
+- domain=ONNX_ML_DOMAIN,
+- n_targets=5,
+- nodes_featureids=[0] * interior_nodes,
+- nodes_splits=nodes_splits,
+- nodes_modes=make_tensor(
+- "nodes_modes",
+- TensorProto.UINT8,
+- (interior_nodes,),
+- [0] * interior_nodes,
+- ),
+- nodes_truenodeids=nodes_truenodeids,
+- nodes_falsenodeids=[0] * interior_nodes,
+- nodes_trueleafs=[0] * interior_nodes,
+- nodes_falseleafs=[0] * interior_nodes,
+- leaf_targetids=[0] * leaves,
+- leaf_weights=leaf_weights,
+- tree_roots=[0],
+- )
+-
+- graph = self._make_graph(
+- [("x", TensorProto.DOUBLE, ("Batch Size", "Features"))],
+- [tree],
+- [],
+- )
+- self.assertRaises(onnx.shape_inference.InferenceError, self._inferred, graph)
+-
+ @unittest.skipUnless(ONNX_ML, "ONNX_ML required to test ai.onnx.ml operators")
+ def test_tree_ensemble_classifier(self) -> None:
+ tree = make_node(
+diff --git a/onnx/test/test_backend_reference.py b/onnx/test/test_backend_reference.py
+index 71ce7651e..b482f2778 100644
+--- a/onnx/test/test_backend_reference.py
++++ b/onnx/test/test_backend_reference.py
+@@ -193,6 +193,15 @@ backend_test.exclude("(test_eyelike_without_dtype)")
+ # The following tests fail due to discrepancies (small but still higher than 1e-7).
+ backend_test.exclude("test_adam_multiple") # 1e-2
+
++backend_test.exclude(
++ "("
++ "test_affine_grid_2d_align_corners_expanded_cpu"
++ "|test_affine_grid_2d_expanded_cpu"
++ "|test_affine_grid_3d_align_corners_expanded_cpu"
++ "|test_affine_grid_3d_expanded_cpu"
++ ")"
++)
++
+ # Currently google-re2/Pillow is not supported on Win32 and is required for the reference implementation of RegexFullMatch.
+ if sys.platform == "win32":
+ backend_test.exclude("test_regex_full_match_basic_cpu")
+diff --git a/onnx/test/test_external_data.py b/onnx/test/test_external_data.py
+index fc4b2f802..d755c04cc 100644
+--- a/onnx/test/test_external_data.py
++++ b/onnx/test/test_external_data.py
+@@ -12,7 +12,6 @@ import uuid
+ from typing import Any, Sequence
+
+ import numpy as np
+-import parameterized
+
+ import onnx
+ from onnx import (
+@@ -112,621 +111,6 @@ class TestLoadExternalDataBase(unittest.TestCase):
+ checker.check_model(self.model_filename)
+
+
+-@parameterized.parameterized_class(
+- [
+- {"serialization_format": "protobuf"},
+- {"serialization_format": "textproto"},
+- ]
+-)
+-class TestLoadExternalData(TestLoadExternalDataBase):
+- def test_load_external_data(self) -> None:
+- model = onnx.load_model(self.model_filename, self.serialization_format)
+- initializer_tensor = model.graph.initializer[0]
+- np.testing.assert_allclose(to_array(initializer_tensor), self.initializer_value)
+-
+- attribute_tensor = model.graph.node[0].attribute[0].t
+- np.testing.assert_allclose(to_array(attribute_tensor), self.attribute_value)
+-
+- def test_load_external_data_for_model(self) -> None:
+- model = onnx.load_model(
+- self.model_filename, self.serialization_format, load_external_data=False
+- )
+- load_external_data_for_model(model, self.temp_dir)
+- initializer_tensor = model.graph.initializer[0]
+- np.testing.assert_allclose(to_array(initializer_tensor), self.initializer_value)
+-
+- attribute_tensor = model.graph.node[0].attribute[0].t
+- np.testing.assert_allclose(to_array(attribute_tensor), self.attribute_value)
+-
+- def test_save_external_data(self) -> None:
+- model = onnx.load_model(self.model_filename, self.serialization_format)
+-
+- temp_dir = os.path.join(self.temp_dir, "save_copy")
+- os.mkdir(temp_dir)
+- new_model_filename = os.path.join(temp_dir, "model.onnx")
+- onnx.save_model(model, new_model_filename, self.serialization_format)
+-
+- new_model = onnx.load_model(new_model_filename, self.serialization_format)
+- initializer_tensor = new_model.graph.initializer[0]
+- np.testing.assert_allclose(to_array(initializer_tensor), self.initializer_value)
+-
+- attribute_tensor = new_model.graph.node[0].attribute[0].t
+- np.testing.assert_allclose(to_array(attribute_tensor), self.attribute_value)
+-
+-
+-@parameterized.parameterized_class(
+- [
+- {"serialization_format": "protobuf"},
+- {"serialization_format": "textproto"},
+- ]
+-)
+-class TestLoadExternalDataSingleFile(TestLoadExternalDataBase):
+- def create_external_data_tensors(
+- self, tensors_data: list[tuple[list[Any], Any]]
+- ) -> list[TensorProto]:
+- tensor_filename = "tensors.bin"
+- tensors = []
+-
+- with open(os.path.join(self.temp_dir, tensor_filename), "ab") as data_file:
+- for value, tensor_name in tensors_data:
+- tensor = from_array(np.array(value))
+- offset = data_file.tell()
+- if offset % 4096 != 0:
+- data_file.write(b"\0" * (4096 - offset % 4096))
+- offset = offset + 4096 - offset % 4096
+-
+- data_file.write(tensor.raw_data)
+- set_external_data(
+- tensor,
+- location=tensor_filename,
+- offset=offset,
+- length=data_file.tell() - offset,
+- )
+- tensor.name = tensor_name
+- tensor.ClearField("raw_data")
+- tensor.data_location = onnx.TensorProto.EXTERNAL
+- tensors.append(tensor)
+-
+- return tensors
+-
+- def test_load_external_single_file_data(self) -> None:
+- model = onnx.load_model(self.model_filename, self.serialization_format)
+-
+- initializer_tensor = model.graph.initializer[0]
+- np.testing.assert_allclose(to_array(initializer_tensor), self.initializer_value)
+-
+- attribute_tensor = model.graph.node[0].attribute[0].t
+- np.testing.assert_allclose(to_array(attribute_tensor), self.attribute_value)
+-
+- def test_save_external_single_file_data(self) -> None:
+- model = onnx.load_model(self.model_filename, self.serialization_format)
+-
+- temp_dir = os.path.join(self.temp_dir, "save_copy")
+- os.mkdir(temp_dir)
+- new_model_filename = os.path.join(temp_dir, "model.onnx")
+- onnx.save_model(model, new_model_filename, self.serialization_format)
+-
+- new_model = onnx.load_model(new_model_filename, self.serialization_format)
+- initializer_tensor = new_model.graph.initializer[0]
+- np.testing.assert_allclose(to_array(initializer_tensor), self.initializer_value)
+-
+- attribute_tensor = new_model.graph.node[0].attribute[0].t
+- np.testing.assert_allclose(to_array(attribute_tensor), self.attribute_value)
+-
+- @parameterized.parameterized.expand(itertools.product((True, False), (True, False)))
+- def test_save_external_invalid_single_file_data_and_check(
+- self, use_absolute_path: bool, use_model_path: bool
+- ) -> None:
+- model = onnx.load_model(self.model_filename, self.serialization_format)
+-
+- model_dir = os.path.join(self.temp_dir, "save_copy")
+- os.mkdir(model_dir)
+-
+- traversal_external_data_dir = os.path.join(
+- self.temp_dir, "invlid_external_data"
+- )
+- os.mkdir(traversal_external_data_dir)
+-
+- if use_absolute_path:
+- traversal_external_data_location = os.path.join(
+- traversal_external_data_dir, "tensors.bin"
+- )
+- else:
+- traversal_external_data_location = "../invlid_external_data/tensors.bin"
+-
+- external_data_dir = os.path.join(self.temp_dir, "external_data")
+- os.mkdir(external_data_dir)
+- new_model_filepath = os.path.join(model_dir, "model.onnx")
+-
+- def convert_model_to_external_data_no_check(model: ModelProto, location: str):
+- for tensor in model.graph.initializer:
+- if tensor.HasField("raw_data"):
+- set_external_data(tensor, location)
+-
+- convert_model_to_external_data_no_check(
+- model,
+- location=traversal_external_data_location,
+- )
+-
+- onnx.save_model(model, new_model_filepath, self.serialization_format)
+- if use_model_path:
+- with self.assertRaises(onnx.checker.ValidationError):
+- _ = onnx.load_model(new_model_filepath, self.serialization_format)
+- else:
+- onnx_model = onnx.load_model(
+- new_model_filepath, self.serialization_format, load_external_data=False
+- )
+- with self.assertRaises(onnx.checker.ValidationError):
+- load_external_data_for_model(onnx_model, external_data_dir)
+-
+-
+-@parameterized.parameterized_class(
+- [
+- {"serialization_format": "protobuf"},
+- {"serialization_format": "textproto"},
+- ]
+-)
+-class TestSaveAllTensorsAsExternalData(unittest.TestCase):
+- serialization_format: str = "protobuf"
+-
+- def setUp(self) -> None:
+- self._temp_dir_obj = tempfile.TemporaryDirectory()
+- self.temp_dir: str = self._temp_dir_obj.name
+- self.initializer_value = np.arange(6).reshape(3, 2).astype(np.float32) + 512
+- self.attribute_value = np.arange(6).reshape(2, 3).astype(np.float32) + 256
+- self.model = self.create_test_model_proto()
+-
+- def get_temp_model_filename(self):
+- return os.path.join(self.temp_dir, str(uuid.uuid4()) + ".onnx")
+-
+- def create_data_tensors(
+- self, tensors_data: list[tuple[list[Any], Any]]
+- ) -> list[TensorProto]:
+- tensors = []
+- for value, tensor_name in tensors_data:
+- tensor = from_array(np.array(value))
+- tensor.name = tensor_name
+- tensors.append(tensor)
+-
+- return tensors
+-
+- def create_test_model_proto(self) -> ModelProto:
+- tensors = self.create_data_tensors(
+- [
+- (self.attribute_value, "attribute_value"), # type: ignore[list-item]
+- (self.initializer_value, "input_value"), # type: ignore[list-item]
+- ]
+- )
+-
+- constant_node = onnx.helper.make_node(
+- "Constant", inputs=[], outputs=["values"], value=tensors[0]
+- )
+-
+- inputs = [
+- helper.make_tensor_value_info(
+- "input_value", onnx.TensorProto.FLOAT, self.initializer_value.shape
+- )
+- ]
+-
+- graph = helper.make_graph(
+- [constant_node],
+- "test_graph",
+- inputs=inputs,
+- outputs=[],
+- initializer=[tensors[1]],
+- )
+- return helper.make_model(graph)
+-
+- @unittest.skipIf(
+- serialization_format != "protobuf",
+- "check_model supports protobuf only when provided as a path",
+- )
+- def test_check_model(self) -> None:
+- checker.check_model(self.model)
+-
+- def test_convert_model_to_external_data_with_size_threshold(self) -> None:
+- model_file_path = self.get_temp_model_filename()
+-
+- convert_model_to_external_data(self.model, size_threshold=1024)
+- onnx.save_model(self.model, model_file_path, self.serialization_format)
+-
+- model = onnx.load_model(model_file_path, self.serialization_format)
+- initializer_tensor = model.graph.initializer[0]
+- self.assertFalse(initializer_tensor.HasField("data_location"))
+-
+- def test_convert_model_to_external_data_without_size_threshold(self) -> None:
+- model_file_path = self.get_temp_model_filename()
+- convert_model_to_external_data(self.model, size_threshold=0)
+- onnx.save_model(self.model, model_file_path, self.serialization_format)
+-
+- model = onnx.load_model(model_file_path, self.serialization_format)
+- initializer_tensor = model.graph.initializer[0]
+- self.assertTrue(initializer_tensor.HasField("data_location"))
+- np.testing.assert_allclose(to_array(initializer_tensor), self.initializer_value)
+-
+- def test_convert_model_to_external_data_from_one_file_with_location(self) -> None:
+- model_file_path = self.get_temp_model_filename()
+- external_data_file = str(uuid.uuid4())
+-
+- convert_model_to_external_data(
+- self.model,
+- size_threshold=0,
+- all_tensors_to_one_file=True,
+- location=external_data_file,
+- )
+- onnx.save_model(self.model, model_file_path, self.serialization_format)
+-
+- self.assertTrue(os.path.isfile(os.path.join(self.temp_dir, external_data_file)))
+-
+- model = onnx.load_model(model_file_path, self.serialization_format)
+-
+- # test convert model from external data
+- convert_model_from_external_data(model)
+- model_file_path = self.get_temp_model_filename()
+- onnx.save_model(model, model_file_path, self.serialization_format)
+- model = onnx.load_model(model_file_path, self.serialization_format)
+- initializer_tensor = model.graph.initializer[0]
+- self.assertFalse(len(initializer_tensor.external_data))
+- self.assertEqual(initializer_tensor.data_location, TensorProto.DEFAULT)
+- np.testing.assert_allclose(to_array(initializer_tensor), self.initializer_value)
+-
+- attribute_tensor = model.graph.node[0].attribute[0].t
+- self.assertFalse(len(attribute_tensor.external_data))
+- self.assertEqual(attribute_tensor.data_location, TensorProto.DEFAULT)
+- np.testing.assert_allclose(to_array(attribute_tensor), self.attribute_value)
+-
+- def test_convert_model_to_external_data_from_one_file_without_location_uses_model_name(
+- self,
+- ) -> None:
+- model_file_path = self.get_temp_model_filename()
+-
+- convert_model_to_external_data(
+- self.model, size_threshold=0, all_tensors_to_one_file=True
+- )
+- onnx.save_model(self.model, model_file_path, self.serialization_format)
+-
+- self.assertTrue(os.path.isfile(model_file_path))
+- self.assertTrue(os.path.isfile(os.path.join(self.temp_dir, model_file_path)))
+-
+- def test_convert_model_to_external_data_one_file_per_tensor_without_attribute(
+- self,
+- ) -> None:
+- model_file_path = self.get_temp_model_filename()
+-
+- convert_model_to_external_data(
+- self.model,
+- size_threshold=0,
+- all_tensors_to_one_file=False,
+- convert_attribute=False,
+- )
+- onnx.save_model(self.model, model_file_path, self.serialization_format)
+-
+- self.assertTrue(os.path.isfile(model_file_path))
+- self.assertTrue(os.path.isfile(os.path.join(self.temp_dir, "input_value")))
+- self.assertFalse(os.path.isfile(os.path.join(self.temp_dir, "attribute_value")))
+-
+- def test_convert_model_to_external_data_one_file_per_tensor_with_attribute(
+- self,
+- ) -> None:
+- model_file_path = self.get_temp_model_filename()
+-
+- convert_model_to_external_data(
+- self.model,
+- size_threshold=0,
+- all_tensors_to_one_file=False,
+- convert_attribute=True,
+- )
+- onnx.save_model(self.model, model_file_path, self.serialization_format)
+-
+- self.assertTrue(os.path.isfile(model_file_path))
+- self.assertTrue(os.path.isfile(os.path.join(self.temp_dir, "input_value")))
+- self.assertTrue(os.path.isfile(os.path.join(self.temp_dir, "attribute_value")))
+-
+- def test_convert_model_to_external_data_does_not_convert_attribute_values(
+- self,
+- ) -> None:
+- model_file_path = self.get_temp_model_filename()
+-
+- convert_model_to_external_data(
+- self.model,
+- size_threshold=0,
+- convert_attribute=False,
+- all_tensors_to_one_file=False,
+- )
+- onnx.save_model(self.model, model_file_path, self.serialization_format)
+-
+- self.assertTrue(os.path.isfile(os.path.join(self.temp_dir, "input_value")))
+- self.assertFalse(os.path.isfile(os.path.join(self.temp_dir, "attribute_value")))
+-
+- model = onnx.load_model(model_file_path, self.serialization_format)
+- initializer_tensor = model.graph.initializer[0]
+- self.assertTrue(initializer_tensor.HasField("data_location"))
+-
+- attribute_tensor = model.graph.node[0].attribute[0].t
+- self.assertFalse(attribute_tensor.HasField("data_location"))
+-
+- def test_convert_model_to_external_data_converts_attribute_values(self) -> None:
+- model_file_path = self.get_temp_model_filename()
+-
+- convert_model_to_external_data(
+- self.model, size_threshold=0, convert_attribute=True
+- )
+- onnx.save_model(self.model, model_file_path, self.serialization_format)
+-
+- model = onnx.load_model(model_file_path, self.serialization_format)
+-
+- initializer_tensor = model.graph.initializer[0]
+- np.testing.assert_allclose(to_array(initializer_tensor), self.initializer_value)
+- self.assertTrue(initializer_tensor.HasField("data_location"))
+-
+- attribute_tensor = model.graph.node[0].attribute[0].t
+- np.testing.assert_allclose(to_array(attribute_tensor), self.attribute_value)
+- self.assertTrue(attribute_tensor.HasField("data_location"))
+-
+- def test_save_model_does_not_convert_to_external_data_and_saves_the_model(
+- self,
+- ) -> None:
+- model_file_path = self.get_temp_model_filename()
+- onnx.save_model(
+- self.model,
+- model_file_path,
+- self.serialization_format,
+- save_as_external_data=False,
+- )
+- self.assertTrue(os.path.isfile(model_file_path))
+-
+- model = onnx.load_model(model_file_path, self.serialization_format)
+- initializer_tensor = model.graph.initializer[0]
+- self.assertFalse(initializer_tensor.HasField("data_location"))
+-
+- attribute_tensor = model.graph.node[0].attribute[0].t
+- self.assertFalse(attribute_tensor.HasField("data_location"))
+-
+- def test_save_model_does_convert_and_saves_the_model(self) -> None:
+- model_file_path = self.get_temp_model_filename()
+- onnx.save_model(
+- self.model,
+- model_file_path,
+- self.serialization_format,
+- save_as_external_data=True,
+- all_tensors_to_one_file=True,
+- location=None,
+- size_threshold=0,
+- convert_attribute=False,
+- )
+-
+- model = onnx.load_model(model_file_path, self.serialization_format)
+-
+- initializer_tensor = model.graph.initializer[0]
+- self.assertTrue(initializer_tensor.HasField("data_location"))
+- np.testing.assert_allclose(to_array(initializer_tensor), self.initializer_value)
+-
+- attribute_tensor = model.graph.node[0].attribute[0].t
+- self.assertFalse(attribute_tensor.HasField("data_location"))
+- np.testing.assert_allclose(to_array(attribute_tensor), self.attribute_value)
+-
+- def test_save_model_without_loading_external_data(self) -> None:
+- model_file_path = self.get_temp_model_filename()
+- onnx.save_model(
+- self.model,
+- model_file_path,
+- self.serialization_format,
+- save_as_external_data=True,
+- location=None,
+- size_threshold=0,
+- convert_attribute=False,
+- )
+- # Save without load_external_data
+- model = onnx.load_model(
+- model_file_path, self.serialization_format, load_external_data=False
+- )
+- onnx.save_model(
+- model,
+- model_file_path,
+- self.serialization_format,
+- save_as_external_data=True,
+- location=None,
+- size_threshold=0,
+- convert_attribute=False,
+- )
+- # Load the saved model again; Only works if the saved path is under the same directory
+- model = onnx.load_model(model_file_path, self.serialization_format)
+-
+- initializer_tensor = model.graph.initializer[0]
+- self.assertTrue(initializer_tensor.HasField("data_location"))
+- np.testing.assert_allclose(to_array(initializer_tensor), self.initializer_value)
+-
+- attribute_tensor = model.graph.node[0].attribute[0].t
+- self.assertFalse(attribute_tensor.HasField("data_location"))
+- np.testing.assert_allclose(to_array(attribute_tensor), self.attribute_value)
+-
+- def test_save_model_with_existing_raw_data_should_override(self) -> None:
+- model_file_path = self.get_temp_model_filename()
+- original_raw_data = self.model.graph.initializer[0].raw_data
+- onnx.save_model(
+- self.model,
+- model_file_path,
+- self.serialization_format,
+- save_as_external_data=True,
+- size_threshold=0,
+- )
+- self.assertTrue(os.path.isfile(model_file_path))
+-
+- model = onnx.load_model(
+- model_file_path, self.serialization_format, load_external_data=False
+- )
+- initializer_tensor = model.graph.initializer[0]
+- initializer_tensor.raw_data = b"dummpy_raw_data"
+- # If raw_data and external tensor exist at the same time, override existing raw_data
+- load_external_data_for_tensor(initializer_tensor, self.temp_dir)
+- self.assertEqual(initializer_tensor.raw_data, original_raw_data)
+-
+-
+-@parameterized.parameterized_class(
+- [
+- {"serialization_format": "protobuf"},
+- {"serialization_format": "textproto"},
+- ]
+-)
+-class TestExternalDataToArray(unittest.TestCase):
+- serialization_format: str = "protobuf"
+-
+- def setUp(self) -> None:
+- self._temp_dir_obj = tempfile.TemporaryDirectory()
+- self.temp_dir: str = self._temp_dir_obj.name
+- self._model_file_path: str = os.path.join(self.temp_dir, "model.onnx")
+- self.large_data = np.random.rand(10, 60, 100).astype(np.float32)
+- self.small_data = (200, 300)
+- self.model = self.create_test_model()
+-
+- @property
+- def model_file_path(self):
+- return self._model_file_path
+-
+- def tearDown(self) -> None:
+- self._temp_dir_obj.cleanup()
+-
+- def create_test_model(self) -> ModelProto:
+- X = helper.make_tensor_value_info("X", TensorProto.FLOAT, self.large_data.shape)
+- input_init = helper.make_tensor(
+- name="X",
+- data_type=TensorProto.FLOAT,
+- dims=self.large_data.shape,
+- vals=self.large_data.tobytes(),
+- raw=True,
+- )
+-
+- shape_data = np.array(self.small_data, np.int64)
+- shape_init = helper.make_tensor(
+- name="Shape",
+- data_type=TensorProto.INT64,
+- dims=shape_data.shape,
+- vals=shape_data.tobytes(),
+- raw=True,
+- )
+- C = helper.make_tensor_value_info("C", TensorProto.INT64, self.small_data)
+-
+- reshape = onnx.helper.make_node(
+- "Reshape",
+- inputs=["X", "Shape"],
+- outputs=["Y"],
+- )
+- cast = onnx.helper.make_node(
+- "Cast", inputs=["Y"], outputs=["C"], to=TensorProto.INT64
+- )
+-
+- graph_def = helper.make_graph(
+- [reshape, cast],
+- "test-model",
+- [X],
+- [C],
+- initializer=[input_init, shape_init],
+- )
+- model = helper.make_model(graph_def, producer_name="onnx-example")
+- return model
+-
+- @unittest.skipIf(
+- serialization_format != "protobuf",
+- "check_model supports protobuf only when provided as a path",
+- )
+- def test_check_model(self) -> None:
+- checker.check_model(self.model)
+-
+- def test_reshape_inference_with_external_data_fail(self) -> None:
+- onnx.save_model(
+- self.model,
+- self.model_file_path,
+- self.serialization_format,
+- save_as_external_data=True,
+- all_tensors_to_one_file=False,
+- size_threshold=0,
+- )
+- model_without_external_data = onnx.load(
+- self.model_file_path, self.serialization_format, load_external_data=False
+- )
+- # Shape inference of Reshape uses ParseData
+- # ParseData cannot handle external data and should throw the error as follows:
+- # Cannot parse data from external tensors. Please load external data into raw data for tensor: Shape
+- self.assertRaises(
+- shape_inference.InferenceError,
+- shape_inference.infer_shapes,
+- model_without_external_data,
+- strict_mode=True,
+- )
+-
+- def test_to_array_with_external_data(self) -> None:
+- onnx.save_model(
+- self.model,
+- self.model_file_path,
+- self.serialization_format,
+- save_as_external_data=True,
+- all_tensors_to_one_file=False,
+- size_threshold=0,
+- )
+- # raw_data of external tensor is not loaded
+- model = onnx.load(
+- self.model_file_path, self.serialization_format, load_external_data=False
+- )
+- # Specify self.temp_dir to load external tensor
+- loaded_large_data = to_array(model.graph.initializer[0], self.temp_dir)
+- np.testing.assert_allclose(loaded_large_data, self.large_data)
+-
+- def test_save_model_with_external_data_multiple_times(self) -> None:
+- # Test onnx.save should respectively handle typical tensor and external tensor properly
+- # 1st save: save two tensors which have raw_data
+- # Only w_large will be stored as external tensors since it's larger than 1024
+- onnx.save_model(
+- self.model,
+- self.model_file_path,
+- self.serialization_format,
+- save_as_external_data=True,
+- all_tensors_to_one_file=False,
+- location=None,
+- size_threshold=1024,
+- convert_attribute=True,
+- )
+- model_without_loading_external = onnx.load(
+- self.model_file_path, self.serialization_format, load_external_data=False
+- )
+- large_input_tensor = model_without_loading_external.graph.initializer[0]
+- self.assertTrue(large_input_tensor.HasField("data_location"))
+- np.testing.assert_allclose(
+- to_array(large_input_tensor, self.temp_dir), self.large_data
+- )
+-
+- small_shape_tensor = model_without_loading_external.graph.initializer[1]
+- self.assertTrue(not small_shape_tensor.HasField("data_location"))
+- np.testing.assert_allclose(to_array(small_shape_tensor), self.small_data)
+-
+- # 2nd save: one tensor has raw_data (small); one external tensor (large)
+- # Save them both as external tensors this time
+- onnx.save_model(
+- model_without_loading_external,
+- self.model_file_path,
+- self.serialization_format,
+- save_as_external_data=True,
+- all_tensors_to_one_file=False,
+- location=None,
+- size_threshold=0,
+- convert_attribute=True,
+- )
+-
+- model_without_loading_external = onnx.load(
+- self.model_file_path, self.serialization_format, load_external_data=False
+- )
+- large_input_tensor = model_without_loading_external.graph.initializer[0]
+- self.assertTrue(large_input_tensor.HasField("data_location"))
+- np.testing.assert_allclose(
+- to_array(large_input_tensor, self.temp_dir), self.large_data
+- )
+-
+- small_shape_tensor = model_without_loading_external.graph.initializer[1]
+- self.assertTrue(small_shape_tensor.HasField("data_location"))
+- np.testing.assert_allclose(
+- to_array(small_shape_tensor, self.temp_dir), self.small_data
+- )
+-
+-
+ class TestNotAllowToLoadExternalDataOutsideModelDirectory(TestLoadExternalDataBase):
+ """Essential test to check that onnx (validate) C++ code will not allow to load external_data outside the model
+ directory.
+@@ -791,17 +175,6 @@ class TestNotAllowToLoadExternalDataOutsideModelDirectoryOnWindows(
+ checker.check_model(self.model_filename)
+
+
+-class TestSaveAllTensorsAsExternalDataWithPath(TestSaveAllTensorsAsExternalData):
+- def get_temp_model_filename(self) -> pathlib.Path:
+- return pathlib.Path(super().get_temp_model_filename())
+-
+-
+-class TestExternalDataToArrayWithPath(TestExternalDataToArray):
+- @property
+- def model_file_path(self) -> pathlib.Path:
+- return pathlib.Path(self._model_file_path)
+-
+-
+ class TestFunctionsAndSubGraphs(unittest.TestCase):
+ def setUp(self) -> None:
+ self._temp_dir_obj = tempfile.TemporaryDirectory()
+diff --git a/onnx/test/tools_test.py b/onnx/test/tools_test.py
+index fd4413786..f843c1fbc 100644
+--- a/onnx/test/tools_test.py
++++ b/onnx/test/tools_test.py
+@@ -112,32 +112,6 @@ class TestToolsFunctions(unittest.TestCase):
+ y2 = oinf2.run(None, {"X": x})[0] # type: ignore[index]
+ assert_allclose(y1, y2)
+
+- def test_replace_range(self):
+- dtype = np.float32
+- value = np.random.randn(2, 100).astype(dtype)
+- A = numpy_helper.from_array(value, name="A")
+- value = np.array([1], dtype=dtype)
+- C = numpy_helper.from_array(value, name="C")
+-
+- X = helper.make_tensor_value_info("X", TensorProto.FLOAT, [None, None])
+- Y = helper.make_tensor_value_info("Y", TensorProto.FLOAT, [None])
+- node0 = helper.make_node("Constant", [], ["A"], value=A)
+- node1 = helper.make_node("MatMul", ["X", "A"], ["AX"])
+- node2 = helper.make_node("Sub", ["AX", "C"], ["Y"])
+- graph = helper.make_graph([node0, node1, node2], "lr", [X], [Y], [C])
+- model_def = helper.make_model(graph)
+-
+- x = np.array([1, 2, 4, 5, 5, 4]).astype(np.float32).reshape((3, 2))
+- oinf1 = ReferenceEvaluator(model_def)
+- y1 = oinf1.run(None, {"X": x})[0] # type: ignore[index]
+- repl = replace_initializer_by_constant_of_shape(model_def, use_range=True)
+- node_types = {n.op_type for n in repl.graph.node}
+- self.assertIn("Range", node_types)
+- self.assertNotIn("ConstantOfShape", node_types)
+- oinf2 = ReferenceEvaluator(repl)
+- y2 = oinf2.run(None, {"X": x})[0] # type: ignore[index]
+- assert_allclose(y1.shape, y2.shape)
+-
+ def test_replace_constant_function(self):
+ dtype = np.float32
+ value = np.random.randn(2, 100).astype(dtype)
+@@ -182,49 +156,6 @@ class TestToolsFunctions(unittest.TestCase):
+ y2 = oinf2.run(None, {"X": x})[0] # type: ignore[index]
+ assert_allclose(y1, y2)
+
+- def test_replace_range_function(self):
+- dtype = np.float32
+- value = np.random.randn(2, 100).astype(dtype)
+- A = numpy_helper.from_array(value, name="A")
+- value = np.array([1], dtype=dtype)
+- C = numpy_helper.from_array(value, name="C")
+-
+- X = helper.make_tensor_value_info("X", TensorProto.FLOAT, [None, None])
+- Y = helper.make_tensor_value_info("Y", TensorProto.FLOAT, [None])
+- nodeC = helper.make_node("Constant", [], ["C"], value=C)
+- node0 = helper.make_node("Constant", [], ["A"], value=A)
+- node1 = helper.make_node("MatMul", ["X", "A"], ["AX"])
+- node2 = helper.make_node("Sub", ["AX", "C"], ["Y"])
+- opset_imports = [
+- helper.make_opsetid("", onnx_opset_version()),
+- helper.make_opsetid("custom", 1),
+- ]
+- fct = helper.make_function(
+- "custom",
+- "unittest",
+- ["X"],
+- ["Y"],
+- [nodeC, node0, node1, node2],
+- opset_imports,
+- )
+-
+- node = helper.make_node("unittest", ["X"], ["Y"], domain="custom")
+- graph = helper.make_graph([node], "lr", [X], [Y], [C])
+- model_def = helper.make_model(
+- graph, functions=[fct], opset_imports=opset_imports
+- )
+-
+- x = np.array([1, 2, 4, 5, 5, 4]).astype(np.float32).reshape((3, 2))
+- oinf1 = ReferenceEvaluator(model_def)
+- y1 = oinf1.run(None, {"X": x})[0] # type: ignore[index]
+- repl = replace_initializer_by_constant_of_shape(model_def, use_range=True)
+- node_types = {n.op_type for n in repl.functions[0].node}
+- self.assertIn("Range", node_types)
+- self.assertNotIn("ConstantOfShape", node_types)
+- oinf2 = ReferenceEvaluator(repl)
+- y2 = oinf2.run(None, {"X": x})[0] # type: ignore[index]
+- assert_allclose(y1.shape, y2.shape)
+-
+ def test_replace_constant_graph(self):
+ value = np.array([0], dtype=np.float32)
+ zero = numpy_helper.from_array(value, name="zero")
+@@ -274,54 +205,6 @@ class TestToolsFunctions(unittest.TestCase):
+ y1[:] = 0.5
+ assert_allclose(y1, y2)
+
+- def test_replace_range_graph(self):
+- value = np.array([0], dtype=np.float32)
+- zero = numpy_helper.from_array(value, name="zero")
+-
+- X = helper.make_tensor_value_info("X", onnx.TensorProto.FLOAT, [None, None])
+- Y = helper.make_tensor_value_info("Y", onnx.TensorProto.FLOAT, [None])
+-
+- rsum = helper.make_node("ReduceSum", ["X"], ["rsum"])
+- cond = helper.make_node("Greater", ["rsum", "zero"], ["cond"])
+-
+- then_out = helper.make_tensor_value_info(
+- "then_out", onnx.TensorProto.FLOAT, None
+- )
+- then_cst = numpy_helper.from_array(np.array([1] * 129).astype(np.float32))
+-
+- then_const_node = helper.make_node(
+- "Constant", inputs=[], outputs=["then_out"], value=then_cst, name="cst1"
+- )
+- then_body = helper.make_graph([then_const_node], "then_body", [], [then_out])
+-
+- else_out = helper.make_tensor_value_info(
+- "else_out", onnx.TensorProto.FLOAT, None
+- )
+- else_cst = numpy_helper.from_array(np.array([-1] * 129).astype(np.float32))
+- else_const_node = helper.make_node(
+- "Constant", inputs=[], outputs=["else_out"], value=else_cst, name="cst2"
+- )
+- else_body = helper.make_graph([else_const_node], "else_body", [], [else_out])
+-
+- if_node = onnx.helper.make_node(
+- "If", ["cond"], ["Y"], then_branch=then_body, else_branch=else_body
+- )
+- graph = helper.make_graph([rsum, cond, if_node], "if", [X], [Y], [zero])
+- onnx_model = helper.make_model(
+- graph, opset_imports=[helper.make_opsetid("", onnx_opset_version())]
+- )
+- self.assertNotIn("ConstantOfShape", str(onnx_model))
+-
+- x = np.ones((3, 2), dtype=np.float32)
+- oinf1 = ReferenceEvaluator(onnx_model)
+- y1 = oinf1.run(None, {"X": x})[0] # type: ignore[index]
+- repl = replace_initializer_by_constant_of_shape(onnx_model, use_range=True)
+- self.assertNotIn("ConstantOfShape", str(repl))
+- self.assertIn("Range", str(repl))
+- oinf2 = ReferenceEvaluator(repl)
+- y2 = oinf2.run(None, {"X": x})[0] # type: ignore[index]
+- assert_allclose(y1.shape, y2.shape)
+-
+
+ if __name__ == "__main__":
+ unittest.main(verbosity=2)
+diff --git a/onnx/test/version_converter/automatic_downgrade_test.py b/onnx/test/version_converter/automatic_downgrade_test.py
+index a94aea1a9..f639d44f8 100644
+--- a/onnx/test/version_converter/automatic_downgrade_test.py
++++ b/onnx/test/version_converter/automatic_downgrade_test.py
+@@ -7,7 +7,6 @@ import unittest
+
+ import automatic_conversion_test_base
+ import numpy as np
+-import parameterized
+
+ import onnx
+ from onnx import helper
+@@ -22,35 +21,6 @@ class TestAutomaticDowngrade(automatic_conversion_test_base.TestAutomaticConvers
+ def _test_op_downgrade(self, op: str, *args, **kwargs):
+ self._test_op_conversion(op, *args, **kwargs, is_upgrade=False)
+
+- @parameterized.parameterized.expand(
+- [
+- "ReduceL1",
+- "ReduceL2",
+- "ReduceLogSum",
+- "ReduceLogSumExp",
+- "ReduceMean",
+- "ReduceMax",
+- "ReduceMin",
+- "ReduceProd",
+- "ReduceSum",
+- "ReduceSumSquare",
+- ]
+- )
+- def test_reduce_ops(self, op) -> None:
+- # TODO: need to add test cases for missing axes input which depends on this pr:
+- # https://github.com/onnx/onnx/pull/5613
+- axes = helper.make_tensor(
+- "b", onnx.TensorProto.INT64, dims=[3], vals=np.array([0, 1, 2])
+- )
+- self._test_op_downgrade(
+- op,
+- from_opset=13,
+- input_shapes=[[3, 4, 5], [3]],
+- output_shapes=[[1, 1, 1]],
+- input_types=[onnx.TensorProto.FLOAT, onnx.TensorProto.INT64],
+- initializer=[axes],
+- )
+-
+ def test_dft20_no_axis(self) -> None:
+ self._test_model_conversion(
+ to_opset=19,
+diff --git a/onnx/test/version_converter_test.py b/onnx/test/version_converter_test.py
+index 1790e5997..4a4c27766 100644
+--- a/onnx/test/version_converter_test.py
++++ b/onnx/test/version_converter_test.py
+@@ -8,7 +8,6 @@ import struct
+ import unittest
+
+ import numpy as np
+-import parameterized
+
+ import onnx.version_converter
+ from onnx import (
+@@ -2006,169 +2005,6 @@ class TestVersionConverter(unittest.TestCase):
+ assert converted_model.graph.node[3].op_type == "Reshape"
+ assert converted_model.opset_import[0].version == 13
+
+- @parameterized.parameterized.expand(
+- [
+- ("per_tensor", (16, 3), (1,), None, None, None, TensorProto.INT8, True),
+- (
+- "per_axis_none_block_shape",
+- (16, 3),
+- (16,),
+- 1,
+- None,
+- None,
+- TensorProto.INT8,
+- True,
+- ),
+- (
+- "per_axis_zero_block_shape",
+- (16, 3),
+- (16,),
+- 1,
+- 0,
+- None,
+- TensorProto.INT8,
+- True,
+- ),
+- (
+- "per_tensor_positive_block_shape",
+- (16, 3),
+- (1,),
+- 1,
+- 2,
+- None,
+- TensorProto.INT8,
+- False,
+- ),
+- (
+- "per_axis_positive_block_shape",
+- (16, 3),
+- (16,),
+- 1,
+- 2,
+- None,
+- TensorProto.INT8,
+- False,
+- ),
+- ("blocked_2d", (16, 3), (4, 3), 0, 4, None, TensorProto.INT8, False),
+- ("blocked_3d", (4, 3, 32), (4, 3, 8), 2, 4, None, TensorProto.INT8, False),
+- (
+- "per_axis_output_dtype",
+- (16, 3),
+- (16,),
+- 1,
+- None,
+- TensorProto.FLOAT8E4M3FN,
+- None,
+- False,
+- ),
+- (
+- "per_axis_unsupported_type",
+- (16, 3),
+- (16,),
+- 1,
+- None,
+- None,
+- TensorProto.UINT16,
+- False,
+- ),
+- ]
+- )
+- def test_quantize_21_20(
+- self,
+- _: str,
+- x_shape: tuple[int, ...],
+- scale_shape: tuple[int, ...],
+- axis: int,
+- block_size: int,
+- output_dtype: int | None,
+- zero_point_dtype: int | None,
+- compatible: bool,
+- ) -> None:
+- def test(
+- input_shape, scale_shape, axis, block_size, output_dtype, zero_point_dtype
+- ) -> None:
+- nodes = [
+- helper.make_node(
+- "QuantizeLinear",
+- ["X", "S"],
+- ["Y"],
+- axis=axis,
+- block_size=block_size,
+- output_dtype=output_dtype,
+- )
+- ]
+- inputs = [
+- helper.make_tensor_value_info("X", TensorProto.FLOAT, input_shape),
+- helper.make_tensor_value_info("S", TensorProto.FLOAT, scale_shape),
+- ]
+- if zero_point_dtype:
+- inputs.append(
+- helper.make_tensor_value_info("ZP", zero_point_dtype, scale_shape)
+- )
+- nodes[0].input.append("ZP")
+- output_type_ = output_dtype or zero_point_dtype
+- graph = helper.make_graph(
+- nodes,
+- "test",
+- inputs,
+- [helper.make_tensor_value_info("Y", output_type_, input_shape)],
+- )
+- _ = self._converted(graph, helper.make_operatorsetid("", 21), 20)
+-
+- context_manager = (
+- contextlib.nullcontext() if compatible else self.assertRaises(RuntimeError)
+- )
+- with context_manager: # type: ignore[attr-defined]
+- test(x_shape, scale_shape, axis, block_size, output_dtype, zero_point_dtype)
+-
+- @parameterized.parameterized.expand(
+- [
+- ("per_tensor", (16, 3), (1,), None, None, True),
+- ("per_axis_none_block_shape", (16, 3), (16,), 1, None, True),
+- ("per_axis_zero_block_shape", (16, 3), (16,), 1, 0, True),
+- ("per_tensor_positive_block_shape", (16, 3), (1,), 1, 2, False),
+- ("per_axis_positive_block_shape", (16, 3), (16,), 1, 2, False),
+- ("blocked_2d", (16, 3), (4, 3), 0, 4, False),
+- ("blocked_3d", (4, 3, 32), (4, 3, 8), 2, 4, False),
+- ]
+- )
+- def test_dequantize_21_20(
+- self,
+- _: str,
+- y_shape: tuple[int, ...],
+- scale_shape: tuple[int, ...],
+- axis: int,
+- block_size: int,
+- compatible: bool,
+- ) -> None:
+- def test(input_shape, scale_shape, axis, block_size) -> None:
+- nodes = [
+- helper.make_node(
+- "DequantizeLinear",
+- ["X", "S", "ZP"],
+- ["Y"],
+- axis=axis,
+- block_size=block_size,
+- )
+- ]
+- graph = helper.make_graph(
+- nodes,
+- "test",
+- [
+- helper.make_tensor_value_info("X", TensorProto.INT8, input_shape),
+- helper.make_tensor_value_info("S", TensorProto.FLOAT, scale_shape),
+- helper.make_tensor_value_info("ZP", TensorProto.INT8, scale_shape),
+- ],
+- [helper.make_tensor_value_info("Y", TensorProto.FLOAT, input_shape)],
+- )
+- _ = self._converted(graph, helper.make_operatorsetid("", 21), 20)
+-
+- context_manager = (
+- contextlib.nullcontext() if compatible else self.assertRaises(RuntimeError)
+- )
+- with context_manager: # type: ignore[attr-defined]
+- test(y_shape, scale_shape, axis, block_size)
+-
+
+ if __name__ == "__main__":
+ unittest.main()
+diff --git a/requirements-dev.txt b/requirements-dev.txt
+index ea38712d8..165b3f7f4 100644
+--- a/requirements-dev.txt
++++ b/requirements-dev.txt
+@@ -2,7 +2,6 @@ build
+ jupyter
+ nbval
+ numpy
+-parameterized
+ protobuf
+ pytest
+ pytest-cov
+diff --git a/requirements-release.txt b/requirements-release.txt
+index 9a9d85351..0c19ebdb5 100644
+--- a/requirements-release.txt
++++ b/requirements-release.txt
+@@ -3,7 +3,6 @@ ipython
+ nbval
+ numpy==1.24.3; python_version<"3.9"
+ numpy==2.0.0; python_version>="3.9"
+-parameterized
+ protobuf==4.21.12; python_version<"3.12"
+ protobuf==4.25.1; python_version>="3.12"
+ pytest
+diff --git a/requirements.txt b/requirements.txt
+index 46dd7f7fd..62dac8a3b 100644
+--- a/requirements.txt
++++ b/requirements.txt
+@@ -1,3 +1,2 @@
+ numpy>=1.20
+ protobuf >= 3.14.0, < 4
+-parameterized >= 0.8.1, < 1
+--
+2.52.0
+
diff --git a/onnx.spec b/onnx.spec
index 9b41741..54f2167 100644
--- a/onnx.spec
+++ b/onnx.spec
@@ -1,19 +1,21 @@
Name: onnx
Version: 1.17.0
-Release: 8%{?dist}
+Release: 9%{?dist}
Summary: Open standard for machine learning interoperability
License: Apache-2.0
URL: https://github.com/onnx/onnx
Source0: https://github.com/onnx/onnx/archive/v%{version}/%{name}-%{version}.tar.gz
# Build shared libraries and fix install location
-Patch0: 0000-Build-shared-libraries-and-fix-install-location.patch
+Patch: 0000-Build-shared-libraries-and-fix-install-location.patch
# Use system protobuf and require parameterized
-Patch2: 0002-Use-system-protobuf-and-require-parameterized.patch
+Patch: 0001-Use-system-protobuf-and-require-parameterized.patch
# Let pyproject_wheel use binaries from cmake_build
-Patch3: 0003-Let-pyproject_wheel-use-binaries-from-cmake_build.patch
+Patch: 0002-Let-pyproject_wheel-use-binaries-from-cmake_build.patch
# Add fixes for use with onnxruntime
-Patch4: 0004-Add-fixes-for-use-with-onnxruntime.patch
+Patch: 0003-Add-fixes-for-use-with-onnxruntime.patch
+# Add fixes for use with onnxruntime
+Patch: 0004-Remove-python-parameterized-dependency.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2212096
ExcludeArch: s390x
@@ -122,6 +124,10 @@ export LD_LIBRARY_PATH=%{buildroot}/%{_libdir}
%{_bindir}/check-node
%changelog
+* Thu Jan 15 2026 Diego Herrera <dherrera@fedoraproject.org> - 1.17.0-9
+- Disable tests that depend on python-parameterized
+- Clean up patches
+
* Fri Sep 19 2025 Python Maint <python-maint@redhat.com> - 1.17.0-8
- Rebuilt for Python 3.14.0rc3 bytecode
reply other threads:[~2026-06-08 15:18 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=178093190724.1.1640843290736511251.rpms-onnx-8f9af18ab5ad@fedoraproject.org \
--to=dherrera@redhat.com \
--cc=git-commits@fedoraproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox