Skip to content

Commit

Permalink
Do not do a full recalc when creating a new Var.
Browse files Browse the repository at this point in the history
This is to avoid triggering the calculation of lazy variables in the chain.
Method .w renamed to .widget_set as it makes more sense.

Added new testcases
  • Loading branch information
kefirbandi committed Jan 19, 2022
1 parent 3f9496b commit a1704a5
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 9 deletions.
17 changes: 12 additions & 5 deletions autocalc/autocalc.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import warnings

from IPython.display import display
from ipywidgets import FloatText, FileUpload, Button, HBox, DatePicker
import math
Expand Down Expand Up @@ -111,8 +113,8 @@ def __init__(self, name:str=None, *, fun=None, inputs=[], initial_value=undefine
# Var just created. No other Var depends on it yet, so no need to update anything upstream.
# Just set or recalculate the value
self._set_raw(initial_value, skip_updating_this_widget= initial_value is undefined) # The underlying value
if (initial_value is undefined) and (not lazy):
self.recalc()
if (initial_value is undefined) and (not lazy) and (self.fun is not None):
self._recalc_this_node_only()

# self.outer_obj = None

Expand Down Expand Up @@ -317,7 +319,7 @@ def _recalc_this_node_only(self):
self._set_raw(v)

@property
def w(self):
def widget_set(self):
"""
Returns the "thing" that you can put inside `display` or `HBox`.
:return:
Expand All @@ -330,10 +332,15 @@ def w(self):
if help:
label.description += ' (?)'
label.tooltip = help
label.style.button_color = 'lightgreen'
label.style.button_color = 'lightgreen'
return HBox([label, widget])
else:
return self._get_raw()

@property
def w(self):
warnings.warn('The "w" field of Var is deprecated. Please use "widget_set" instead.')
return self.widget_set

def _ipython_display_(self):
display(self.w)
display(self.widget_set)
55 changes: 55 additions & 0 deletions tests/test_3_nodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from autocalc.autocalc import Var

# c depends on b, which depends on a
# a -> b -> c
def double(x):
return 2*x

class EC():
def __init__(self):
self.execution_count = 0

@property
def executed(self):
v = self.execution_count
self.execution_count = 0
return v

def fun(self, x):
self.execution_count += 1
return 2*x


def test_proper_function_triggering():
ecB = EC()
ecC = EC()
a = Var('A', initial_value=1)
b = Var('B', fun=ecB.fun, inputs=[a])
assert ecB.executed
c = Var('C', fun=ecC.fun, inputs=[b])
assert not ecB.executed
assert ecC.executed

assert c._get_raw() == 4
assert c.get() == 4

assert not ecB.executed
assert not ecC.executed

b.set(6)

assert not ecB.executed
assert ecC.executed

assert c._get_raw() == 12
assert a._get_raw() == 1

a.set(2)

assert ecB.executed
assert ecC.executed

assert c.get() == 8
assert not ecC.executed


18 changes: 14 additions & 4 deletions tests/test_one_level_dependency.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from autocalc.autocalc import Var, undefined


def _b(a):
def double(a):
return 2*a

def test_update():
a = Var('A', initial_value=1)
b = Var('B', fun=_b, inputs=[a])
b_lazy = Var('B_lazy', fun=_b, inputs=[a], lazy=True)
b = Var('B', fun=double, inputs=[a])
b_lazy = Var('B_lazy', fun=double, inputs=[a], lazy=True)

assert b.get() == 2
assert b_lazy._get_raw() is undefined
Expand All @@ -30,4 +30,14 @@ def test_update():
assert b.get(undefined_inputs) is undefined

assert len(undefined_inputs) == 1
assert a in undefined_inputs
assert a in undefined_inputs

def test_read_only():
a = Var('A', initial_value=1)
b = Var('B', fun=double, inputs=[a], read_only=True)

b.set(12)
assert b.get() == 2

a.set(6)
assert b.get() == 12

0 comments on commit a1704a5

Please sign in to comment.