aidhound / hotxlfp

A Python Excel Formula Parser similar to the javascript handsontable formulaparser
MIT License
27 stars 12 forks source link

Certain number comparisons have inverted results #6

Closed ievans3024 closed 3 years ago

ievans3024 commented 3 years ago

Python 3.7.3 hotxlfp 0.0.11

Under the following conditions:

The following shows the behavior in action:

>>> from hotxlfp import Parser
>>> p = Parser()
>>> p.on('callCellValue', lambda *_: 3)
<hotxlfp.parser.Parser object at 0x10dd8ddd8>
>>> p.parse('A1 > 3.5')
{'result': False, 'error': None}
>>> p.parse('A1 < 3.5')
{'result': True, 'error': None}
>>> p.parse('A1 > 2.5')
{'result': False, 'error': None}
>>> p.parse('A1 < 2.5')
{'result': True, 'error': None}
>>> p.parse('4.5 > A1')
{'result': False, 'error': None}
>>> p.parse('4.5 < A1')
{'result': True, 'error': None}

# this particular case is an exception. unsure why.
>>> p.on('callCellValue', lambda *_: 3.5)
<hotxlfp.parser.Parser object at 0x10dd8ddd8>
>>> p.parse('4 < A1')
{'result': False, 'error': None}
>>> p.parse('4 > A1')
{'result': True, 'error': None}

# comparing hardcoded numbers exhibits the same behavior
>>> p.parse('3 < 2.25')
{'result': True, 'error': None}
>>> p.parse('3 > 2.25')
{'result': False, 'error': None}
>>> p.parse('3.5 > 2')
{'result': False, 'error': None}
>>> p.parse('3.5 < 2')
{'result': True, 'error': None}

# comparing the same type works fine
>>> p.parse('3.14 > 2.25')
{'result': True, 'error': None}
>>> p.parse('3.14 < 2.25')
{'result': False, 'error': None}
>>> p.parse('3 < 2')
{'result': False, 'error': None}
>>> p.parse('3 > 2')
{'result': True, 'error': None}

# same behavior applies to cell values
# same type compares fine
>>> values = [[1, 3]]
>>> p.on('callCellValue', lambda cell, done: done(values[cell.row.index][cell.col.index]))
<hotxlfp.parser.Parser object at 0x10dd8ddd8>
>>> p.parse('A1 < B1')  # 1 is less than 3
{'result': True, 'error': None}
>>> p.parse('A1 > B1')  # 1 is greater than 3
{'result': False, 'error': None}
>>> p.parse('B1 > A1')
{'result': True, 'error': None}
>>> p.parse('B1 < A1')
{'result': False, 'error': None}

# different types have inverted results
>>> values = [[1, 2.5]]
>>> p.on('callCellValue', lambda cell, done: done(values[cell.row.index][cell.col.index]))
<hotxlfp.parser.Parser object at 0x10dd8ddd8>
>>> p.parse('A1 > B1')
{'result': False, 'error': None}
>>> p.parse('A1 < B1')
{'result': True, 'error': None}
>>> p.parse('B1 > A1')
{'result': False, 'error': None}
>>> p.parse('B1 < A1')
{'result': True, 'error': None}

Additionally, in exploring this bug, I found that if a hardcoded floating point number less than 1 does not start with 0, it errors. I am unsure if this is intentional:

>>> p.parse('A1 > .5')
{'result': None, 'error': '#ERROR!'}
leonelcamara commented 3 years ago

@ievans3024 this was an amazing bug report thanks a lot!