edsl 0.1.58__py3-none-any.whl → 0.1.59__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.
@@ -16,8 +16,9 @@ class InterviewExceptionEntry:
16
16
  invigilator: "InvigilatorBase",
17
17
  traceback_format="text",
18
18
  answers=None,
19
+ time=None, # Added time parameter for deserialization
19
20
  ):
20
- self.time = datetime.datetime.now().isoformat()
21
+ self.time = time or datetime.datetime.now().isoformat()
21
22
  self.exception = exception
22
23
  self.invigilator = invigilator
23
24
  self.traceback_format = traceback_format
@@ -130,7 +131,12 @@ class InterviewExceptionEntry:
130
131
  'Traceback (most recent call last):...'
131
132
  """
132
133
  e = self.exception
133
- tb_str = "".join(traceback.format_exception(type(e), e, e.__traceback__))
134
+ # Check if the exception has a traceback attribute
135
+ if hasattr(e, "__traceback__") and e.__traceback__:
136
+ tb_str = "".join(traceback.format_exception(type(e), e, e.__traceback__))
137
+ else:
138
+ # Use the message as traceback if no traceback available
139
+ tb_str = f"Exception: {str(e)}"
134
140
  return tb_str
135
141
 
136
142
  @property
@@ -144,14 +150,19 @@ class InterviewExceptionEntry:
144
150
 
145
151
  console = Console(file=html_output, record=True)
146
152
 
147
- tb = Traceback.from_exception(
148
- type(self.exception),
149
- self.exception,
150
- self.exception.__traceback__,
151
- show_locals=True,
152
- )
153
- console.print(tb)
154
- return html_output.getvalue()
153
+ # Check if the exception has a traceback attribute
154
+ if hasattr(self.exception, "__traceback__") and self.exception.__traceback__:
155
+ tb = Traceback.from_exception(
156
+ type(self.exception),
157
+ self.exception,
158
+ self.exception.__traceback__,
159
+ show_locals=True,
160
+ )
161
+ console.print(tb)
162
+ return html_output.getvalue()
163
+ else:
164
+ # Return a simple string if no traceback available
165
+ return f"<pre>Exception: {str(self.exception)}</pre>"
155
166
 
156
167
  @staticmethod
157
168
  def serialize_exception(exception: Exception) -> dict:
@@ -160,14 +171,25 @@ class InterviewExceptionEntry:
160
171
  >>> entry = InterviewExceptionEntry.example()
161
172
  >>> _ = entry.serialize_exception(entry.exception)
162
173
  """
163
- return {
164
- "type": type(exception).__name__,
165
- "message": str(exception),
166
- "traceback": "".join(
174
+ # Store the original exception type for proper reconstruction
175
+ exception_type = type(exception).__name__
176
+ module_name = getattr(type(exception), "__module__", "builtins")
177
+
178
+ # Extract traceback if available
179
+ if hasattr(exception, "__traceback__") and exception.__traceback__:
180
+ tb_str = "".join(
167
181
  traceback.format_exception(
168
182
  type(exception), exception, exception.__traceback__
169
183
  )
170
- ),
184
+ )
185
+ else:
186
+ tb_str = f"Exception: {str(exception)}"
187
+
188
+ return {
189
+ "type": exception_type,
190
+ "module": module_name,
191
+ "message": str(exception),
192
+ "traceback": tb_str,
171
193
  }
172
194
 
173
195
  @staticmethod
@@ -177,11 +199,31 @@ class InterviewExceptionEntry:
177
199
  >>> entry = InterviewExceptionEntry.example()
178
200
  >>> _ = entry.deserialize_exception(entry.to_dict()["exception"])
179
201
  """
202
+ exception_type = data.get("type", "Exception")
203
+ module_name = data.get("module", "builtins")
204
+ message = data.get("message", "")
205
+
180
206
  try:
181
- exception_class = globals()[data["type"]]
182
- except KeyError:
183
- exception_class = Exception
184
- return exception_class(data["message"])
207
+ # Try to import the module and get the exception class
208
+ # if module_name != "builtins":
209
+ # import importlib
210
+
211
+ # module = importlib.import_module(module_name)
212
+ # exception_class = getattr(module, exception_type, Exception)
213
+ # else:
214
+ # # Look for exception in builtins
215
+ import builtins
216
+
217
+ exception_class = getattr(builtins, exception_type, Exception)
218
+
219
+ except (ImportError, AttributeError):
220
+ # Fall back to a generic Exception but preserve the type name
221
+ exception = Exception(message)
222
+ exception.__class__.__name__ = exception_type
223
+ return exception
224
+
225
+ # Create instance of the original exception type if possible
226
+ return exception_class(message)
185
227
 
186
228
  def to_dict(self) -> dict:
187
229
  """Return the exception as a dictionary.
@@ -221,7 +263,11 @@ class InterviewExceptionEntry:
221
263
  invigilator = None
222
264
  else:
223
265
  invigilator = InvigilatorAI.from_dict(data["invigilator"])
224
- return cls(exception=exception, invigilator=invigilator)
266
+
267
+ # Use the original timestamp from serialization
268
+ time = data.get("time")
269
+
270
+ return cls(exception=exception, invigilator=invigilator, time=time)
225
271
 
226
272
 
227
273
  class InterviewExceptionCollection(UserDict):
@@ -105,7 +105,11 @@ class InvigilatorBase(ABC):
105
105
  value = getattr(self, attr)
106
106
  if value is None:
107
107
  return None
108
- if hasattr(value, "to_dict"):
108
+ if attr == "scenario" and hasattr(value, "offload"):
109
+ # Use the scenario's offload method to replace base64_string values
110
+ offloaded = value.offload()
111
+ return offloaded.to_dict()
112
+ elif hasattr(value, "to_dict"):
109
113
  return value.to_dict()
110
114
  if isinstance(value, (int, float, str, bool, dict, list)):
111
115
  return value