Google OR-Tools v9.15
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
errors.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2# Copyright 2010-2025 Google LLC
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""Translate C++'s absl::Status errors to Python standard errors.
16
17Here we try to use the standard Python errors we would use if the C++ code was
18instead implemented in Python. This will give Python users a more familiar API.
19"""
20
21import enum
22from typing import Optional, Type
23from ortools.math_opt import rpc_pb2
24
25
26class _StatusCode(enum.Enum):
27 """The C++ absl::Status::code() values."""
28
29 OK = 0
30 CANCELLED = 1
31 UNKNOWN = 2
32 INVALID_ARGUMENT = 3
33 DEADLINE_EXCEEDED = 4
34 NOT_FOUND = 5
35 ALREADY_EXISTS = 6
36 PERMISSION_DENIED = 7
37 UNAUTHENTICATED = 16
38 RESOURCE_EXHAUSTED = 8
39 FAILED_PRECONDITION = 9
40 ABORTED = 10
41 OUT_OF_RANGE = 11
42 UNIMPLEMENTED = 12
43 INTERNAL = 13
44 UNAVAILABLE = 14
45 DATA_LOSS = 15
46
47
48class InternalMathOptError(RuntimeError):
49 """Some MathOpt internal error.
50
51 This error is usually raised because of a bug in MathOpt or one of the solver
52 library it wraps.
53 """
54
55
57 status_proto: rpc_pb2.StatusProto,
58) -> Optional[Exception]:
59 """Returns the Python exception that best match the input absl::Status.
60
61 There are some Status that we expect the MathOpt code to return, for those the
62 matching exceptions are:
63 - InvalidArgument: ValueError
64 - FailedPrecondition: AssertionError
65 - Unimplemented: NotImplementedError
66 - Internal: InternalMathOptError
67
68 Other Status's are not used by MathOpt, if they are seen a
69 InternalMathOptError is raised (as if the Status was Internal) and the error
70 message contains the unexpected code.
71
72 Args:
73 status_proto: The input proto to convert to an exception.
74
75 Returns:
76 The corresponding exception. None if the input status is OK.
77 """
78 try:
79 code = _StatusCode(status_proto.code)
80 except ValueError:
81 return InternalMathOptError(
82 f"unknown C++ error (code = {status_proto.code}):"
83 f" {status_proto.message}"
84 )
85
86 if code == _StatusCode.OK:
87 return None
88
89 # For expected errors we compute the corresponding class.
90 error_type: Optional[Type[Exception]] = None
91 if code == _StatusCode.INVALID_ARGUMENT:
92 error_type = ValueError
93 if code == _StatusCode.FAILED_PRECONDITION:
94 error_type = AssertionError
95 if code == _StatusCode.UNIMPLEMENTED:
96 error_type = NotImplementedError
97 if code == _StatusCode.INTERNAL:
98 error_type = InternalMathOptError
99
100 if error_type is not None:
101 return error_type(f"{status_proto.message} (was C++ {code.name})")
102
103 return InternalMathOptError(
104 f"unexpected C++ error {code.name}: {status_proto.message}"
105 )
Optional[Exception] status_proto_to_exception(rpc_pb2.StatusProto status_proto)
Definition errors.py:58