from info import lazy_value_or_error, is_error from usertypes import AltText # pylint: disable=unused-import,import-error def AND(logical_expression, *logical_expressions): """ Returns True if all of the arguments are logically true, and False if any are false. Same as `all([value1, value2, ...])`. >>> AND(1) True >>> AND(0) False >>> AND(1, 1) True >>> AND(1,2,3,4) True >>> AND(1,2,3,4,0) False """ return all((logical_expression,) + logical_expressions) def FALSE(): """ Returns the logical value `False`. You may also use the value `False` directly. This function is provided primarily for compatibility with other spreadsheet programs. >>> FALSE() False """ return False def IF(logical_expression, value_if_true, value_if_false): """ Returns one value if a logical expression is `True` and another if it is `False`. The equivalent Python expression is: ``` value_if_true if logical_expression else value_if_false ``` Since Grist supports multi-line formulas, you may also use Python blocks such as: ``` if logical_expression: return value_if_true else: return value_if_false ``` NOTE: Grist follows Excel model by only evaluating one of the value expressions, by automatically wrapping the expressions to use lazy evaluation. This allows `IF(False, 1/0, 1)` to evaluate to `1` rather than raise an exception. >>> IF(12, "Yes", "No") 'Yes' >>> IF(None, "Yes", "No") 'No' >>> IF(True, 0.85, 0.0) 0.85 >>> IF(False, 0.85, 0.0) 0.0 More tests: >>> IF(True, lambda: (1/0), lambda: (17)) Traceback (most recent call last): ... ZeroDivisionError: integer division or modulo by zero >>> IF(False, lambda: (1/0), lambda: (17)) 17 """ return lazy_value(value_if_true) if logical_expression else lazy_value(value_if_false) def IFERROR(value, value_if_error=""): """ Returns the first argument if it is not an error value, otherwise returns the second argument if present, or a blank if the second argument is absent. NOTE: Grist handles values that raise an exception by wrapping them to use lazy evaluation. >>> IFERROR(float('nan'), "**NAN**") '**NAN**' >>> IFERROR(17.17, "**NAN**") 17.17 >>> IFERROR("Text") 'Text' >>> IFERROR(AltText("hello")) '' More tests: >>> IFERROR(lambda: (1/0.1), "X") 10.0 >>> IFERROR(lambda: (1/0.0), "X") 'X' >>> IFERROR(lambda: AltText("A"), "err") 'err' >>> IFERROR(lambda: None, "err") >>> IFERROR(lambda: foo.bar, 123) 123 >>> IFERROR(lambda: "test".bar(), 123) 123 >>> IFERROR(lambda: "test".bar()) '' >>> IFERROR(lambda: "test".upper(), 123) 'TEST' """ value = lazy_value_or_error(value) return value if not is_error(value) else value_if_error def NOT(logical_expression): """ Returns the opposite of a logical value: `NOT(True)` returns `False`; `NOT(False)` returns `True`. Same as `not logical_expression`. >>> NOT(123) False >>> NOT(0) True """ return not logical_expression def OR(logical_expression, *logical_expressions): """ Returns True if any of the arguments is logically true, and false if all of the arguments are false. Same as `any([value1, value2, ...])`. >>> OR(1) True >>> OR(0) False >>> OR(1, 1) True >>> OR(0, 1) True >>> OR(0, 0) False >>> OR(0,False,0.0,"",None) False >>> OR(0,None,3,0) True """ return any((logical_expression,) + logical_expressions) def TRUE(): """ Returns the logical value `True`. You may also use the value `True` directly. This function is provided primarily for compatibility with other spreadsheet programs. >>> TRUE() True """ return True def lazy_value(value): """ Evaluates a lazy value by calling it when it's a callable, or returns it unchanged otherwise. """ return value() if callable(value) else value