code: def eval(self, frame):
      expr = Interpretable(self.expr)
      expr.eval(frame)
      for operation, expr2 in self.ops:
          if hasattr(self, "result"):
              # shortcutting in chained expressions
              if not frame.is_true(self.result):
                  break
          expr2 = Interpretable(expr2)
          expr2.eval(frame)
          self.explanation = "%s %s %s" % (
              expr.explanation,
              operation,
              expr2.explanation,
          )
          source = "__exprinfo_left %s __exprinfo_right" % operation
          try:
              self.result = frame.eval(
                  source,
                  __exprinfo_left=expr.result,
                  __exprinfo_right=expr2.result,
              )
          except passthroughex:
              raise
          except:
              raise Failure(self)
          expr = expr2
  
imports: import py
  import sys, inspect
  from compiler import parse, ast, pycodegen
  from py._code.assertion import BuiltinAssertionError, _format_explanation
  import types
label_desc: Use image node_id 1 for calling the Compare obj's underlying member method code with example usage: obj.eval(frame) without return types