onnx-ir 0.1.8__py3-none-any.whl → 0.1.10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of onnx-ir might be problematic. Click here for more details.

onnx_ir/__init__.py CHANGED
@@ -78,6 +78,7 @@ __all__ = [
78
78
  # Convenience constructors
79
79
  "tensor",
80
80
  "node",
81
+ "val",
81
82
  # Pass infrastructure
82
83
  "passes",
83
84
  # IO
@@ -90,7 +91,7 @@ __all__ = [
90
91
  import types
91
92
 
92
93
  from onnx_ir import convenience, external_data, passes, serde, tape, traversal
93
- from onnx_ir._convenience._constructors import node, tensor
94
+ from onnx_ir._convenience._constructors import node, tensor, val
94
95
  from onnx_ir._core import (
95
96
  Attr,
96
97
  AttrFloat32,
@@ -167,4 +168,4 @@ def __set_module() -> None:
167
168
 
168
169
 
169
170
  __set_module()
170
- __version__ = "0.1.8"
171
+ __version__ = "0.1.10"
@@ -226,7 +226,7 @@ def convert_attributes(
226
226
  ... "type_protos": [ir.TensorType(ir.DataType.FLOAT), ir.TensorType(ir.DataType.FLOAT)],
227
227
  ... }
228
228
  >>> convert_attributes(attrs)
229
- [Attr('int', INT, 1), Attr('float', FLOAT, 1.0), Attr('str', STRING, 'hello'), Attr('ints', INTS, [1, 2, 3]), Attr('floats', FLOATS, [1.0, 2.0, 3.0]), Attr('strings', STRINGS, ['hello', 'world']), Attr('tensor', TENSOR, Tensor<DOUBLE,[3]>(array([1., 2., 3.]), name=None)), Attr('tensor_proto', TENSOR, TensorProtoTensor<FLOAT,[3]>(array([1., 2., 3.], dtype=float32), name='proto')), Attr('graph', GRAPH, Graph(
229
+ [Attr('int', INT, 1), Attr('float', FLOAT, 1.0), Attr('str', STRING, 'hello'), Attr('ints', INTS, (1, 2, 3)), Attr('floats', FLOATS, (1.0, 2.0, 3.0)), Attr('strings', STRINGS, ('hello', 'world')), Attr('tensor', TENSOR, Tensor<DOUBLE,[3]>(array([1., 2., 3.]), name=None)), Attr('tensor_proto', TENSOR, TensorProtoTensor<FLOAT,[3]>(array([1., 2., 3.], dtype=float32), name='proto')), Attr('graph', GRAPH, Graph(
230
230
  name='graph0',
231
231
  inputs=(
232
232
  <BLANKLINE>
@@ -235,7 +235,7 @@ def convert_attributes(
235
235
  <BLANKLINE>
236
236
  ),
237
237
  len()=0
238
- )), Attr('graphs', GRAPHS, [Graph(
238
+ )), Attr('graphs', GRAPHS, (Graph(
239
239
  name='graph1',
240
240
  inputs=(
241
241
  <BLANKLINE>
@@ -253,7 +253,7 @@ def convert_attributes(
253
253
  <BLANKLINE>
254
254
  ),
255
255
  len()=0
256
- )]), Attr('type_proto', TYPE_PROTO, Tensor(FLOAT)), Attr('type_protos', TYPE_PROTOS, [Tensor(FLOAT), Tensor(FLOAT)])]
256
+ ))), Attr('type_proto', TYPE_PROTO, Tensor(FLOAT)), Attr('type_protos', TYPE_PROTOS, (Tensor(FLOAT), Tensor(FLOAT)))]
257
257
 
258
258
  .. important::
259
259
  An empty sequence should be created with an explicit type by initializing
@@ -293,7 +293,7 @@ def replace_all_uses_with(
293
293
  We want to replace the node A with a new node D::
294
294
 
295
295
  >>> import onnx_ir as ir
296
- >>> input = ir.Input("input")
296
+ >>> input = ir.val("input")
297
297
  >>> node_a = ir.Node("", "A", [input])
298
298
  >>> node_b = ir.Node("", "B", node_a.outputs)
299
299
  >>> node_c = ir.Node("", "C", node_a.outputs)
@@ -25,7 +25,7 @@ if typing.TYPE_CHECKING:
25
25
 
26
26
  def tensor(
27
27
  value: npt.ArrayLike | onnx.TensorProto | ir.DLPackCompatible | ir.ArrayCompatible,
28
- dtype: _enums.DataType | None = None,
28
+ dtype: ir.DataType | None = None,
29
29
  name: str | None = None,
30
30
  doc_string: str | None = None,
31
31
  ) -> _protocols.TensorProtocol:
@@ -159,7 +159,7 @@ def node(
159
159
  doc_string: str | None = None,
160
160
  metadata_props: dict[str, str] | None = None,
161
161
  ) -> ir.Node:
162
- """Create an :class:`~onnx_ir.Node`.
162
+ """Create a :class:`~onnx_ir.Node`.
163
163
 
164
164
  This is a convenience constructor for creating a Node that supports Python
165
165
  objects as attributes.
@@ -167,8 +167,8 @@ def node(
167
167
  Example::
168
168
 
169
169
  >>> import onnx_ir as ir
170
- >>> input_a = ir.Input("A", shape=ir.Shape([1, 2]), type=ir.TensorType(ir.DataType.INT32))
171
- >>> input_b = ir.Input("B", shape=ir.Shape([1, 2]), type=ir.TensorType(ir.DataType.INT32))
170
+ >>> input_a = ir.val("A", shape=[1, 2], type=ir.TensorType(ir.DataType.INT32))
171
+ >>> input_b = ir.val("B", shape=[1, 2], type=ir.TensorType(ir.DataType.INT32))
172
172
  >>> node = ir.node(
173
173
  ... "SomeOp",
174
174
  ... inputs=[input_a, input_b],
@@ -215,3 +215,77 @@ def node(
215
215
  doc_string=doc_string,
216
216
  metadata_props=metadata_props,
217
217
  )
218
+
219
+
220
+ def val(
221
+ name: str | None,
222
+ dtype: ir.DataType | None = None,
223
+ shape: ir.Shape | Sequence[int | str | None] | None = None,
224
+ *,
225
+ type: ir.TypeProtocol | None = None,
226
+ const_value: ir.TensorProtocol | None = None,
227
+ metadata_props: dict[str, str] | None = None,
228
+ ) -> ir.Value:
229
+ """Create a :class:`~onnx_ir.Value` with the given name and type.
230
+
231
+ This is a convenience constructor for creating a Value that allows you to specify
232
+ dtype and shape in a more relaxed manner. Whereas to create a Value directly, you
233
+ need to create a :class:`~onnx_ir.TypeProtocol` and :class:`~onnx_ir.Shape` object
234
+ first, this function allows you to specify dtype as a :class:`~onnx_ir.DataType`
235
+ and shape as a sequence of integers or symbolic dimensions.
236
+
237
+ Example::
238
+
239
+ >>> import onnx_ir as ir
240
+ >>> t = ir.val("x", ir.DataType.FLOAT, ["N", 42, 3])
241
+ >>> t.name
242
+ 'x'
243
+ >>> t.type
244
+ Tensor(FLOAT)
245
+ >>> t.shape
246
+ Shape([SymbolicDim(N), 42, 3])
247
+
248
+ .. versionadded:: 0.1.9
249
+
250
+ Args:
251
+ name: The name of the value.
252
+ dtype: The data type of the TensorType of the value. This is used only when type is None.
253
+ shape: The shape of the value.
254
+ type: The type of the value. Only one of dtype and type can be specified.
255
+ const_value: The constant tensor that initializes the value. Supply this argument
256
+ when you want to create an initializer. The type and shape can be obtained from the tensor.
257
+ metadata_props: The metadata properties that will be serialized to the ONNX proto.
258
+
259
+ Returns:
260
+ A Value object.
261
+ """
262
+ if const_value is not None:
263
+ const_tensor_type = _core.TensorType(const_value.dtype)
264
+ if type is not None and type != const_tensor_type:
265
+ raise ValueError(
266
+ f"The type does not match the const_value. type={type} but const_value has type {const_tensor_type}. "
267
+ "You do not have to specify the type when const_value is provided."
268
+ )
269
+ if dtype is not None and dtype != const_value.dtype:
270
+ raise ValueError(
271
+ f"The dtype does not match the const_value. dtype={dtype} but const_value has dtype {const_value.dtype}. "
272
+ "You do not have to specify the dtype when const_value is provided."
273
+ )
274
+ if shape is not None and _core.Shape(shape) != const_value.shape:
275
+ raise ValueError(
276
+ f"The shape does not match the const_value. shape={shape} but const_value has shape {const_value.shape}. "
277
+ "You do not have to specify the shape when const_value is provided."
278
+ )
279
+ return _core.Value(
280
+ name=name,
281
+ type=const_tensor_type,
282
+ shape=_core.Shape(const_value.shape), # type: ignore
283
+ const_value=const_value,
284
+ metadata_props=metadata_props,
285
+ )
286
+
287
+ if type is None and dtype is not None:
288
+ type = _core.TensorType(dtype)
289
+ if shape is not None and not isinstance(shape, _core.Shape):
290
+ shape = _core.Shape(shape)
291
+ return _core.Value(name=name, type=type, shape=shape, metadata_props=metadata_props)
onnx_ir/_core.py CHANGED
@@ -45,7 +45,7 @@ from typing import (
45
45
 
46
46
  import ml_dtypes
47
47
  import numpy as np
48
- from typing_extensions import TypeIs
48
+ from typing_extensions import TypeIs, deprecated
49
49
 
50
50
  import onnx_ir
51
51
  from onnx_ir import (
@@ -165,6 +165,11 @@ class TensorBase(abc.ABC, _protocols.TensorProtocol, _display.PrettyPrintable):
165
165
 
166
166
  @property
167
167
  def metadata_props(self) -> dict[str, str]:
168
+ """The metadata properties of the tensor.
169
+
170
+ The metadata properties are used to store additional information about the tensor.
171
+ Unlike ``meta``, this property is serialized to the ONNX proto.
172
+ """
168
173
  if self._metadata_props is None:
169
174
  self._metadata_props = {}
170
175
  return self._metadata_props
@@ -1214,6 +1219,12 @@ class Shape(_protocols.ShapeProtocol, _display.PrettyPrintable):
1214
1219
 
1215
1220
  Use :meth:`get_denotation` and :meth:`set_denotation` to access and modify the denotations.
1216
1221
 
1222
+ .. note::
1223
+ Two shapes can be compared for equality. Be careful when comparing shapes with
1224
+ unknown dimensions (``None``), as they may not be considered semantically equal
1225
+ even if all dimensions are the same. You can use :meth:`has_unknown_dim` to
1226
+ check if a shape has any unknown dimensions.
1227
+
1217
1228
  Example::
1218
1229
 
1219
1230
  >>> import onnx_ir as ir
@@ -1422,6 +1433,29 @@ class Shape(_protocols.ShapeProtocol, _display.PrettyPrintable):
1422
1433
  return not self.is_static()
1423
1434
  return not self.is_static(dim)
1424
1435
 
1436
+ def is_unknown_dim(self, dim: int) -> bool:
1437
+ """Return True if the dimension is unknown (None).
1438
+
1439
+ A dynamic dimension without a symbolic name is considered unknown.
1440
+
1441
+ .. versionadded:: 0.1.10
1442
+
1443
+ Args:
1444
+ dim: The index of the dimension.
1445
+ """
1446
+ dim_obj = self._dims[dim]
1447
+ return isinstance(dim_obj, SymbolicDim) and dim_obj.value is None
1448
+
1449
+ def has_unknown_dim(self) -> bool:
1450
+ """Return True if any dimension is unknown (None).
1451
+
1452
+ You can use :meth:`is_unknown_dim` to check if a specific dimension is unknown.
1453
+
1454
+ .. versionadded:: 0.1.10
1455
+ """
1456
+ # We can use "in" directly because SymbolicDim implements __eq__ with None
1457
+ return None in self._dims
1458
+
1425
1459
 
1426
1460
  def _quoted(string: str) -> str:
1427
1461
  """Return a quoted string.
@@ -2022,9 +2056,18 @@ class Value(_protocols.ValueProtocol, _display.PrettyPrintable):
2022
2056
  type: _protocols.TypeProtocol | None = None,
2023
2057
  doc_string: str | None = None,
2024
2058
  const_value: _protocols.TensorProtocol | None = None,
2059
+ metadata_props: dict[str, str] | None = None,
2025
2060
  ) -> None:
2026
2061
  """Initialize a value.
2027
2062
 
2063
+ When assigning a name to the value, the name of the backing `const_value` (Tensor)
2064
+ will also be updated. If the value is an initializer of a graph, the initializers
2065
+ dictionary of the graph will also be updated.
2066
+
2067
+ .. versionchanged:: 0.1.10
2068
+ Assigning a name to the value will also update the graph initializer entry
2069
+ if the value is an initializer of a graph.
2070
+
2028
2071
  Args:
2029
2072
  producer: The node that produces the value.
2030
2073
  It can be ``None`` when the value is initialized first than its producer.
@@ -2034,11 +2077,12 @@ class Value(_protocols.ValueProtocol, _display.PrettyPrintable):
2034
2077
  type: The type of the value.
2035
2078
  doc_string: The documentation string.
2036
2079
  const_value: The constant tensor if the value is constant.
2080
+ metadata_props: Metadata that will be serialized to the ONNX file.
2037
2081
  """
2038
2082
  self._producer: Node | None = producer
2039
2083
  self._index: int | None = index
2040
2084
  self._metadata: _metadata.MetadataStore | None = None
2041
- self._metadata_props: dict[str, str] | None = None
2085
+ self._metadata_props: dict[str, str] | None = metadata_props
2042
2086
 
2043
2087
  self._name: str | None = name
2044
2088
  self._shape: Shape | None = shape
@@ -2172,7 +2216,23 @@ class Value(_protocols.ValueProtocol, _display.PrettyPrintable):
2172
2216
  def name(self, value: str | None) -> None:
2173
2217
  if self._const_value is not None:
2174
2218
  self._const_value.name = value
2219
+ old_name = self._name
2175
2220
  self._name = value
2221
+ if self.is_initializer():
2222
+ if value is None:
2223
+ raise ValueError(
2224
+ "Initializer value cannot have name set to None. Please pop() the value from initializers first"
2225
+ )
2226
+ # Rename the initializer entry in the graph
2227
+ graph = self._graph
2228
+ assert graph is not None
2229
+ assert old_name is not None
2230
+ if value in graph.initializers and graph.initializers[value] is not self:
2231
+ raise ValueError(
2232
+ f"Cannot rename initializer to '{value}': an initializer with that name already exists."
2233
+ )
2234
+ graph.initializers.pop(old_name)
2235
+ graph.initializers[value] = self
2176
2236
 
2177
2237
  @property
2178
2238
  def type(self) -> _protocols.TypeProtocol | None:
@@ -2226,9 +2286,16 @@ class Value(_protocols.ValueProtocol, _display.PrettyPrintable):
2226
2286
  def const_value(
2227
2287
  self,
2228
2288
  ) -> _protocols.TensorProtocol | None:
2229
- """A concrete value.
2289
+ """The backing constant tensor for the value.
2290
+
2291
+ If the ``Value`` has a ``const_value`` and is part of a graph initializers
2292
+ dictionary, the value is an initialized value. Its ``const_value``
2293
+ will appear as an ``initializer`` in the GraphProto when serialized.
2294
+
2295
+ If the ``Value`` is not part of a graph initializers dictionary, the ``const_value``
2296
+ field will be ignored during serialization.
2230
2297
 
2231
- The value can be backed by different raw data types, such as numpy arrays.
2298
+ ``const_value`` can be backed by different raw data types, such as numpy arrays.
2232
2299
  The only guarantee is that it conforms TensorProtocol.
2233
2300
  """
2234
2301
  return self._const_value
@@ -2258,6 +2325,11 @@ class Value(_protocols.ValueProtocol, _display.PrettyPrintable):
2258
2325
 
2259
2326
  @property
2260
2327
  def metadata_props(self) -> dict[str, str]:
2328
+ """The metadata properties of the value.
2329
+
2330
+ The metadata properties are used to store additional information about the value.
2331
+ Unlike ``meta``, this property is serialized to the ONNX proto.
2332
+ """
2261
2333
  if self._metadata_props is None:
2262
2334
  self._metadata_props = {}
2263
2335
  return self._metadata_props
@@ -2275,6 +2347,7 @@ class Value(_protocols.ValueProtocol, _display.PrettyPrintable):
2275
2347
  return self._is_initializer
2276
2348
 
2277
2349
 
2350
+ @deprecated("Input is deprecated since 0.1.9. Use ir.val(...) instead.")
2278
2351
  def Input(
2279
2352
  name: str | None = None,
2280
2353
  shape: Shape | None = None,
@@ -2804,6 +2877,11 @@ class Graph(_protocols.GraphProtocol, Sequence[Node], _display.PrettyPrintable):
2804
2877
 
2805
2878
  @property
2806
2879
  def metadata_props(self) -> dict[str, str]:
2880
+ """The metadata properties of the graph.
2881
+
2882
+ The metadata properties are used to store additional information about the graph.
2883
+ Unlike ``meta``, this property is serialized to the ONNX proto.
2884
+ """
2807
2885
  if self._metadata_props is None:
2808
2886
  self._metadata_props = {}
2809
2887
  return self._metadata_props
@@ -3056,6 +3134,11 @@ class Model(_protocols.ModelProtocol, _display.PrettyPrintable):
3056
3134
 
3057
3135
  @property
3058
3136
  def metadata_props(self) -> dict[str, str]:
3137
+ """The metadata properties of the model.
3138
+
3139
+ The metadata properties are used to store additional information about the model.
3140
+ Unlike ``meta``, this property is serialized to the ONNX proto.
3141
+ """
3059
3142
  if self._metadata_props is None:
3060
3143
  self._metadata_props = {}
3061
3144
  return self._metadata_props
@@ -3249,6 +3332,11 @@ class Function(_protocols.FunctionProtocol, Sequence[Node], _display.PrettyPrint
3249
3332
 
3250
3333
  @property
3251
3334
  def metadata_props(self) -> dict[str, str]:
3335
+ """The metadata properties of the function.
3336
+
3337
+ The metadata properties are used to store additional information about the function.
3338
+ Unlike ``meta``, this property is serialized to the ONNX proto.
3339
+ """
3252
3340
  return self._graph.metadata_props
3253
3341
 
3254
3342
  def all_nodes(self) -> Iterator[Node]:
@@ -3397,6 +3485,31 @@ class Attr(
3397
3485
  *,
3398
3486
  doc_string: str | None = None,
3399
3487
  ) -> None:
3488
+ # Quick checks to ensure that INT and FLOAT attributes are stored as int and float,
3489
+ # not np.int32, np.float32, bool, etc.
3490
+ # This also allows errors to be raised at the time of construction instead of later
3491
+ # during serialization.
3492
+ # TODO(justinchuby): Use case matching when we drop support for Python 3.9
3493
+ if value is None:
3494
+ # Value can be None for reference attributes or when it is used as a
3495
+ # placeholder for schemas
3496
+ pass
3497
+ elif type == _enums.AttributeType.INT:
3498
+ value = int(value)
3499
+ elif type == _enums.AttributeType.FLOAT:
3500
+ value = float(value)
3501
+ elif type == _enums.AttributeType.INTS:
3502
+ value = tuple(int(v) for v in value)
3503
+ elif type == _enums.AttributeType.FLOATS:
3504
+ value = tuple(float(v) for v in value)
3505
+ elif type in {
3506
+ _enums.AttributeType.STRINGS,
3507
+ _enums.AttributeType.TENSORS,
3508
+ _enums.AttributeType.GRAPHS,
3509
+ _enums.AttributeType.TYPE_PROTOS,
3510
+ }:
3511
+ value = tuple(value)
3512
+
3400
3513
  self._name = name
3401
3514
  self._type = type
3402
3515
  self._value = value
@@ -3458,7 +3571,7 @@ class Attr(
3458
3571
  return f"@{self.ref_attr_name}"
3459
3572
  if self.type == _enums.AttributeType.GRAPH:
3460
3573
  return textwrap.indent("\n" + str(self.value), " " * 4)
3461
- return str(self.value)
3574
+ return repr(self.value)
3462
3575
 
3463
3576
  def __repr__(self) -> str:
3464
3577
  if self.is_ref():
@@ -3472,8 +3585,8 @@ class Attr(
3472
3585
  raise TypeError(
3473
3586
  f"Attribute '{self.name}' is not of type FLOAT. Actual type: {self.type}"
3474
3587
  )
3475
- # Do not use isinstance check because it may prevent np.float32 etc. from being used
3476
- return float(self.value)
3588
+ # value is guaranteed to be a float in the constructor
3589
+ return self.value
3477
3590
 
3478
3591
  def as_int(self) -> int:
3479
3592
  """Get the attribute value as an int."""
@@ -3481,8 +3594,8 @@ class Attr(
3481
3594
  raise TypeError(
3482
3595
  f"Attribute '{self.name}' is not of type INT. Actual type: {self.type}"
3483
3596
  )
3484
- # Do not use isinstance check because it may prevent np.int32 etc. from being used
3485
- return int(self.value)
3597
+ # value is guaranteed to be an int in the constructor
3598
+ return self.value
3486
3599
 
3487
3600
  def as_string(self) -> str:
3488
3601
  """Get the attribute value as a string."""
@@ -3490,9 +3603,10 @@ class Attr(
3490
3603
  raise TypeError(
3491
3604
  f"Attribute '{self.name}' is not of type STRING. Actual type: {self.type}"
3492
3605
  )
3493
- if not isinstance(self.value, str):
3606
+ value = self.value
3607
+ if not isinstance(value, str):
3494
3608
  raise TypeError(f"Value of attribute '{self!r}' is not a string.")
3495
- return self.value
3609
+ return value
3496
3610
 
3497
3611
  def as_tensor(self) -> _protocols.TensorProtocol:
3498
3612
  """Get the attribute value as a tensor."""
@@ -3500,9 +3614,10 @@ class Attr(
3500
3614
  raise TypeError(
3501
3615
  f"Attribute '{self.name}' is not of type TENSOR. Actual type: {self.type}"
3502
3616
  )
3503
- if not isinstance(self.value, _protocols.TensorProtocol):
3617
+ value = self.value
3618
+ if not isinstance(value, _protocols.TensorProtocol):
3504
3619
  raise TypeError(f"Value of attribute '{self!r}' is not a tensor.")
3505
- return self.value
3620
+ return value
3506
3621
 
3507
3622
  def as_graph(self) -> Graph:
3508
3623
  """Get the attribute value as a graph."""
@@ -3510,75 +3625,64 @@ class Attr(
3510
3625
  raise TypeError(
3511
3626
  f"Attribute '{self.name}' is not of type GRAPH. Actual type: {self.type}"
3512
3627
  )
3513
- if not isinstance(self.value, Graph):
3628
+ value = self.value
3629
+ if not isinstance(value, Graph):
3514
3630
  raise TypeError(f"Value of attribute '{self!r}' is not a graph.")
3515
- return self.value
3631
+ return value
3516
3632
 
3517
- def as_floats(self) -> Sequence[float]:
3633
+ def as_floats(self) -> tuple[float, ...]:
3518
3634
  """Get the attribute value as a sequence of floats."""
3519
3635
  if self.type != _enums.AttributeType.FLOATS:
3520
3636
  raise TypeError(
3521
3637
  f"Attribute '{self.name}' is not of type FLOATS. Actual type: {self.type}"
3522
3638
  )
3523
- if not isinstance(self.value, Sequence):
3524
- raise TypeError(f"Value of attribute '{self!r}' is not a Sequence.")
3525
- # Do not use isinstance check on elements because it may prevent np.int32 etc. from being used
3526
- # Create a copy of the list to prevent mutation
3527
- return [float(v) for v in self.value]
3639
+ # value is guaranteed to be a sequence of float in the constructor
3640
+ return self.value
3528
3641
 
3529
- def as_ints(self) -> Sequence[int]:
3642
+ def as_ints(self) -> tuple[int, ...]:
3530
3643
  """Get the attribute value as a sequence of ints."""
3531
3644
  if self.type != _enums.AttributeType.INTS:
3532
3645
  raise TypeError(
3533
3646
  f"Attribute '{self.name}' is not of type INTS. Actual type: {self.type}"
3534
3647
  )
3535
- if not isinstance(self.value, Sequence):
3536
- raise TypeError(f"Value of attribute '{self!r}' is not a Sequence.")
3537
- # Do not use isinstance check on elements because it may prevent np.int32 etc. from being used
3538
- # Create a copy of the list to prevent mutation
3539
- return list(self.value)
3648
+ # value is guaranteed to be a sequence of int in the constructor
3649
+ return self.value
3540
3650
 
3541
- def as_strings(self) -> Sequence[str]:
3651
+ def as_strings(self) -> tuple[str, ...]:
3542
3652
  """Get the attribute value as a sequence of strings."""
3543
3653
  if self.type != _enums.AttributeType.STRINGS:
3544
3654
  raise TypeError(
3545
3655
  f"Attribute '{self.name}' is not of type STRINGS. Actual type: {self.type}"
3546
3656
  )
3547
- if not isinstance(self.value, Sequence):
3548
- raise TypeError(f"Value of attribute '{self!r}' is not a Sequence.")
3549
3657
  if onnx_ir.DEBUG:
3550
3658
  if not all(isinstance(x, str) for x in self.value):
3551
3659
  raise TypeError(f"Value of attribute '{self!r}' is not a Sequence of strings.")
3552
- # Create a copy of the list to prevent mutation
3553
- return list(self.value)
3660
+ # value is guaranteed to be a sequence in the constructor
3661
+ return self.value
3554
3662
 
3555
- def as_tensors(self) -> Sequence[_protocols.TensorProtocol]:
3663
+ def as_tensors(self) -> tuple[_protocols.TensorProtocol, ...]:
3556
3664
  """Get the attribute value as a sequence of tensors."""
3557
3665
  if self.type != _enums.AttributeType.TENSORS:
3558
3666
  raise TypeError(
3559
3667
  f"Attribute '{self.name}' is not of type TENSORS. Actual type: {self.type}"
3560
3668
  )
3561
- if not isinstance(self.value, Sequence):
3562
- raise TypeError(f"Value of attribute '{self!r}' is not a Sequence.")
3563
3669
  if onnx_ir.DEBUG:
3564
3670
  if not all(isinstance(x, _protocols.TensorProtocol) for x in self.value):
3565
3671
  raise TypeError(f"Value of attribute '{self!r}' is not a Sequence of tensors.")
3566
- # Create a copy of the list to prevent mutation
3567
- return list(self.value)
3672
+ # value is guaranteed to be a sequence in the constructor
3673
+ return tuple(self.value)
3568
3674
 
3569
- def as_graphs(self) -> Sequence[Graph]:
3675
+ def as_graphs(self) -> tuple[Graph, ...]:
3570
3676
  """Get the attribute value as a sequence of graphs."""
3571
3677
  if self.type != _enums.AttributeType.GRAPHS:
3572
3678
  raise TypeError(
3573
3679
  f"Attribute '{self.name}' is not of type GRAPHS. Actual type: {self.type}"
3574
3680
  )
3575
- if not isinstance(self.value, Sequence):
3576
- raise TypeError(f"Value of attribute '{self!r}' is not a Sequence.")
3577
3681
  if onnx_ir.DEBUG:
3578
3682
  if not all(isinstance(x, Graph) for x in self.value):
3579
3683
  raise TypeError(f"Value of attribute '{self!r}' is not a Sequence of graphs.")
3580
- # Create a copy of the list to prevent mutation
3581
- return list(self.value)
3684
+ # value is guaranteed to be a sequence in the constructor
3685
+ return tuple(self.value)
3582
3686
 
3583
3687
 
3584
3688
  # NOTE: The following functions are just for convenience
@@ -3605,7 +3709,7 @@ def RefAttr(
3605
3709
  return Attr(name, type, None, ref_attr_name=ref_attr_name, doc_string=doc_string)
3606
3710
 
3607
3711
 
3608
- def AttrFloat32(name: str, value: float, doc_string: str | None = None) -> Attr:
3712
+ def AttrFloat32(name: str, value: float | np.floating, doc_string: str | None = None) -> Attr:
3609
3713
  """Create a float attribute."""
3610
3714
  # NOTE: The function name is capitalized to maintain API backward compatibility.
3611
3715
  return Attr(
@@ -3616,7 +3720,7 @@ def AttrFloat32(name: str, value: float, doc_string: str | None = None) -> Attr:
3616
3720
  )
3617
3721
 
3618
3722
 
3619
- def AttrInt64(name: str, value: int, doc_string: str | None = None) -> Attr:
3723
+ def AttrInt64(name: str, value: int | np.integer, doc_string: str | None = None) -> Attr:
3620
3724
  """Create an int attribute."""
3621
3725
  # NOTE: The function name is capitalized to maintain API backward compatibility.
3622
3726
  return Attr(
onnx_ir/_enums.py CHANGED
@@ -357,7 +357,10 @@ class DataType(enum.IntEnum):
357
357
  }
358
358
 
359
359
  def is_string(self) -> bool:
360
- """Returns True if the data type is a string type."""
360
+ """Returns True if the data type is a string type.
361
+
362
+ .. versionadded:: 0.1.8
363
+ """
361
364
  return self == DataType.STRING
362
365
 
363
366
  def __repr__(self) -> str:
@@ -419,15 +422,9 @@ _NP_TYPE_TO_DATA_TYPE = {
419
422
  np.dtype(ml_dtypes.float8_e8m0fnu): DataType.FLOAT8E8M0,
420
423
  np.dtype(ml_dtypes.int4): DataType.INT4,
421
424
  np.dtype(ml_dtypes.uint4): DataType.UINT4,
425
+ np.dtype(ml_dtypes.float4_e2m1fn): DataType.FLOAT4E2M1,
422
426
  }
423
427
 
424
- # TODO(after min req for ml_dtypes>=0.5): Move this inside _NP_TYPE_TO_DATA_TYPE
425
- _NP_TYPE_TO_DATA_TYPE.update(
426
- {np.dtype(ml_dtypes.float4_e2m1fn): DataType.FLOAT4E2M1}
427
- if hasattr(ml_dtypes, "float4_e2m1fn")
428
- else {}
429
- )
430
-
431
428
  # ONNX DataType to Numpy dtype.
432
429
  _DATA_TYPE_TO_NP_TYPE = {v: k for k, v in _NP_TYPE_TO_DATA_TYPE.items()}
433
430
 
@@ -69,7 +69,12 @@ class LiftConstantsToInitializersPass(ir.passes.InPlacePass):
69
69
  shape=tensor.shape, # type: ignore[arg-type]
70
70
  type=ir.TensorType(tensor.dtype),
71
71
  const_value=tensor,
72
+ # Preserve metadata from Constant value into the onnx model
73
+ metadata_props=node.outputs[0].metadata_props.copy(),
72
74
  )
75
+ # Preserve value meta from the Constant output for intermediate analysis
76
+ initializer.meta.update(node.outputs[0].meta)
77
+
73
78
  assert node.graph is not None
74
79
  node.graph.register_initializer(initializer)
75
80
  # Replace the constant node with the initializer
@@ -193,14 +193,8 @@ class NameFixPass(ir.passes.InPlacePass):
193
193
  if not value.name:
194
194
  modified = self._assign_value_name(value, used_value_names, value_counter)
195
195
  else:
196
- old_name = value.name
197
196
  modified = self._fix_duplicate_value_name(value, used_value_names, value_counter)
198
- if modified:
199
- assert value.graph is not None
200
- if value.is_initializer():
201
- value.graph.initializers.pop(old_name)
202
- # Add the initializer back with the new name
203
- value.graph.initializers.add(value)
197
+ # initializers dictionary is updated automatically when the Value is renamed
204
198
 
205
199
  # Record the final name for this value
206
200
  assert value.name is not None
onnx_ir/serde.py CHANGED
@@ -709,9 +709,8 @@ def _deserialize_graph(
709
709
  annotation.tensor_name: annotation for annotation in proto.quantization_annotation
710
710
  }
711
711
 
712
- # Create values for initializers and inputs
713
- initializer_tensors = [deserialize_tensor(tensor) for tensor in proto.initializer]
714
- inputs = [_core.Input(info.name) for info in proto.input]
712
+ # Create values for inputs
713
+ inputs = [_core.Value(name=info.name) for info in proto.input]
715
714
  for info, value in zip(proto.input, inputs):
716
715
  deserialize_value_info_proto(info, value)
717
716
 
@@ -725,6 +724,11 @@ def _deserialize_graph(
725
724
  # Enter the graph scope by pushing the values for this scope to the stack
726
725
  scoped_values.append(values)
727
726
 
727
+ # Build the value info dictionary to allow for quick lookup for this graph scope
728
+ value_info = {info.name: info for info in proto.value_info}
729
+
730
+ # Create values for initializers
731
+ initializer_tensors = [deserialize_tensor(tensor) for tensor in proto.initializer]
728
732
  initializer_values = []
729
733
  for i, tensor in enumerate(initializer_tensors):
730
734
  initializer_name = tensor.name
@@ -750,6 +754,8 @@ def _deserialize_graph(
750
754
  shape=tensor.shape, # type: ignore[arg-type]
751
755
  const_value=tensor,
752
756
  )
757
+ if initializer_name in value_info:
758
+ deserialize_value_info_proto(value_info[initializer_name], initializer_value)
753
759
  if initializer_value.name in quantization_annotations:
754
760
  _deserialize_quantization_annotation(
755
761
  quantization_annotations[initializer_value.name], initializer_value
@@ -757,9 +763,6 @@ def _deserialize_graph(
757
763
  values[initializer_name] = initializer_value
758
764
  initializer_values.append(initializer_value)
759
765
 
760
- # Build the value info dictionary to allow for quick lookup for this graph scope
761
- value_info = {info.name: info for info in proto.value_info}
762
-
763
766
  # Declare values for all node outputs from this graph scope. This is necessary
764
767
  # to handle the case where a node in a subgraph uses a value that is declared out
765
768
  # of order in the outer graph. Declaring the values first allows us to find the
@@ -869,7 +872,7 @@ def deserialize_function(proto: onnx.FunctionProto) -> _core.Function:
869
872
  Returns:
870
873
  An IR Function object representing the ONNX function.
871
874
  """
872
- inputs = [_core.Input(name) for name in proto.input]
875
+ inputs = [_core.Value(name=name) for name in proto.input]
873
876
  values: dict[str, _core.Value] = {v.name: v for v in inputs} # type: ignore[misc]
874
877
  value_info = {info.name: info for info in getattr(proto, "value_info", [])}
875
878
 
@@ -1143,7 +1146,19 @@ def _deserialize_attribute(
1143
1146
  if type_ == _enums.AttributeType.FLOAT:
1144
1147
  return _core.AttrFloat32(name, proto.f, doc_string=doc_string)
1145
1148
  if type_ == _enums.AttributeType.STRING:
1146
- return _core.AttrString(name, proto.s.decode("utf-8"), doc_string=doc_string)
1149
+ try:
1150
+ return _core.AttrString(name, proto.s.decode("utf-8"), doc_string=doc_string)
1151
+ except UnicodeDecodeError:
1152
+ # Even though onnx.ai/onnx/repo-docs/IR.html#attributes requires the attribute
1153
+ # for strings to be utf-8 encoded bytes, custom ops may still store arbitrary data there
1154
+ logger.warning(
1155
+ "Attribute %r contains invalid UTF-8 bytes. ONNX spec requires string attributes "
1156
+ "to be UTF-8 encoded so the model is invalid. We will skip decoding the attribute and "
1157
+ "use the bytes as attribute value",
1158
+ name,
1159
+ )
1160
+ return _core.Attr(name, type_, proto.s, doc_string=doc_string)
1161
+
1147
1162
  if type_ == _enums.AttributeType.INTS:
1148
1163
  return _core.AttrInt64s(name, proto.ints, doc_string=doc_string)
1149
1164
  if type_ == _enums.AttributeType.FLOATS:
@@ -1378,7 +1393,12 @@ def _should_create_value_info_for_value(value: _protocols.ValueProtocol) -> bool
1378
1393
  True if value info should be created for the value.
1379
1394
  """
1380
1395
  # No need to serialize value info if it is not set
1381
- if value.shape is None and value.type is None:
1396
+ if (
1397
+ value.shape is None
1398
+ and value.type is None
1399
+ and not value.metadata_props
1400
+ and not value.doc_string
1401
+ ):
1382
1402
  return False
1383
1403
  if not value.name:
1384
1404
  logger.debug("Did not serialize '%s' because its name is empty", value)
@@ -1784,16 +1804,26 @@ def _fill_in_value_for_attribute(
1784
1804
  ) -> None:
1785
1805
  if type_ == _enums.AttributeType.INT:
1786
1806
  # value: int
1787
- # Cast bool to int, for example
1788
- attribute_proto.i = int(value)
1807
+ attribute_proto.i = value
1789
1808
  attribute_proto.type = onnx.AttributeProto.INT
1790
1809
  elif type_ == _enums.AttributeType.FLOAT:
1791
1810
  # value: float
1792
- attribute_proto.f = float(value)
1811
+ attribute_proto.f = value
1793
1812
  attribute_proto.type = onnx.AttributeProto.FLOAT
1794
1813
  elif type_ == _enums.AttributeType.STRING:
1795
1814
  # value: str
1796
- attribute_proto.s = value.encode("utf-8")
1815
+ if type(value) is bytes:
1816
+ # Even though onnx.ai/onnx/repo-docs/IR.html#attributes requires the attribute
1817
+ # for strings to be utf-8 encoded bytes, custom ops may still store arbitrary data there
1818
+ logger.warning(
1819
+ "Value in attribute %r should be a string but is instead bytes. ONNX "
1820
+ "spec requires string attributes to be UTF-8 encoded so the model is invalid. "
1821
+ "We will skip encoding the attribute and use the bytes as attribute value",
1822
+ attribute_proto.name,
1823
+ )
1824
+ attribute_proto.s = value
1825
+ else:
1826
+ attribute_proto.s = value.encode("utf-8")
1797
1827
  attribute_proto.type = onnx.AttributeProto.STRING
1798
1828
  elif type_ == _enums.AttributeType.INTS:
1799
1829
  # value: Sequence[int]
@@ -1945,11 +1975,26 @@ def serialize_type(type_protocol: _protocols.TypeProtocol) -> onnx.TypeProto:
1945
1975
  @_capture_errors(lambda type_proto, from_: repr(from_))
1946
1976
  def serialize_shape_into(type_proto: onnx.TypeProto, from_: _protocols.ShapeProtocol) -> None:
1947
1977
  value_field = type_proto.WhichOneof("value")
1978
+ if value_field is None:
1979
+ # We cannot write the shape because we do not know where to write it
1980
+ logger.warning(
1981
+ # TODO(justinchuby): Show more context about the value when move everything to an object
1982
+ "The value type for shape %s is not known. Please set type for the value. Skipping serialization",
1983
+ from_,
1984
+ )
1985
+ return
1948
1986
  tensor_type = getattr(type_proto, value_field)
1949
1987
  while not isinstance(tensor_type.elem_type, int):
1950
1988
  # Find the leaf type that has the shape field
1951
1989
  type_proto = tensor_type.elem_type
1952
1990
  value_field = type_proto.WhichOneof("value")
1991
+ if value_field is None:
1992
+ logger.warning(
1993
+ # TODO(justinchuby): Show more context about the value when move everything to an object
1994
+ "The value type for shape %s is not known. Please set type for the value. Skipping serialization",
1995
+ from_,
1996
+ )
1997
+ return
1953
1998
  tensor_type = getattr(type_proto, value_field)
1954
1999
  # When from is empty, we still need to set the shape field to an empty list by touching it
1955
2000
  tensor_type.shape.ClearField("dim")
@@ -1970,5 +2015,8 @@ def serialize_dimension_into(
1970
2015
  dim_proto.dim_value = dim
1971
2016
  elif isinstance(dim, (_core.SymbolicDim, _protocols.SymbolicDimProtocol)):
1972
2017
  if dim.value is not None:
1973
- # TODO(justinchuby): None is probably not a valid value for dim_param
1974
2018
  dim_proto.dim_param = str(dim.value)
2019
+ # NOTE: None is a valid value for symbolic dimension:
2020
+ # A dimension MAY have neither dim_value nor dim_param set. Such a dimension
2021
+ # represents an unknown dimension unrelated to other unknown dimensions.
2022
+ # Here we will just leave the dim_proto empty.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: onnx-ir
3
- Version: 0.1.8
3
+ Version: 0.1.10
4
4
  Summary: Efficient in-memory representation for ONNX
5
5
  Author-email: ONNX Contributors <onnx-technical-discuss@lists.lfaidata.foundation>
6
6
  License-Expression: Apache-2.0
@@ -19,7 +19,7 @@ License-File: LICENSE
19
19
  Requires-Dist: numpy
20
20
  Requires-Dist: onnx>=1.16
21
21
  Requires-Dist: typing_extensions>=4.10
22
- Requires-Dist: ml_dtypes
22
+ Requires-Dist: ml_dtypes>=0.5.0
23
23
  Dynamic: license-file
24
24
 
25
25
  # <img src="docs/_static/logo-light.png" alt="ONNX IR" width="250"/>
@@ -1,7 +1,7 @@
1
- onnx_ir/__init__.py,sha256=kcifjxB2nP9t4WMrxcJriVQ_WmgpOf0DOfUgsngd_PA,3424
2
- onnx_ir/_core.py,sha256=EEQyNzWkz_ukCV_9Dc6AUIVAmPErhVjntr4xwPNobU4,139190
1
+ onnx_ir/__init__.py,sha256=N-6BRNeRjjU17-iaezMOq1ErVq8irJltkubTpAbZ2BY,3441
2
+ onnx_ir/_core.py,sha256=9AnsXuoiFzypp9U_al7yU46OU0iqrGq0rJzLw4FHmcI,143517
3
3
  onnx_ir/_display.py,sha256=230bMN_hVy47Ug3HkA4o5Tf5Hr21AnBEoq5w0fxjyTs,1300
4
- onnx_ir/_enums.py,sha256=NvfBARtUGc6_qrXRvWdenuhGR7DqDrqigbWaECugTv8,14043
4
+ onnx_ir/_enums.py,sha256=E7WQ7yQzulBeimamc9q_k4fEUoyH_2PWtaOMpwck_W0,13915
5
5
  onnx_ir/_graph_comparison.py,sha256=8_D1gu547eCDotEUqxfIJhUGU_Ufhfji7sfsSraOj3g,727
6
6
  onnx_ir/_graph_containers.py,sha256=PRKrshRZ5rzWCgRs1TefzJq9n8wyo7OqeKy3XxMhyys,14265
7
7
  onnx_ir/_io.py,sha256=GWwA4XOZ-ZX1cgibgaYD0K0O5d9LX21ZwcBN02Wrh04,5205
@@ -16,13 +16,13 @@ onnx_ir/_version_utils.py,sha256=bZThuE7meVHFOY1DLsmss9WshVIp9iig7udGfDbVaK4,133
16
16
  onnx_ir/convenience.py,sha256=0B1epuXZCSmY4FbW2vaYfR-t5ubxBZ1UruiytHs-zFw,917
17
17
  onnx_ir/external_data.py,sha256=rXHtRU-9tjAt10Iervhr5lsI6Dtv-EhR7J4brxppImA,18079
18
18
  onnx_ir/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
19
- onnx_ir/serde.py,sha256=H9V9dff3UF2e-vnsQt9FlUJMnlKWKOms6CjivMtD2c4,78226
19
+ onnx_ir/serde.py,sha256=S0zCZnfePs1UV927HDEr3VnXuue_B5PD1dVPqwuwrak,80636
20
20
  onnx_ir/tape.py,sha256=4FyfAHmVhQoMsfHMYnBwP2azi6UF6b6pj--ercObqZs,350
21
21
  onnx_ir/tensor_adapters.py,sha256=YffUeZDZi8thxm-4nF2cL6cNSJSVmLm4A3IbEzwY8QQ,7233
22
22
  onnx_ir/testing.py,sha256=WTrjf2joWizDWaYMJlV1KjZMQw7YmZ8NvuBTVn1uY6s,8803
23
23
  onnx_ir/traversal.py,sha256=Wy4XphwuapAvm94-5iaz6G8LjIoMFpY7qfPfXzYViEE,4488
24
- onnx_ir/_convenience/__init__.py,sha256=bXUxjZ_91idQJ33zWtByQ0J4VsWCUdvAy9iIflpLtW8,19754
25
- onnx_ir/_convenience/_constructors.py,sha256=5GhlYy_xCE2ng7l_4cNx06WQsNDyvS-0U1HgOpPKJEk,8347
24
+ onnx_ir/_convenience/__init__.py,sha256=SO7kc8RXVKEUODGh0q2Y7WgmbUsOjYSixmKFx_A0DAQ,19752
25
+ onnx_ir/_convenience/_constructors.py,sha256=HqCGtNPMzFFEerC7I5VEyMdBuIdOJDucn9UEdwuymcg,11519
26
26
  onnx_ir/_thirdparty/asciichartpy.py,sha256=afQ0fsqko2uYRPAR4TZBrQxvCb4eN8lxZ2yDFbVQq_s,10533
27
27
  onnx_ir/passes/__init__.py,sha256=M_Tcl_-qGSNPluFIvOoeDyh0qAwNayaYyXDS5UJUJPQ,764
28
28
  onnx_ir/passes/_pass_infra.py,sha256=xIOw_zZIuOqD4Z_wZ4OvsqXfh2IZMoMlDp1xQ_MPQlc,9567
@@ -30,17 +30,17 @@ onnx_ir/passes/common/__init__.py,sha256=NYBrXvkq_CbWRwcZptSsF4u_-1zfN_BClLhVQY0
30
30
  onnx_ir/passes/common/_c_api_utils.py,sha256=g6riA6xNGVWaO5YjVHZ0krrfslWHmRlryRkwB8X56cg,2907
31
31
  onnx_ir/passes/common/clear_metadata_and_docstring.py,sha256=YwouLfsNFSaTuGd7uMOGjdvVwG9yHQTkSphUgDlM0ME,2365
32
32
  onnx_ir/passes/common/common_subexpression_elimination.py,sha256=wZ1zEPdCshYB_ifP9fCAVfzQkesE6uhCfzCuL2qO5fA,7948
33
- onnx_ir/passes/common/constant_manipulation.py,sha256=dFzzqbpRecJJrYf6edvR_sdr4F0gV-1wEtDXsQ7fStM,9101
33
+ onnx_ir/passes/common/constant_manipulation.py,sha256=Ja_2uO59ni8YX600iF3wvCmOk4EvM5crl7csYU1s7rQ,9391
34
34
  onnx_ir/passes/common/identity_elimination.py,sha256=wN8g8uPGn6IIQ6Jf1lo6nGTXvpWyiSQtT_CfmtvZpwA,3664
35
35
  onnx_ir/passes/common/initializer_deduplication.py,sha256=gKrXTMFAtCkMmiIm8zWzwPnwSbRdZxunJeAt_jFU-vY,7253
36
36
  onnx_ir/passes/common/inliner.py,sha256=wBoO6yXt6F1AObQjYZHMQ0wn3YH681N4HQQVyaMAYd4,13702
37
- onnx_ir/passes/common/naming.py,sha256=NNKc9IPrmzm3J0zGQILfooayVzfdXDYHY9DHex1hFgs,10927
37
+ onnx_ir/passes/common/naming.py,sha256=l_LrUiI3gAoSEVs8YeQ5kRNWp7aMOlBK-SfFUsKobZI,10687
38
38
  onnx_ir/passes/common/onnx_checker.py,sha256=_sPmJ2ff9pDB1g9q7082BL6fyubomRaj6svE0cCyDew,1691
39
39
  onnx_ir/passes/common/shape_inference.py,sha256=LVdvxjeKtcIEbPcb6mKisxoPJOOawzsm3tzk5j9xqeM,3992
40
40
  onnx_ir/passes/common/topological_sort.py,sha256=Vcu1YhBdfRX4LROr0NScjB1Pwz2DjBFD0Z_GxqaxPF8,999
41
41
  onnx_ir/passes/common/unused_removal.py,sha256=cBNqaqGnUVyCWxsD7hBzYk4qSglVPo3SmHAvkUo5-Oc,7613
42
- onnx_ir-0.1.8.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
43
- onnx_ir-0.1.8.dist-info/METADATA,sha256=trHcb8JDn1IJRC3B9iLv8o6QjAC7G6etJJw6gfGQE2s,3597
44
- onnx_ir-0.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
- onnx_ir-0.1.8.dist-info/top_level.txt,sha256=W5tROO93YjO0XRxIdjMy4wocp-5st5GiI2ukvW7UhDo,8
46
- onnx_ir-0.1.8.dist-info/RECORD,,
42
+ onnx_ir-0.1.10.dist-info/licenses/LICENSE,sha256=z8d0m5b2O9McPEK1xHG_dWgUBT6EfBDz6wA0F7xSPTA,11358
43
+ onnx_ir-0.1.10.dist-info/METADATA,sha256=3ou4NcDwiEwn172tRdD57Tb7y7rCGUyfhFDqan7qM3s,3605
44
+ onnx_ir-0.1.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
+ onnx_ir-0.1.10.dist-info/top_level.txt,sha256=W5tROO93YjO0XRxIdjMy4wocp-5st5GiI2ukvW7UhDo,8
46
+ onnx_ir-0.1.10.dist-info/RECORD,,