vallettea / koala

Transpose your Excel calculations into python for better performances and scaling.
GNU General Public License v3.0
143 stars 60 forks source link

When there is no argument for a function, Koala exits. #232

Open eiso opened 4 years ago

eiso commented 4 years ago

I ran into the issue that if a function is not passed an argument, koala is unable to accept it. Please find a reproducible case below with the function TODAY() which exists in excellib.py.

Modify example/basic.py (line 24):

from __future__ import print_function

from koala.ExcelCompiler import ExcelCompiler
from koala.Spreadsheet import Spreadsheet

filename = "./examples/basic.xlsx"

print(filename)

### Graph Generation ###
c = ExcelCompiler(filename)
sp = c.gen_graph()

## Graph Serialization ###
print("Serializing to disk...")
sp.dump(filename.replace("xlsx", "gzip"))

### Graph Loading ###
print("Reading from disk...")
sp = Spreadsheet.load(filename.replace("xlsx", "gzip"))

### Graph Evaluation ###
#sp.set_value('Sheet1!A1', 10)
sp.cell_set_formula('Sheet1!A1', formula='=TODAY()')

print('New D1 value: %s' % str(sp.evaluate('Sheet1!D1')))

Output:

$ python3 examples/basic.py
./examples/basic.xlsx
Serializing to disk...
Reading from disk...
Graph loading done, 120 nodes, 111 edges, 120 cellmap entries
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/networkx/classes/digraph.py", line 837, in predecessors
    return iter(self._pred[n])
KeyError: <koala.ast.astnodes.FunctionNode object at 0x121edddd0>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "examples/basic.py", line 24, in <module>
    sp.cell_set_formula('Sheet1!A1', formula='=TODAY()')
  File "/Users/x/koala/koala/Spreadsheet.py", line 318, in cell_set_formula
    cellmap, G = graph_from_seeds(seeds, self)
  File "/Users/x/koala/koala/ast/__init__.py", line 473, in graph_from_seeds
    pystr, ast = cell2code(c1, names)
  File "/Users/x/koala/koala/ast/__init__.py", line 374, in cell2code
    code = root.emit(ast, context=sheet)
  File "/Users/x/koala/koala/ast/astnodes.py", line 301, in emit
    args = self.children(ast)
  File "/Users/x/koala/koala/ast/astnodes.py", line 44, in children
    args = ast.predecessors(self)
  File "/usr/local/lib/python3.7/site-packages/networkx/classes/digraph.py", line 839, in predecessors
    raise NetworkXError("The node %s is not in the digraph." % (n,))
networkx.exception.NetworkXError: The node TODAY is not in the digraph.

This can be bypassed by adding the following try/except on line 300 in ast/astnodes.py:

try:
    args = self.children(ast)
except:
    args = ''
danielsjf commented 4 years ago

@eiso, thanks a lot for reporting this. I think it is the same problem as #149. Your solution seems quite elegant and feel free to submit it as a PR. If all the other tests pass, this seems like a nice fix.

danielsjf commented 4 years ago

I've seen that the PI functions solves it via astnodes.py: https://github.com/vallettea/koala/blob/62296bdc9e5f42dde6ff72dc436339c07b963b30/koala/ast/astnodes.py#L306

Maybe we should remove this code once you update the code. I like your generic approach better.

danielsjf commented 4 years ago

I would still like to add a test for this so I'll keep it open for the time being. I'm waiting for #231 to be merged. However, the functionality should work now.