text: import py
  
  from _pytest._code.code import TerminalRepr
  
  
  def getslaveinfoline(node):
      try:
          return node._slaveinfocache
      except AttributeError:
          d = node.slaveinfo
          ver = "%s.%s.%s" % d["version_info"][:3]
          node._slaveinfocache = s = "[%s] %s -- Python %s %s" % (
              d["id"],
              d["sysplatform"],
              ver,
              d["executable"],
          )
          return s
  
  
  class BaseReport(object):
      when = None
  
      def __init__(self, **kw):
          self.__dict__.update(kw)
  
      def toterminal(self, out):
          if hasattr(self, "node"):
              out.line(getslaveinfoline(self.node))
  
          longrepr = self.longrepr
          if longrepr is None:
              return
  
          if hasattr(longrepr, "toterminal"):
              longrepr.toterminal(out)
          else:
              try:
                  out.line(longrepr)
              except UnicodeEncodeError:
                  out.line("<unprintable longrepr>")
  
      def get_sections(self, prefix):
          for name, content in self.sections:
              if name.startswith(prefix):
                  yield prefix, content
  
      @property
      def longreprtext(self):
          """
          Read-only property that returns the full string representation
          of ``longrepr``.
  
          .. versionadded:: 3.0
          """
          tw = py.io.TerminalWriter(stringio=True)
          tw.hasmarkup = False
          self.toterminal(tw)
          exc = tw.stringio.getvalue()
          return exc.strip()
  
      @property
      def caplog(self):
          """Return captured log lines, if log capturing is enabled
  
          .. versionadded:: 3.5
          """
          return "\n".join(
              content for (prefix, content) in self.get_sections("Captured log")
          )
  
      @property
      def capstdout(self):
          """Return captured text from stdout, if capturing is enabled
  
          .. versionadded:: 3.0
          """
          return "".join(
              content for (prefix, content) in self.get_sections("Captured stdout")
          )
  
      @property
      def capstderr(self):
          """Return captured text from stderr, if capturing is enabled
  
          .. versionadded:: 3.0
          """
          return "".join(
              content for (prefix, content) in self.get_sections("Captured stderr")
          )
  
      passed = property(lambda x: x.outcome == "passed")
      failed = property(lambda x: x.outcome == "failed")
      skipped = property(lambda x: x.outcome == "skipped")
  
      @property
      def fspath(self):
          return self.nodeid.split("::")[0]
  
  
  class TestReport(BaseReport):
      """ Basic test report object (also used for setup and teardown calls if
      they fail).
      """
  
      def __init__(
          self,
          nodeid,
          location,
          keywords,
          outcome,
          longrepr,
          when,
          sections=(),
          duration=0,
          user_properties=None,
          **extra
      ):
          #: normalized collection node id
          self.nodeid = nodeid
  
          #: a (filesystempath, lineno, domaininfo) tuple indicating the
          #: actual location of a test item - it might be different from the
          #: collected one e.g. if a method is inherited from a different module.
          self.location = location
  
          #: a name -> value dictionary containing all keywords and
          #: markers associated with a test invocation.
          self.keywords = keywords
  
          #: test outcome, always one of "passed", "failed", "skipped".
          self.outcome = outcome
  
          #: None or a failure representation.
          self.longrepr = longrepr
  
          #: one of 'setup', 'call', 'teardown' to indicate runtest phase.
          self.when = when
  
          #: user properties is a list of tuples (name, value) that holds user
          #: defined properties of the test
          self.user_properties = list(user_properties or [])
  
          #: list of pairs ``(str, str)`` of extra information which needs to
          #: marshallable. Used by pytest to add captured text
          #: from ``stdout`` and ``stderr``, but may be used by other plugins
          #: to add arbitrary information to reports.
          self.sections = list(sections)
  
          #: time it took to run just the test
          self.duration = duration
  
          self.__dict__.update(extra)
  
      def __repr__(self):
          return "<TestReport %r when=%r outcome=%r>" % (
              self.nodeid,
              self.when,
              self.outcome,
          )
  
  
  class TeardownErrorReport(BaseReport):
      outcome = "failed"
      when = "teardown"
  
      def __init__(self, longrepr, **extra):
          self.longrepr = longrepr
          self.sections = []
          self.__dict__.update(extra)
  
  
  class CollectReport(BaseReport):
      when = "collect"
  
      def __init__(self, nodeid, outcome, longrepr, result, sections=(), **extra):
          self.nodeid = nodeid
          self.outcome = outcome
          self.longrepr = longrepr
          self.result = result or []
          self.sections = list(sections)
          self.__dict__.update(extra)
  
      @property
      def location(self):
          return (self.fspath, None, self.fspath)
  
      def __repr__(self):
          return "<CollectReport %r lenresult=%s outcome=%r>" % (
              self.nodeid,
              len(self.result),
              self.outcome,
          )
  
  
  class CollectErrorRepr(TerminalRepr):
      def __init__(self, msg):
          self.longrepr = msg
  
      def toterminal(self, out):
          out.line(self.longrepr, red=True)
  