Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def _eval_zero(evaluator, tree):
return IntermediateExpr(False, None, True, [])
if tree.args[1].type in ("ONE", "NUMBER"):
expr = tree.args[1].token.extra
try:
power = int(expr)
except ValueError:
pass
if power < 1:
raise PatsyError("'**' requires a positive integer", tree.args[1])
all_terms = left_expr.terms
big_expr = left_expr
# Small optimization: (a + b)**100 is just the same as (a + b)**2.
power = min(len(left_expr.terms), power)
for i in range(1, power):
big_expr = _interaction(left_expr, big_expr)
all_terms = all_terms + big_expr.terms
return IntermediateExpr(False, None, False, all_terms)
def _eval_binary_minus(evaluator, tree):
left_expr = evaluator.eval(tree.args[0])
if tree.args[1].type == "ZERO":
return IntermediateExpr(True, tree.args[1], False,
left_expr.terms)
elif tree.args[1].type == "ONE":
return IntermediateExpr(False, None, True, left_expr.terms)
else:
right_expr = evaluator.eval(tree.args[1])
terms = [term for term in left_expr.terms
if term not in right_expr.terms]
if right_expr.intercept:
return IntermediateExpr(False, None, True, terms)
else:
return IntermediateExpr(left_expr.intercept,
left_expr.intercept_origin,
left_expr.intercept_removed,
terms)
def _eval_binary_plus(evaluator, tree):
left_expr = evaluator.eval(tree.args[0])
if tree.args[1].type == "ZERO":
return IntermediateExpr(False, None, True, left_expr.terms)
else:
right_expr = evaluator.eval(tree.args[1])
if right_expr.intercept:
return IntermediateExpr(True, right_expr.intercept_origin, False,
left_expr.terms + right_expr.terms)
else:
return IntermediateExpr(left_expr.intercept,
left_expr.intercept_origin,
left_expr.intercept_removed,
left_expr.terms + right_expr.terms)
def _interaction(left_expr, right_expr):
for expr in (left_expr, right_expr):
_check_interactable(expr)
terms = []
for l_term in left_expr.terms:
for r_term in right_expr.terms:
terms.append(Term(l_term.factors + r_term.factors))
return IntermediateExpr(False, None, False, terms)
def eval(self, tree, require_evalexpr=True):
result = None
assert isinstance(tree, ParseNode)
key = (tree.type, len(tree.args))
if key not in self._evaluators:
raise PatsyError("I don't know how to evaluate this "
"'%s' operator" % (tree.type,),
tree.token)
result = self._evaluators[key](self, tree)
if require_evalexpr and not isinstance(result, IntermediateExpr):
if isinstance(result, ModelDesc):
raise PatsyError("~ can only be used once, and "
"only at the top level",
tree)
else:
raise PatsyError("custom operator returned an "
"object that I don't know how to "
"handle", tree)
return result
def _eval_any_tilde(evaluator, tree):
exprs = [evaluator.eval(arg) for arg in tree.args]
if len(exprs) == 1:
# Formula was like: "~ foo"
# We pretend that instead it was like: "0 ~ foo"
exprs.insert(0, IntermediateExpr(False, None, True, []))
assert len(exprs) == 2
# Note that only the RHS gets an implicit intercept:
return ModelDesc(_maybe_add_intercept(exprs[0].intercept, exprs[0].terms),
_maybe_add_intercept(not exprs[1].intercept_removed,
exprs[1].terms))
def _eval_binary_div(evaluator, tree):
left_expr = evaluator.eval(tree.args[0])
right_expr = evaluator.eval(tree.args[1])
terms = list(left_expr.terms)
_check_interactable(left_expr)
# Build a single giant combined term for everything on the left:
left_factors = []
for term in left_expr.terms:
left_factors += list(term.factors)
left_combined_expr = IntermediateExpr(False, None, False,
[Term(left_factors)])
# Then interact it with everything on the right:
terms += list(_interaction(left_combined_expr, right_expr).terms)
return IntermediateExpr(False, None, False, terms)
def _eval_binary_minus(evaluator, tree):
left_expr = evaluator.eval(tree.args[0])
if tree.args[1].type == "ZERO":
return IntermediateExpr(True, tree.args[1], False,
left_expr.terms)
elif tree.args[1].type == "ONE":
return IntermediateExpr(False, None, True, left_expr.terms)
else:
right_expr = evaluator.eval(tree.args[1])
terms = [term for term in left_expr.terms
if term not in right_expr.terms]
if right_expr.intercept:
return IntermediateExpr(False, None, True, terms)
else:
return IntermediateExpr(left_expr.intercept,
left_expr.intercept_origin,
left_expr.intercept_removed,
terms)