Coverage for /opt/cloud/slavespace/usr1/096471637100f3de0fcfc01072822a80/dttest/api/python/ge/ge/onnx_plugin/plugin.py: 100%
45 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-18 20:50 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-18 20:50 +0800
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# -----------------------------------------------------------------------------------------------------------
4# Copyright (c) 2026 Huawei Technologies Co., Ltd.
5# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
6# CANN Open Software License Agreement Version 2.0 (the "License").
7# Please refer to the License for details. You may not use this file except in compliance with the License.
8# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
9# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
10# See LICENSE in the root of the software repository for the full text of the License.
11# -----------------------------------------------------------------------------------------------------------
13"""Public descriptor and callback decorator for Python ONNX Plugins."""
15import inspect
16from collections.abc import Collection
17from typing import Callable, Optional, Tuple
19from .registry import OnnxPluginDescriptor, register_onnx_plugin
22def _normalize_name(
23 value: str, field_name: str, *, reject_origin_separator=False
24) -> str:
25 if not isinstance(value, str) or not value:
26 raise TypeError(f"onnx_plugin {field_name} must be a non-empty string")
27 if reject_origin_separator and "::" in value:
28 raise TypeError(f"onnx_plugin {field_name} must not contain '::'")
29 return value
32def _normalize_opsets(opsets: Collection[int]) -> Tuple[int, ...]:
33 if isinstance(opsets, (str, bytes)) or not isinstance(opsets, Collection):
34 raise TypeError("onnx_plugin opsets must be a collection of positive integers")
35 if not opsets:
36 raise ValueError("onnx_plugin opsets must not be empty")
37 normalized = set()
38 for opset in opsets:
39 if type(opset) is not int:
40 raise TypeError("onnx_plugin opsets must contain only integers")
41 if opset <= 0:
42 raise ValueError("onnx_plugin opsets must contain only positive integers")
43 normalized.add(opset)
44 return tuple(sorted(normalized))
47class OnnxPlugin:
48 """ONNX source-to-target descriptor awaiting a parse_node callback."""
50 __slots__ = ("_descriptor", "_domain", "_opsets", "_source", "_target")
52 def __init__(
53 self, *, source: str, domain: str, opsets: Tuple[int, ...], target: str
54 ) -> None:
55 self._source = source
56 self._domain = domain
57 self._opsets = opsets
58 self._target = target
59 self._descriptor: Optional[OnnxPluginDescriptor] = None
61 def parse_node(self, fn: Callable[..., None]) -> Callable[..., None]:
62 if self._descriptor is not None:
63 raise ValueError("OnnxPlugin parse_node is already bound")
64 if not inspect.isfunction(fn):
65 raise TypeError("OnnxPlugin parse_node expects a Python function")
67 module_name = fn.__module__
68 parser_node_name = fn.__qualname__
69 origin_types = tuple(
70 f"{self._domain}::{opset}::{self._source}" for opset in self._opsets
71 )
72 descriptor = register_onnx_plugin(
73 OnnxPluginDescriptor(
74 descriptor_key=(
75 f"{module_name}:{parser_node_name}:{self._domain}:"
76 f"{self._source}:{','.join(map(str, self._opsets))}"
77 ),
78 source=self._source,
79 domain=self._domain,
80 opsets=self._opsets,
81 target=self._target,
82 origin_types=origin_types,
83 module_name=module_name,
84 parser_node=fn,
85 )
86 )
87 self._descriptor = descriptor
88 setattr(fn, "__ge_onnx_plugin_descriptor__", descriptor)
89 return fn
92def onnx_plugin(
93 *, source: str, domain: str, opsets: Collection[int], target: str
94) -> OnnxPlugin:
95 """Create an ONNX Plugin descriptor for binding a parse_node callback."""
97 return OnnxPlugin(
98 source=_normalize_name(source, "source", reject_origin_separator=True),
99 domain=_normalize_name(domain, "domain", reject_origin_separator=True),
100 opsets=_normalize_opsets(opsets),
101 target=_normalize_name(target, "target"),
102 )