-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy patherrors.py
263 lines (215 loc) · 7.63 KB
/
errors.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
# Copyright 2024, Battelle Energy Alliance, LLC All Rights Reserved.
import traceback
class LineOverRunWarning(UserWarning):
"""
Raised when non-comment inputs exceed the allowed line length in an input.
"""
def __init__(self, message):
self.message = message
class MalformedInputError(ValueError):
"""
Raised when there is an error with the MCNP input not related to the parser.
"""
def __init__(self, input, message):
if input and getattr(input, "input_file", None) and input.input_file:
self.input = input
path = input.input_file.path
start_line = input.line_number
self.path = path
self.start = start_line
lines = "\n".join(input.input_lines)
else:
path = ""
start_line = 0
lines = ""
self.message = message
super().__init__(self.message)
class ParsingError(MalformedInputError):
"""
Raised when there is an error parsing the MCNP input at the SLY parsing layer.
"""
def __init__(self, input, message, error_queue):
messages = []
if input and getattr(input, "input_file", None) and input.input_file:
self.input = input
path = input.input_file.path
start_line = input.line_number
self.path = path
self.start = start_line
else:
path = ""
start_line = 0
if error_queue:
for error in error_queue:
if token := error["token"]:
line_no = error["line"]
index = error["index"]
self.rel_line = line_no
self.abs_line = line_no + start_line
base_message = f'There was an error parsing "{token.value}".'
else:
line_no = 0
index = 0
base_message = f"The input ended prematurely."
messages.append(
_print_input(
path,
start_line,
error["message"],
line_no,
input,
token,
base_message,
index,
)
)
self.message = "\n".join(messages + [message])
else:
self.message = message
ValueError.__init__(self, self.message)
def _print_input(
path,
start_line,
error_msg,
line_no=0,
input=None,
token=None,
base_message=None,
index=None,
):
buffer = [f" {path}, line {start_line + line_no -1}", ""]
if input:
for i, line in enumerate(input.input_lines):
if i == line_no - 1:
buffer.append(f" >{start_line + i:5g}| {line}")
if token:
length = len(token.value)
marker = "^" * length
buffer.append(
f"{' '* 10}|{' ' * (index+1)}{marker} not expected here."
)
else:
buffer.append(f" {start_line + i:5g}| {line}")
if base_message:
buffer.append(base_message)
buffer.append(error_msg)
return "\n".join(buffer)
class NumberConflictError(Exception):
"""
Raised when there is a conflict in number spaces
"""
def __init__(self, message):
self.message = message
super().__init__(message)
class BrokenObjectLinkError(MalformedInputError):
"""Raised when the referenced object does not exist in the input file."""
def __init__(self, parent_type, parent_number, child_type, child_number):
"""
:param parent_type: Name of the parent object linking (e.g., Cell)
:type parent_type: str
:param parent_number: the number of the parent object
:type parent_number: int
:param child_type: Name of the type of object missing in the link (e.g., surface)
:type child_type: str
:param child_number: the number for the missing object
:type child_number: int
"""
super().__init__(
None,
f"{child_type} {child_number} is missing from the input from the definition of: {parent_type} {parent_number}",
)
class RedundantParameterSpecification(ValueError):
"""
Raised when multiple conflicting parameters are given.
e.g., ``1 0 -1 imp:n=5 imp:n=0``
"""
def __init__(self, key, new_value):
self.message = (
f"Multiple values given for parameter: {key}. new_value given: {new_value}."
)
super().__init__(self.message)
class ParticleTypeWarning(Warning):
"""
Base class for incongruencies between particle types
in problem mode, cell importances, and tallies
"""
def __init__(self, message):
self.message = message
super().__init__(message)
class ParticleTypeNotInProblem(ParticleTypeWarning):
"""
Raised when data, such as cell importance or tally type,
are set for a particle type not in the problem's mode.
"""
pass
class ParticleTypeNotInCell(ParticleTypeWarning):
"""
Raised when data for importance data for a particle in
the problem is not provided for a cell.
"""
pass
class UnsupportedFeature(NotImplementedError):
"""
Raised when MCNP syntax that is not supported is found
"""
def __init__(self, message):
self.message = message
super().__init__(self.message)
class UnknownElement(ValueError):
"""
Raised when an undefined element is used.
"""
def __init__(self, missing_val):
self.message = f"An element identified by: {missing_val} is unknown to MontePy."
super().__init__(self.message)
class IllegalState(ValueError):
"""
Raised when an object can't be printed out due to an illegal state.
"""
def __init__(self, message):
self.message = message
super().__init__(self.message)
class LineExpansionWarning(Warning):
"""
Warning for when a field or line expands that may damage user formatting.
"""
def __init__(self, message):
self.message = message
super().__init__(self.message)
def add_line_number_to_exception(error, broken_robot):
"""
Adds additional context to an Exception raised by an :class:`~montepy.mcnp_object.MCNP_Object`.
This will add the line, file name, and the input lines to the error.
:param error: The error that was raised.
:type error: Exception
:param broken_robot: The parent object that had the error raised.
:type broken_robot: MCNP_Object
:raises Exception: ... that's the whole point.
"""
# avoid calling this n times recursively
if hasattr(error, "montepy_handled"):
raise error
error.montepy_handled = True
args = error.args
trace = error.__traceback__
if len(args) > 0:
message = args[0]
else:
message = ""
try:
input_obj = broken_robot._input
assert input_obj is not None
lineno = input_obj.line_number
file = str(input_obj.input_file)
lines = input_obj.input_lines
message = _print_input(file, lineno, message, input=input_obj)
except Exception as e:
try:
message = (
f"{message}\n\nError came from {broken_robot} from an unknown file."
)
except Exception as e2:
message = f"{message}\n\nError came from an object of type {type(broken_robot)} from an unknown file."
args = (message,) + args[1:]
error.args = args
raise error.with_traceback(trace)