Skip to content

Commit 11dd04c

Browse files
committed
Revert "Fix linter and CI issues"
This reverts commit 446f1da.
1 parent ad81015 commit 11dd04c

File tree

4 files changed

+107
-97
lines changed

4 files changed

+107
-97
lines changed

src/bindings/python/src/pyopenvino/graph/model.cpp

Lines changed: 58 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -540,40 +540,26 @@ void regclass_graph_Model(py::module m) {
540540
}
541541

542542
bool is_multi_input_format = false;
543-
bool all_containers = true;
543+
bool has_list = false;
544544
bool has_int = false;
545545

546546
for (size_t i = 0; i < partial_shape.size(); ++i) {
547547
py::handle elem = partial_shape[i];
548-
if (py::isinstance<py::int_>(elem)) {
548+
if (py::isinstance<py::list>(elem)) {
549+
has_list = true;
550+
} else if (py::isinstance<py::int_>(elem)) {
549551
has_int = true;
550-
all_containers = false;
551-
} else if (py::isinstance<py::list>(elem) || py::isinstance<py::tuple>(elem)) {
552-
// list/tuple are treated as shape containers at the top level
553-
} else {
552+
} else if (!py::isinstance<py::tuple>(elem)) {
554553
throw std::runtime_error("Invalid shape format");
555554
}
556555
}
557556

558-
// If the number of provided shapes matches the number of model inputs
559-
// but top-level elements are not all containers, the user likely
560-
// intended multi-input format but provided an invalid element type.
561-
if ((partial_shape.size() == inputs.size()) && !all_containers) {
562-
throw std::runtime_error("Each shape must be a list or tuple.");
563-
}
564-
565-
// If all top-level elements are containers but the number of shapes
566-
// does not match number of model inputs, report a clear error instead
567-
// of trying to parse the whole thing as a flat shape.
568-
if (all_containers && (partial_shape.size() != inputs.size())) {
569-
throw std::runtime_error("Number of shapes does not match number of model inputs.");
557+
if (has_list) {
558+
is_multi_input_format = true;
559+
} else {
560+
is_multi_input_format = !has_int;
570561
}
571562

572-
// Multi-input format is used only when the number of provided shapes
573-
// matches the number of model inputs and all top-level elements are
574-
// shape containers (lists/tuples). Otherwise treat as a flat shape.
575-
is_multi_input_format = (partial_shape.size() == inputs.size()) && all_containers;
576-
577563
if (!is_multi_input_format) {
578564
// FLAT FORMAT
579565
const auto new_shape = Common::partial_shape_from_list(partial_shape);
@@ -586,18 +572,36 @@ void regclass_graph_Model(py::module m) {
586572
// MULTI-INPUT FORMAT
587573
std::map<std::string, ov::PartialShape> new_shapes_map;
588574

589-
// Reuse existing helper to parse inner shape containers so that all
590-
// dimension notation forms supported elsewhere (ints, [min,max],
591-
// (min,max), -1, strings, openvino.Dimension, etc.) are accepted
592-
// here too. This avoids divergence between flat and multi-input
593-
// parsing behavior.
594-
auto parse_shape = [](py::handle shape_handle) -> ov::PartialShape {
595-
if (!py::isinstance<py::list>(shape_handle) && !py::isinstance<py::tuple>(shape_handle)) {
596-
throw std::runtime_error("Each shape must be a list or tuple.");
575+
auto parse_dimension = [](py::handle dim_obj) -> ov::Dimension {
576+
if (py::isinstance<py::list>(dim_obj)) {
577+
throw std::runtime_error("Unexpected nested list in dimension specification.");
578+
}
579+
if (py::isinstance<py::tuple>(dim_obj)) {
580+
py::tuple t = dim_obj.cast<py::tuple>();
581+
if (t.size() != 2) {
582+
throw std::runtime_error(
583+
"Two elements are expected in tuple(lower, upper) for dynamic dimension, but " +
584+
std::to_string(t.size()) + " elements were given.");
585+
}
586+
if (!py::isinstance<py::int_>(t[0]) || !py::isinstance<py::int_>(t[1])) {
587+
throw std::runtime_error("Tuple elements must be integers.");
588+
}
589+
int lower = t[0].cast<int>();
590+
int upper = t[1].cast<int>();
591+
return ov::Dimension(lower, upper);
592+
}
593+
if (py::isinstance<py::int_>(dim_obj)) {
594+
return ov::Dimension(dim_obj.cast<int>());
595+
}
596+
throw std::runtime_error("Invalid dimension type. Must be int or (lower, upper) tuple.");
597+
};
598+
599+
auto parse_shape = [&parse_dimension](py::sequence shape_seq) -> ov::PartialShape {
600+
std::vector<ov::Dimension> dims;
601+
for (size_t i = 0; i < shape_seq.size(); ++i) {
602+
dims.push_back(parse_dimension(shape_seq[i]));
597603
}
598-
// Common::partial_shape_from_list expects a py::list
599-
py::list shape_list = shape_handle.cast<py::list>();
600-
return Common::partial_shape_from_list(shape_list);
604+
return ov::PartialShape(dims);
601605
};
602606

603607
if (partial_shape.size() != inputs.size()) {
@@ -606,7 +610,11 @@ void regclass_graph_Model(py::module m) {
606610

607611
for (size_t i = 0; i < partial_shape.size(); ++i) {
608612
py::handle shape_handle = partial_shape[i];
609-
new_shapes_map[inputs[i].get_any_name()] = parse_shape(shape_handle);
613+
if (!py::isinstance<py::list>(shape_handle) && !py::isinstance<py::tuple>(shape_handle)) {
614+
throw std::runtime_error("Each shape must be a list or tuple.");
615+
}
616+
py::sequence shape_seq = shape_handle.cast<py::sequence>();
617+
new_shapes_map[inputs[i].get_any_name()] = parse_shape(shape_seq);
610618
}
611619

612620
const auto new_variables_shapes = get_variables_shapes(variables_shapes);
@@ -629,9 +637,21 @@ void regclass_graph_Model(py::module m) {
629637
When list or tuple are used to describe dimensions, each dimension can be written in form:
630638
631639
(1) non-negative `int` which means static value for the dimension
632-
(2) `(min, max)`, dynamic dimension where `min` specifies lower bound and `max` specifies upper bound;
633-
the range includes both `min` and `max`; using `-1` for `min` or `max` means no known bound
634-
(3) `-1` is a dynamic dimension without known bounds
640+
(2) `[min, max]`, dynamic dimension where `min` specifies lower bound and `max` specifies upper bound;
641+
the range includes both `min` and `max`; using `-1` for `min` or `max` means no known bound (3) `(min,
642+
max)`, the same as above (4) `-1` is a dynamic dimension without known bounds (4)
643+
`openvino.Dimension` (5) `str` using next syntax:
644+
'?' - to define fully dynamic dimension
645+
'1' - to define dimension which length is 1
646+
'1..10' - to define bounded dimension
647+
'..10' or '1..' to define dimension with only lower or only upper limit
648+
649+
Multi-input format:
650+
- Pass a list of shapes: [[shape1], [shape2], ...]
651+
- Number of shapes must match number of inputs
652+
653+
Single-input format:
654+
- Pass a flat list: [dim1, dim2, ...]
635655
636656
Examples:
637657
>>> model.reshape([[2, 2], [1, 3, 224, 244], [10]]) # Multi-input

src/bindings/python/tests/test_runtime/test_model.py

Lines changed: 46 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# -*- coding: utf-8 -*-
12
# Copyright (C) 2018-2026 Intel Corporation
23
# SPDX-License-Identifier: Apache-2.0
34

@@ -10,18 +11,16 @@
1011

1112
import numpy as np
1213
import pytest
13-
from tests.utils.helpers import (
14-
create_filenames_for_ir,
15-
generate_add_model,
16-
generate_model_with_memory,
17-
generate_multi_input_model,
18-
generate_single_input_model,
19-
generate_two_input_model,
20-
)
14+
from tests.utils.helpers import (create_filenames_for_ir, generate_add_model,
15+
generate_model_with_memory,
16+
generate_multi_input_model,
17+
generate_single_input_model,
18+
generate_two_input_model)
2119

2220
import openvino.opset13 as ops
23-
from openvino import Core, Dimension, Layout, Model, Output, OVAny, \
24-
PartialShape, Shape, Tensor, Type, get_batch, save_model, serialize, set_batch
21+
from openvino import (Core, Dimension, Layout, Model, Output, OVAny,
22+
PartialShape, Shape, Tensor, Type, get_batch, save_model,
23+
serialize, set_batch)
2524
from openvino.op.util import Variable, VariableInfo
2625

2726

@@ -261,16 +260,16 @@ def test_model_sink_ctors():
261260

262261
# Model(list[openvino._pyopenvino.op.Result], list[ov::Output<ov::Node>],
263262
# list[openvino._pyopenvino.op.Parameter], list[openvino._pyopenvino.op.util.Variable], str = '')
264-
model = Model(results=[res], sinks=[assign.output(0)],
265-
parameters=[input_data], variables=[variable_1], name="TestModel")
263+
model = Model(results=[res], sinks=[assign.output(0)], parameters=[
264+
input_data], variables=[variable_1], name="TestModel")
266265
model.validate_nodes_and_infer_types()
267266
assert model.sinks[0].get_output_shape(0) == Shape([2, 2])
268267
assert sinks == [sink.get_type_name() for sink in model.get_sinks()]
269268

270269
# Model(list[ov::Output<ov::Node>, list[ov::Output<ov::Node>],
271270
# list[openvino._pyopenvino.op.Parameter], list[openvino._pyopenvino.op.util.Variable], str = '')
272-
model = Model(results=[res.output(0)], sinks=[assign.output(0)],
273-
parameters=[input_data], variables=[variable_1], name="TestModel")
271+
model = Model(results=[res.output(0)], sinks=[assign.output(0)], parameters=[
272+
input_data], variables=[variable_1], name="TestModel")
274273
model.validate_nodes_and_infer_types()
275274
assert model.sinks[0].get_output_shape(0) == Shape([2, 2])
276275
assert sinks == [sink.get_type_name() for sink in model.get_sinks()]
@@ -509,15 +508,13 @@ def check_shape(new_shape):
509508
shape10 = [1, 1, 1, 1]
510509
with pytest.raises(TypeError) as e:
511510
model.reshape({model.input().node: shape10})
512-
expected_msg = "Incorrect key type <class 'openvino._pyopenvino.op.Parameter'> to reshape a model, " \
513-
"expected keys as openvino.Output, int or str."
514-
assert expected_msg in str(e.value)
511+
assert "Incorrect key type <class 'openvino._pyopenvino.op.Parameter'> to reshape a model, " "expected keys as openvino.Output, int or str." in str(
512+
e.value)
515513

516514
with pytest.raises(TypeError) as e:
517515
model.reshape({0: range(1, 9)})
518-
expected_msg = "Incorrect value type <class 'range'> to reshape a model, " \
519-
"expected values as openvino.PartialShape, str, list or tuple."
520-
assert expected_msg in str(e.value)
516+
assert "Incorrect value type <class 'range'> to reshape a model, " "expected values as openvino.PartialShape, str, list or tuple." in str(
517+
e.value)
521518

522519

523520
def test_reshape_with_python_types_for_variable():
@@ -590,31 +587,31 @@ def check_shape(new_shape):
590587

591588
with pytest.raises(TypeError) as e:
592589
model.reshape({0: shape10}, {var_id: range(1, 9)})
593-
assert "Incorrect value type <class 'range'> to reshape a model, " \
594-
"expected values as openvino.PartialShape, str, list or tuple." in str(e.value)
590+
assert "Incorrect value type <class 'range'> to reshape a model, " "expected values as openvino.PartialShape, str, list or tuple." in str(
591+
e.value)
595592

596593

597594
@pytest.fixture
598-
def multi_input_model():
595+
def model():
599596
return generate_multi_input_model()
600597

601598

602-
def test_reshape_list_of_shapes(multi_input_model):
599+
def test_reshape_list_of_shapes(model):
603600
"""Multi-input: list-of-lists reshapes all inputs in order."""
604601
input_shapes = [[2, 2], [1, 3, 224, 244], [10]]
605602

606-
multi_input_model.reshape(input_shapes)
603+
model.reshape(input_shapes)
607604

608-
assert multi_input_model.input("A").shape == (2, 2)
609-
assert multi_input_model.input("B").shape == (1, 3, 224, 244)
610-
assert multi_input_model.input("C").shape == (10,)
605+
assert model.input("A").shape == (2, 2)
606+
assert model.input("B").shape == (1, 3, 224, 244)
607+
assert model.input("C").shape == (10,)
611608

612609

613-
def test_reshape_list_of_shapes_wrong_size(multi_input_model):
610+
def test_reshape_list_of_shapes_wrong_size(model):
614611
"""Providing wrong number of shapes should raise an error."""
615612
input_shapes = [[2, 2], [1, 3, 224, 244]] # Missing third input
616613
with pytest.raises(RuntimeError, match="Number of shapes does not match"):
617-
multi_input_model.reshape(input_shapes)
614+
model.reshape(input_shapes)
618615

619616

620617
def test_reshape_single_input_flat_list():
@@ -633,22 +630,15 @@ def test_reshape_with_dynamic_dimensions():
633630
model.reshape(input_shapes)
634631

635632
assert model.input("A").shape == (2, 2)
636-
637-
638-
def test_reshape_single_input_flat_list_with_list_intervals():
639-
"""Single-input flat list: ensure list-based dim intervals are treated as flat."""
640-
param = ops.parameter([1, 3, 224, 224])
641-
model = Model(ops.relu(param), [param])
642-
643-
# Use list-based intervals (inner lists) for dimensions — should be treated
644-
# as a flat shape for single-input models and parsed as PartialShape.
645-
shape = [1, 3, [224, 256], [224, 256]]
646-
model.reshape(shape)
647-
648-
expected = PartialShape([Dimension(1), Dimension(3), Dimension(224, 256), Dimension(224, 256)])
649-
for inp in model.inputs:
650-
assert inp.partial_shape == expected
651-
# single-input model: no inputs named "B", further checks not applicable
633+
b_shape = model.input("B").get_partial_shape()
634+
assert b_shape[0] == 1
635+
assert b_shape[1] == 3
636+
assert b_shape[2].is_dynamic
637+
assert b_shape[2].get_min_length() == 224
638+
assert b_shape[2].get_max_length() == 256
639+
assert b_shape[3].is_dynamic
640+
assert b_shape[3].get_min_length() == 224
641+
assert b_shape[3].get_max_length() == 256
652642

653643

654644
def test_reshape_with_tuple_shapes_multi_input():
@@ -837,20 +827,20 @@ def check_rt_info(model):
837827

838828
assert model.get_rt_info(["config", "type_of_model"]).astype(str) == "classification"
839829
assert model.get_rt_info(["config", "converter_type"]).astype(str) == "classification"
840-
assert math.isclose(model.get_rt_info(
841-
["config", "model_parameters", "threshold"]).astype(float), 13.23, rel_tol=0.0001)
842-
assert math.isclose(model.get_rt_info(
843-
["config", "model_parameters", "min"]).astype(float), -3.24543, rel_tol=0.0001)
844-
assert math.isclose(model.get_rt_info(
845-
["config", "model_parameters", "max"]).astype(float), 3.234223, rel_tol=0.0001)
830+
assert math.isclose(model.get_rt_info(["config", "model_parameters",
831+
"threshold"]).astype(float), 13.23, rel_tol=0.0001)
832+
assert math.isclose(model.get_rt_info(["config", "model_parameters",
833+
"min"]).astype(float), -3.24543, rel_tol=0.0001)
834+
assert math.isclose(model.get_rt_info(["config", "model_parameters",
835+
"max"]).astype(float), 3.234223, rel_tol=0.0001)
846836
assert model.get_rt_info(["config", "model_parameters", "labels", "label_tree", "type"]).astype(str) == "tree"
847-
assert model.get_rt_info(
848-
["config", "model_parameters", "labels", "label_tree", "directed"]).astype(bool) is True
837+
assert model.get_rt_info(["config", "model_parameters", "labels",
838+
"label_tree", "directed"]).astype(bool) is True
849839

850840
assert model.get_rt_info(["config", "model_parameters", "labels", "label_tree", "float_empty"]).aslist() == []
851841
assert model.get_rt_info(["config", "model_parameters", "labels", "label_tree", "nodes"]).aslist() == []
852-
assert model.get_rt_info(
853-
["config", "model_parameters", "labels", "label_groups", "ids"]).aslist(str) == ["sasd", "fdfdfsdf"]
842+
assert model.get_rt_info(["config", "model_parameters", "labels", "label_groups",
843+
"ids"]).aslist(str) == ["sasd", "fdfdfsdf"]
854844
assert model.get_rt_info(["config", "model_parameters", "mean_values"]).aslist(float) == [22.3, 33.11, 44.0]
855845
assert model.get_rt_info("enum_info_int").astype(int) == 1
856846
assert model.get_rt_info("enum_info_str").astype(str) == "info_str"

src/bindings/python/tests/utils/helpers.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# -*- coding: utf-8 -*-
12
# Copyright (C) 2018-2026 Intel Corporation
23
# SPDX-License-Identifier: Apache-2.0
34

@@ -242,8 +243,8 @@ def generate_add_model(input_shape: list[int] = None, input_dtype=np.float32) ->
242243
return Model(add, [param1, param2], "TestModel")
243244

244245

245-
def generate_multi_input_model() -> openvino.Model:
246-
"""Generate a model with three inputs and three corresponding addition outputs."""
246+
def generate_multi_input_model():
247+
247248
input_a = ops.parameter([2, 2], name="A")
248249
input_b = ops.parameter([1, 3, 224, 244], name="B")
249250
input_c = ops.parameter([10], name="C")
Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)