Skip to content

Commit c9e2ce9

Browse files
committed
Explicit reference semantics.
1 parent d3b80be commit c9e2ce9

File tree

2 files changed

+21
-22
lines changed

2 files changed

+21
-22
lines changed

testbook/client.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,13 @@ def ref(self, name: str) -> Union[TestbookObjectReference, Any]:
3939

4040
# Check if exists
4141
self.inject(name, pop=True)
42-
try:
43-
self.inject(f"import cloudpickle; cloudpickle.dumps({name})", pop=True)
44-
return self.value(name)
45-
except Exception:
46-
return TestbookObjectReference(self, name)
42+
return TestbookObjectReference(self, name)
4743

4844
def get(self, item):
49-
return self.ref(item)
45+
return self.value(item)
5046

5147
def __getitem__(self, item):
52-
return self.ref(item)
48+
return self.value(item)
5349

5450
@staticmethod
5551
def _construct_call_code(
@@ -251,9 +247,6 @@ def value(self, code: str) -> Any:
251247
"""
252248
Execute given code in the kernel and returns the serializeable result.
253249
254-
This error object will also contain an attribute called `save_varname` which
255-
can be used to create a reference object with :meth:`ref`.
256-
257250
Parameters
258251
----------
259252
code: str
@@ -276,14 +269,17 @@ def value(self, code: str) -> Any:
276269
raise TestbookExecuteResultNotFoundError(
277270
'code provided does not produce execute_result'
278271
)
272+
273+
save_varname = random_varname()
279274

280275
import tempfile
281276
with tempfile.NamedTemporaryFile() as tmp:
282277
try:
283278
inject_code = f"""
284279
import cloudpickle
280+
{save_varname} = get_ipython().last_execution_result.result
285281
with open('{tmp.name}', 'wb') as f:
286-
cloudpickle.dump(get_ipython().last_execution_result.result, f)
282+
cloudpickle.dump({save_varname}, f)
287283
"""
288284
outputs = self.inject(inject_code, pop=True).outputs
289285
if len(outputs) > 0 and outputs[0].output_type == "error":
@@ -294,7 +290,9 @@ def value(self, code: str) -> Any:
294290
with open(tmp.name, 'rb') as f:
295291
return cloudpickle.load(f)
296292
except TestbookRuntimeError:
297-
raise TestbookSerializeError('could not serialize output')
293+
e = TestbookSerializeError('could not serialize output')
294+
e.save_varname = save_varname
295+
raise e
298296

299297
@contextmanager
300298
def patch(self, target, **kwargs):

testbook/tests/test_reference.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,28 @@ def notebook():
1212

1313
def test_create_reference(notebook):
1414
a = notebook.ref("a")
15-
assert repr(a) == "[1, 2, 3]"
15+
assert repr(a) == "'[1, 2, 3]'"
1616

1717

18-
def test_create_reference_getitem(notebook):
19-
a = notebook["a"]
20-
assert repr(a) == "[1, 2, 3]"
18+
def test_create_reference_resolve(notebook):
19+
a = notebook.ref("a")
20+
assert a.resolve() == [1, 2, 3]
2121

2222

23-
def test_create_reference_get(notebook):
23+
def test_notebook_get_value(notebook):
2424
a = notebook.get("a")
25-
assert repr(a) == "[1, 2, 3]"
25+
assert a == [1, 2, 3]
2626

2727

2828
def test_eq_in_notebook(notebook):
2929
a = notebook.ref("a")
3030
a.append(4)
31-
assert a == [1, 2, 3, 4]
31+
assert a.resolve() == [1, 2, 3, 4]
3232

3333

3434
def test_eq_in_notebook_ref(notebook):
3535
a, b = notebook.ref("a"), notebook.ref("b")
36-
assert a == b
36+
assert a.resolve()[:3] == b
3737

3838

3939
def test_function_call(notebook):
@@ -43,8 +43,9 @@ def test_function_call(notebook):
4343

4444
def test_function_call_with_ref_object(notebook):
4545
double, a = notebook.ref("double"), notebook.ref("a")
46-
47-
assert double(a) == [2, 4, 6]
46+
# a.append(4) above applied to the referenced "a" and therefore is
47+
# reflected here
48+
assert double(a) == [2, 4, 6, 8]
4849

4950

5051
def test_nontrivial_pickling(notebook):

0 commit comments

Comments
 (0)