def test_compare_timecontext(): c1 = (Timestamp('20170101'), Timestamp('20170103')) c2 = (Timestamp('20170101'), Timestamp('20170111')) c3 = (Timestamp('20160101'), Timestamp('20160103')) c4 = (Timestamp('20161215'), Timestamp('20170102')) assert compare_timecontext(c1, c2) == TimeContextRelation.SUBSET assert compare_timecontext(c2, c1) == TimeContextRelation.SUPERSET assert compare_timecontext(c1, c4) == TimeContextRelation.OVERLAP assert compare_timecontext(c1, c3) == TimeContextRelation.NONOVERLAP
def get_value(self, op: Node, timecontext: Optional[TimeContext] = None) -> Any: """ Given a op and timecontext, get the result from scope Parameters ---------- scope : collections.Mapping a dictionary mapping :class:`~ibis.expr.operations.Node` subclass instances to concrete data, and the time context associate with it (if any). op: ibis.expr.operations.Node key in scope. timecontext: Optional[TimeContext] Returns ------- result: the cached result, an object whose types may differ in different backends. """ if op not in self: return None # for ops without timecontext if timecontext is None: return self._items[op].value else: # For op with timecontext, ther are some ops cannot use cached # result with a different (larger) timecontext to get the # correct result. # For example, a groupby followed by count, if we use a larger or # smaller dataset from cache, we will get an error in result. # Such ops with global aggregation, ops whose result is # depending on other rows in result Dataframe, cannot use cached # result with different time context to optimize calculation. # These are time context sensitive operations. Since these cases # are rare in acutal use case, we just enable optimization for # all nodes for now. cached_timecontext = self._items[op].timecontext if cached_timecontext: relation = compare_timecontext(timecontext, cached_timecontext) if relation == TimeContextRelation.SUBSET: return self._items[op].value else: return self._items[op].value return None