prompt: 
  We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  metrics: automatic type detection
  E.g. if we see that output has `.json` suffix, we could safely assume that it is `--type json` without explicitly specifying it.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  
  --- BEGIN FILE ---
  ```
  ### dvc/command/metrics.py
  from __future__ import unicode_literals
  
  import argparse
  
  import dvc.logger as logger
  from dvc.exceptions import DvcException
  from dvc.command.base import CmdBase, fix_subparsers, append_doc_link
  
  
  def show_metrics(metrics, all_branches=False, all_tags=False):
      """
      Args:
          metrics (list): Where each element is either a `list`
              if an xpath was specified, otherwise a `str`
      """
      for branch, val in metrics.items():
          if all_branches or all_tags:
              logger.info("{branch}:".format(branch=branch))
  
          for fname, metric in val.items():
              lines = metric if type(metric) is list else metric.splitlines()
  
              if len(lines) > 1:
                  logger.info("\t{fname}:".format(fname=fname))
  
                  for line in lines:
                      logger.info("\t\t{content}".format(content=line))
  
              else:
                  logger.info("\t{}: {}".format(fname, metric))
  
  
  class CmdMetricsShow(CmdBase):
      def run(self):
          typ = self.args.type
          xpath = self.args.xpath
          try:
              metrics = self.repo.metrics.show(
                  self.args.path,
                  typ=typ,
                  xpath=xpath,
                  all_branches=self.args.all_branches,
                  all_tags=self.args.all_tags,
                  recursive=self.args.recursive,
              )
  
              show_metrics(metrics, self.args.all_branches, self.args.all_tags)
          except DvcException:
              logger.error("failed to show metrics")
              return 1
  
          return 0
  
  
  class CmdMetricsModify(CmdBase):
      def run(self):
          try:
              self.repo.metrics.modify(
                  self.args.path, typ=self.args.type, xpath=self.args.xpath
              )
          except DvcException:
              logger.error("failed to modify metric file settings")
              return 1
  
          return 0
  
  
  class CmdMetricsAdd(CmdBase):
      def run(self):
          try:
              self.repo.metrics.add(
                  self.args.path, self.args.type, self.args.xpath
              )
          except DvcException:
              msg = "failed to add metric file '{}'".format(self.args.path)
              logger.error(msg)
              return 1
  
          return 0
  
  
  class CmdMetricsRemove(CmdBase):
      def run(self):
          try:
              self.repo.metrics.remove(self.args.path)
          except DvcException:
              msg = "failed to remove metric file '{}'".format(self.args.path)
              logger.error(msg)
              return 1
  
          return 0
  
  
  def add_parser(subparsers, parent_parser):
      METRICS_HELP = "Commands to add, manage, collect and display metrics."
  
      metrics_parser = subparsers.add_parser(
          "metrics",
          parents=[parent_parser],
          description=append_doc_link(METRICS_HELP, "metrics"),
          help=METRICS_HELP,
          formatter_class=argparse.RawDescriptionHelpFormatter,
      )
  
      metrics_subparsers = metrics_parser.add_subparsers(
          dest="cmd",
          help="Use dvc metrics CMD --help to display command-specific help.",
      )
  
      fix_subparsers(metrics_subparsers)
  
      METRICS_SHOW_HELP = "Output metric values."
      metrics_show_parser = metrics_subparsers.add_parser(
          "show",
          parents=[parent_parser],
          description=append_doc_link(METRICS_SHOW_HELP, "metrics-show"),
          help=METRICS_SHOW_HELP,
          formatter_class=argparse.RawDescriptionHelpFormatter,
      )
      metrics_show_parser.add_argument(
          "path", nargs="?", help="Path to a metric file or a directory."
      )
      metrics_show_parser.add_argument(
          "-t", "--type", help="Type of metrics (raw/json/tsv/htsv/csv/hcsv)."
      )
      metrics_show_parser.add_argument(
          "-x", "--xpath", help="json/tsv/htsv/csv/hcsv path."
      )
      metrics_show_parser.add_argument(
          "-a",
          "--all-branches",
          action="store_true",
          default=False,
          help="Show metrics for all branches.",
      )
      metrics_show_parser.add_argument(
          "-T",
          "--all-tags",
          action="store_true",
          default=False,
          help="Show metrics for all tags.",
      )
      metrics_show_parser.add_argument(
          "-R",
          "--recursive",
          action="store_true",
          default=False,
          help=(
              "If path is a directory, recursively search and process metric "
              "files in path."
          ),
      )
      metrics_show_parser.set_defaults(func=CmdMetricsShow)
  
      METRICS_ADD_HELP = "Tag file as a metric file."
      metrics_add_parser = metrics_subparsers.add_parser(
          "add",
          parents=[parent_parser],
          description=append_doc_link(METRICS_ADD_HELP, "metrics-add"),
          help=METRICS_ADD_HELP,
          formatter_class=argparse.RawDescriptionHelpFormatter,
      )
      metrics_add_parser.add_argument(
          "-t", "--type", help="Type of metrics (raw/json/tsv/htsv/csv/hcsv)."
      )
      metrics_add_parser.add_argument(
          "-x", "--xpath", help="json/tsv/htsv/csv/hcsv path."
      )
      metrics_add_parser.add_argument("path", help="Path to a metric file.")
      metrics_add_parser.set_defaults(func=CmdMetricsAdd)
  
      METRICS_MODIFY_HELP = "Modify metric file options."
      metrics_modify_parser = metrics_subparsers.add_parser(
          "modify",
          parents=[parent_parser],
          description=append_doc_link(METRICS_MODIFY_HELP, "metrics-modify"),
          help=METRICS_MODIFY_HELP,
          formatter_class=argparse.RawDescriptionHelpFormatter,
      )
      metrics_modify_parser.add_argument(
          "-t", "--type", help="Type of metrics (raw/json/tsv/htsv/csv/hcsv)."
      )
      metrics_modify_parser.add_argument(
          "-x", "--xpath", help="json/tsv/htsv/csv/hcsv path."
      )
      metrics_modify_parser.add_argument("path", help="Path to a metric file.")
      metrics_modify_parser.set_defaults(func=CmdMetricsModify)
  
      METRICS_REMOVE_HELP = "Remove files's metric tag."
      metrics_remove_parser = metrics_subparsers.add_parser(
          "remove",
          parents=[parent_parser],
          description=append_doc_link(METRICS_REMOVE_HELP, "metrics-remove"),
          help=METRICS_REMOVE_HELP,
          formatter_class=argparse.RawDescriptionHelpFormatter,
      )
      metrics_remove_parser.add_argument("path", help="Path to a metric file.")
      metrics_remove_parser.set_defaults(func=CmdMetricsRemove)
  
  
  ### dvc/repo/metrics/show.py
  from __future__ import unicode_literals
  
  import os
  import csv
  import json
  from jsonpath_rw import parse
  
  import dvc.logger as logger
  from dvc.exceptions import OutputNotFoundError, BadMetricError, NoMetricsError
  from dvc.utils.compat import builtin_str, open, StringIO, csv_reader
  
  
  def _read_metric_json(fd, json_path):
      parser = parse(json_path)
      return [x.value for x in parser.find(json.load(fd))]
  
  
  def _get_values(row):
      if isinstance(row, dict):
          return list(row.values())
      else:
          return row
  
  
  def _do_read_metric_xsv(reader, row, col):
      if col is not None and row is not None:
          return [reader[row][col]]
      elif col is not None:
          return [r[col] for r in reader]
      elif row is not None:
          return _get_values(reader[row])
      return [_get_values(r) for r in reader]
  
  
  def _read_metric_hxsv(fd, hxsv_path, delimiter):
      indices = hxsv_path.split(",")
      row = indices[0]
      row = int(row) if row else None
      col = indices[1] if len(indices) > 1 and indices[1] else None
      reader = list(csv.DictReader(fd, delimiter=builtin_str(delimiter)))
      return _do_read_metric_xsv(reader, row, col)
  
  
  def _read_metric_xsv(fd, xsv_path, delimiter):
      indices = xsv_path.split(",")
      row = indices[0]
      row = int(row) if row else None
      col = int(indices[1]) if len(indices) > 1 and indices[1] else None
      reader = list(csv.reader(fd, delimiter=builtin_str(delimiter)))
      return _do_read_metric_xsv(reader, row, col)
  
  
  def _read_typed_metric(typ, xpath, fd):
      if typ == "json":
          ret = _read_metric_json(fd, xpath)
      elif typ == "csv":
          ret = _read_metric_xsv(fd, xpath, ",")
      elif typ == "tsv":
          ret = _read_metric_xsv(fd, xpath, "\t")
      elif typ == "hcsv":
          ret = _read_metric_hxsv(fd, xpath, ",")
      elif typ == "htsv":
          ret = _read_metric_hxsv(fd, xpath, "\t")
      else:
          ret = fd.read().strip()
      return ret
  
  
  def _format_csv(content, delimiter):
      """Format delimited text to have same column width.
  
      Args:
          content (str): The content of a metric.
          delimiter (str): Value separator
  
      Returns:
          str: Formatted content.
  
      Example:
  
          >>> content = (
              "value_mse,deviation_mse,data_set\n"
              "0.421601,0.173461,train\n"
              "0.67528,0.289545,testing\n"
              "0.671502,0.297848,validation\n"
          )
          >>> _format_csv(content, ",")
  
          "value_mse  deviation_mse   data_set\n"
          "0.421601   0.173461        train\n"
          "0.67528    0.289545        testing\n"
          "0.671502   0.297848        validation\n"
      """
      reader = csv_reader(StringIO(content), delimiter=builtin_str(delimiter))
      rows = [row for row in reader]
      max_widths = [max(map(len, column)) for column in zip(*rows)]
  
      lines = [
          " ".join(
              "{entry:{width}}".format(entry=entry, width=width + 2)
              for entry, width in zip(row, max_widths)
          )
          for row in rows
      ]
  
      return "\n".join(lines)
  
  
  def _format_output(content, typ):
      """Tabularize the content according to its type.
  
      Args:
          content (str): The content of a metric.
          typ (str): The type of metric -- (raw|json|tsv|htsv|csv|hcsv).
  
      Returns:
          str: Content in a raw or tabular format.
      """
  
      if "csv" in str(typ):
          return _format_csv(content, delimiter=",")
  
      if "tsv" in str(typ):
          return _format_csv(content, delimiter="\t")
  
      return content
  
  
  def _read_metric(fd, typ=None, xpath=None, rel_path=None, branch=None):
      typ = typ.lower().strip() if typ else typ
      try:
          if xpath:
              return _read_typed_metric(typ, xpath.strip(), fd)
          else:
              return _format_output(fd.read().strip(), typ)
      # Json path library has to be replaced or wrapped in
      # order to fix this too broad except clause.
      except Exception:
          logger.warning(
              "unable to read metric in '{}' in branch '{}'".format(
                  rel_path, branch
              ),
              parse_exception=True,
          )
          return None
  
  
  def _collect_metrics(self, path, recursive, typ, xpath, branch):
      """Gather all the metric outputs.
  
      Args:
          path (str): Path to a metric file or a directory.
          recursive (bool): If path is a directory, do a recursive search for
              metrics on the given path.
          typ (str): The type of metric to search for, could be one of the
              following (raw|json|tsv|htsv|csv|hcsv).
          xpath (str): Path to search for.
          branch (str): Branch to look up for metrics.
  
      Returns:
          list(tuple): (output, typ, xpath)
              - output:
              - typ:
              - xpath:
      """
      outs = [out for stage in self.stages() for out in stage.outs]
  
      if path:
          try:
              outs = self.find_outs_by_path(path, outs=outs, recursive=recursive)
          except OutputNotFoundError:
              logger.debug(
                  "stage file not for found for '{}' in branch '{}'".format(
                      path, branch
                  )
              )
              return []
  
      res = []
      for o in outs:
          if not o.metric:
              continue
  
          if not typ and isinstance(o.metric, dict):
              t = o.metric.get(o.PARAM_METRIC_TYPE, typ)
              x = o.metric.get(o.PARAM_METRIC_XPATH, xpath)
          else:
              t = typ
              x = xpath
  
          res.append((o, t, x))
  
      return res
  
  
  def _read_metrics_filesystem(path, typ, xpath, rel_path, branch):
      if not os.path.exists(path):
          return None
      with open(path, "r") as fd:
          return _read_metric(
              fd, typ=typ, xpath=xpath, rel_path=rel_path, branch=branch
          )
  
  
  def _read_metrics(self, metrics, branch):
      """Read the content of each metric file and format it.
  
      Args:
          metrics (list): List of metric touples
          branch (str): Branch to look up for metrics.
  
      Returns:
          A dict mapping keys with metrics path name and content.
          For example:
  
          {'metric.csv': ("value_mse  deviation_mse   data_set\n"
                          "0.421601   0.173461        train\n"
                          "0.67528    0.289545        testing\n"
                          "0.671502   0.297848        validation\n")}
      """
      res = {}
      for out, typ, xpath in metrics:
          assert out.scheme == "local"
          if out.use_cache:
              metric = _read_metrics_filesystem(
                  self.cache.local.get(out.checksum),
                  typ=typ,
                  xpath=xpath,
                  rel_path=out.rel_path,
                  branch=branch,
              )
          else:
              fd = self.tree.open(out.path)
              metric = _read_metric(
                  fd, typ=typ, xpath=xpath, rel_path=out.rel_path, branch=branch
              )
  
          if not metric:
              continue
  
          res[out.rel_path] = metric
  
      return res
  
  
  def show(
      self,
      path=None,
      typ=None,
      xpath=None,
      all_branches=False,
      all_tags=False,
      recursive=False,
  ):
      res = {}
  
      for branch in self.brancher(all_branches=all_branches, all_tags=all_tags):
          entries = _collect_metrics(self, path, recursive, typ, xpath, branch)
          metrics = _read_metrics(self, entries, branch)
          if metrics:
              res[branch] = metrics
  
      if not res:
          if path:
              raise BadMetricError(path)
          raise NoMetricsError()
  
      return res
  
  ```
  --- END FILE ---
  
  Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.
  
  Every *SEARCH/REPLACE* edit must use this format:
  1. The file path
  2. The start of search block: <<<<<<< SEARCH
  3. A contiguous chunk of lines to search for in the existing source code
  4. The dividing line: =======
  5. The lines to replace into the source code
  6. The end of the replace block: >>>>>>> REPLACE
  
  Here is an example:
  
  ```python
  ### mathweb/flask/app.py
  <<<<<<< SEARCH
  from flask import Flask
  =======
  import math
  from flask import Flask
  >>>>>>> REPLACE
  ```
  
  Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
  Wrap the *SEARCH/REPLACE* edit in blocks ```python...```.
  
instance: {"FAIL_TO_PASS": ["tests/test_metrics.py::TestMetricsType::test_show"], "PASS_TO_PASS": ["tests/test_metrics.py::TestNoMetrics::test_cli", "tests/test_metrics.py::TestMetricsCLI::test_xpath_is_none", "tests/test_metrics.py::TestMetricsRecursive::test", "tests/test_metrics.py::TestMetricsCLI::test_binary", "tests/test_metrics.py::TestMetricsReproCLI::test_dir", "tests/test_metrics.py::TestMetrics::test_xpath_is_none", "tests/test_metrics.py::TestMetrics::test_show", "tests/test_metrics.py::TestMetricsCLI::test_wrong_type_add", "tests/test_metrics.py::TestMetricsCLI::test_xpath_all_with_header", "tests/test_metrics.py::TestMetricsReproCLI::test_binary", "tests/test_metrics.py::TestNoMetrics::test", "tests/test_metrics.py::TestMetricsCLI::test_formatted_output", "tests/test_metrics.py::TestMetricsCLI::test_show", "tests/test_metrics.py::TestMetricsCLI::test_xpath_all", "tests/test_metrics.py::TestMetricsCLI::test_xpath_all_rows", "tests/test_metrics.py::TestMetrics::test_xpath_is_empty", "tests/test_metrics.py::TestMetrics::test_xpath_all_columns", "tests/test_metrics.py::TestMetrics::test_formatted_output", "tests/test_metrics.py::TestMetricsCLI::test_unknown_type_ignored", "tests/test_metrics.py::TestMetrics::test_xpath_all", "tests/test_metrics.py::TestMetrics::test_unknown_type_ignored", "tests/test_metrics.py::TestMetricsReproCLI::test", "tests/test_metrics.py::TestCachedMetrics::test_add", "tests/test_metrics.py::TestMetrics::test_xpath_all_rows", "tests/test_metrics.py::TestMetrics::test_xpath_all_with_header", "tests/test_metrics.py::TestCachedMetrics::test_run", "tests/test_metrics.py::TestMetrics::test_type_case_normalized", "tests/test_metrics.py::TestMetricsCLI::test_wrong_type_show", "tests/test_metrics.py::TestMetricsCLI::test_type_case_normalized", "tests/test_metrics.py::TestMetricsCLI::test_dir", "tests/test_metrics.py::TestMetricsCLI::test_xpath_is_empty", "tests/test_metrics.py::TestMetricsCLI::test_wrong_type_modify", "tests/test_metrics.py::TestMetricsCLI::test", "tests/test_metrics.py::TestMetricsCLI::test_non_existing", "tests/test_metrics.py::TestMetricsCLI::test_xpath_all_columns"], "base_commit": "b3addbd2832ffda1a4ec9a9ac3958ed9a43437dd", "created_at": "2019-03-30T11:47:50Z", "hints_text": "", "instance_id": "iterative__dvc-1809", "patch": "diff --git a/dvc/command/metrics.py b/dvc/command/metrics.py\n--- a/dvc/command/metrics.py\n+++ b/dvc/command/metrics.py\n@@ -107,7 +107,13 @@ def add_parser(subparsers, parent_parser):\n         \"path\", nargs=\"?\", help=\"Path to a metric file or a directory.\"\n     )\n     metrics_show_parser.add_argument(\n-        \"-t\", \"--type\", help=\"Type of metrics (raw/json/tsv/htsv/csv/hcsv).\"\n+        \"-t\",\n+        \"--type\",\n+        help=(\n+            \"Type of metrics (json/tsv/htsv/csv/hcsv). \"\n+            \"It can be detected by the file extension automatically. \"\n+            \"Unsupported types will be treated as raw.\"\n+        ),\n     )\n     metrics_show_parser.add_argument(\n         \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"\ndiff --git a/dvc/repo/metrics/show.py b/dvc/repo/metrics/show.py\n--- a/dvc/repo/metrics/show.py\n+++ b/dvc/repo/metrics/show.py\n@@ -129,6 +129,8 @@ def _read_metrics(self, metrics, branch):\n     res = {}\n     for out, typ, xpath in metrics:\n         assert out.scheme == \"local\"\n+        if not typ:\n+            typ = os.path.splitext(out.path.lower())[1].replace(\".\", \"\")\n         if out.use_cache:\n             metric = _read_metrics_filesystem(\n                 self.cache.local.get(out.checksum),\n", "problem_statement": "metrics: automatic type detection\nE.g. if we see that output has `.json` suffix, we could safely assume that it is `--type json` without explicitly specifying it.\n", "repo": "iterative/dvc", "test_patch": "diff --git a/tests/test_metrics.py b/tests/test_metrics.py\n--- a/tests/test_metrics.py\n+++ b/tests/test_metrics.py\n@@ -541,3 +541,58 @@ def test_add(self):\n \n     def test_run(self):\n         self._test_metrics(self._do_run)\n+\n+\n+class TestMetricsType(TestDvc):\n+    branches = [\"foo\", \"bar\", \"baz\"]\n+    files = [\n+        \"metric\",\n+        \"metric.txt\",\n+        \"metric.json\",\n+        \"metric.tsv\",\n+        \"metric.htsv\",\n+        \"metric.csv\",\n+        \"metric.hcsv\",\n+    ]\n+    xpaths = [None, None, \"branch\", \"0,0\", \"0,branch\", \"0,0\", \"0,branch\"]\n+\n+    def setUp(self):\n+        super(TestMetricsType, self).setUp()\n+        self.dvc.scm.commit(\"init\")\n+\n+        for branch in self.branches:\n+            self.dvc.scm.checkout(branch, create_new=True)\n+            with open(\"metric\", \"w+\") as fd:\n+                fd.write(branch)\n+            with open(\"metric.txt\", \"w+\") as fd:\n+                fd.write(branch)\n+            with open(\"metric.json\", \"w+\") as fd:\n+                json.dump({\"branch\": branch}, fd)\n+            with open(\"metric.csv\", \"w+\") as fd:\n+                fd.write(branch)\n+            with open(\"metric.hcsv\", \"w+\") as fd:\n+                fd.write(\"branch\\n\")\n+                fd.write(branch)\n+            with open(\"metric.tsv\", \"w+\") as fd:\n+                fd.write(branch)\n+            with open(\"metric.htsv\", \"w+\") as fd:\n+                fd.write(\"branch\\n\")\n+                fd.write(branch)\n+            self.dvc.run(metrics_no_cache=self.files, overwrite=True)\n+            self.dvc.scm.add(self.files + [\"metric.dvc\"])\n+            self.dvc.scm.commit(\"metric\")\n+\n+        self.dvc.scm.checkout(\"master\")\n+\n+    def test_show(self):\n+        for file_name, xpath in zip(self.files, self.xpaths):\n+            self._do_show(file_name, xpath)\n+\n+    def _do_show(self, file_name, xpath):\n+        ret = self.dvc.metrics.show(file_name, xpath=xpath, all_branches=True)\n+        self.assertEqual(len(ret), 3)\n+        for branch in self.branches:\n+            if isinstance(ret[branch][file_name], list):\n+                self.assertSequenceEqual(ret[branch][file_name], [branch])\n+            else:\n+                self.assertSequenceEqual(ret[branch][file_name], branch)\n", "version": "0.33"}
parsed_commit_content: {"file_diffs":[{"old_file_content":"from __future__ import unicode_literals\n\nimport argparse\n\nimport dvc.logger as logger\nfrom dvc.exceptions import DvcException\nfrom dvc.command.base import CmdBase, fix_subparsers, append_doc_link\n\n\ndef show_metrics(metrics, all_branches=False, all_tags=False):\n    \"\"\"\n    Args:\n        metrics (list): Where each element is either a `list`\n            if an xpath was specified, otherwise a `str`\n    \"\"\"\n    for branch, val in metrics.items():\n        if all_branches or all_tags:\n            logger.info(\"{branch}:\".format(branch=branch))\n\n        for fname, metric in val.items():\n            lines = metric if type(metric) is list else metric.splitlines()\n\n            if len(lines) > 1:\n                logger.info(\"\\t{fname}:\".format(fname=fname))\n\n                for line in lines:\n                    logger.info(\"\\t\\t{content}\".format(content=line))\n\n            else:\n                logger.info(\"\\t{}: {}\".format(fname, metric))\n\n\nclass CmdMetricsShow(CmdBase):\n    def run(self):\n        typ = self.args.type\n        xpath = self.args.xpath\n        try:\n            metrics = self.repo.metrics.show(\n                self.args.path,\n                typ=typ,\n                xpath=xpath,\n                all_branches=self.args.all_branches,\n                all_tags=self.args.all_tags,\n                recursive=self.args.recursive,\n            )\n\n            show_metrics(metrics, self.args.all_branches, self.args.all_tags)\n        except DvcException:\n            logger.error(\"failed to show metrics\")\n            return 1\n\n        return 0\n\n\nclass CmdMetricsModify(CmdBase):\n    def run(self):\n        try:\n            self.repo.metrics.modify(\n                self.args.path, typ=self.args.type, xpath=self.args.xpath\n            )\n        except DvcException:\n            logger.error(\"failed to modify metric file settings\")\n            return 1\n\n        return 0\n\n\nclass CmdMetricsAdd(CmdBase):\n    def run(self):\n        try:\n            self.repo.metrics.add(\n                self.args.path, self.args.type, self.args.xpath\n            )\n        except DvcException:\n            msg = \"failed to add metric file '{}'\".format(self.args.path)\n            logger.error(msg)\n            return 1\n\n        return 0\n\n\nclass CmdMetricsRemove(CmdBase):\n    def run(self):\n        try:\n            self.repo.metrics.remove(self.args.path)\n        except DvcException:\n            msg = \"failed to remove metric file '{}'\".format(self.args.path)\n            logger.error(msg)\n            return 1\n\n        return 0\n\n\ndef add_parser(subparsers, parent_parser):\n    METRICS_HELP = \"Commands to add, manage, collect and display metrics.\"\n\n    metrics_parser = subparsers.add_parser(\n        \"metrics\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_HELP, \"metrics\"),\n        help=METRICS_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n\n    metrics_subparsers = metrics_parser.add_subparsers(\n        dest=\"cmd\",\n        help=\"Use dvc metrics CMD --help to display command-specific help.\",\n    )\n\n    fix_subparsers(metrics_subparsers)\n\n    METRICS_SHOW_HELP = \"Output metric values.\"\n    metrics_show_parser = metrics_subparsers.add_parser(\n        \"show\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_SHOW_HELP, \"metrics-show\"),\n        help=METRICS_SHOW_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_show_parser.add_argument(\n        \"path\", nargs=\"?\", help=\"Path to a metric file or a directory.\"\n    )\n    metrics_show_parser.add_argument(\n        \"-t\", \"--type\", help=\"Type of metrics (raw/json/tsv/htsv/csv/hcsv).\"\n    )\n    metrics_show_parser.add_argument(\n        \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"\n    )\n    metrics_show_parser.add_argument(\n        \"-a\",\n        \"--all-branches\",\n        action=\"store_true\",\n        default=False,\n        help=\"Show metrics for all branches.\",\n    )\n    metrics_show_parser.add_argument(\n        \"-T\",\n        \"--all-tags\",\n        action=\"store_true\",\n        default=False,\n        help=\"Show metrics for all tags.\",\n    )\n    metrics_show_parser.add_argument(\n        \"-R\",\n        \"--recursive\",\n        action=\"store_true\",\n        default=False,\n        help=(\n            \"If path is a directory, recursively search and process metric \"\n            \"files in path.\"\n        ),\n    )\n    metrics_show_parser.set_defaults(func=CmdMetricsShow)\n\n    METRICS_ADD_HELP = \"Tag file as a metric file.\"\n    metrics_add_parser = metrics_subparsers.add_parser(\n        \"add\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_ADD_HELP, \"metrics-add\"),\n        help=METRICS_ADD_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_add_parser.add_argument(\n        \"-t\", \"--type\", help=\"Type of metrics (raw/json/tsv/htsv/csv/hcsv).\"\n    )\n    metrics_add_parser.add_argument(\n        \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"\n    )\n    metrics_add_parser.add_argument(\"path\", help=\"Path to a metric file.\")\n    metrics_add_parser.set_defaults(func=CmdMetricsAdd)\n\n    METRICS_MODIFY_HELP = \"Modify metric file options.\"\n    metrics_modify_parser = metrics_subparsers.add_parser(\n        \"modify\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_MODIFY_HELP, \"metrics-modify\"),\n        help=METRICS_MODIFY_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_modify_parser.add_argument(\n        \"-t\", \"--type\", help=\"Type of metrics (raw/json/tsv/htsv/csv/hcsv).\"\n    )\n    metrics_modify_parser.add_argument(\n        \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"\n    )\n    metrics_modify_parser.add_argument(\"path\", help=\"Path to a metric file.\")\n    metrics_modify_parser.set_defaults(func=CmdMetricsModify)\n\n    METRICS_REMOVE_HELP = \"Remove files's metric tag.\"\n    metrics_remove_parser = metrics_subparsers.add_parser(\n        \"remove\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_REMOVE_HELP, \"metrics-remove\"),\n        help=METRICS_REMOVE_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_remove_parser.add_argument(\"path\", help=\"Path to a metric file.\")\n    metrics_remove_parser.set_defaults(func=CmdMetricsRemove)\n","new_file_content":"from __future__ import unicode_literals\n\nimport argparse\n\nimport dvc.logger as logger\nfrom dvc.exceptions import DvcException\nfrom dvc.command.base import CmdBase, fix_subparsers, append_doc_link\n\n\ndef show_metrics(metrics, all_branches=False, all_tags=False):\n    for branch, val in metrics.items():\n        if all_branches or all_tags:\n            logger.info(\"{}:\".format(branch))\n\n        for fname, metric in val.items():\n            logger.info(\"\\t{}: {}\".format(fname, metric))\n\n\nclass CmdMetricsShow(CmdBase):\n    def run(self):\n        typ = self.args.type\n        xpath = self.args.xpath\n        try:\n            metrics = self.repo.metrics.show(\n                self.args.path,\n                typ=typ,\n                xpath=xpath,\n                all_branches=self.args.all_branches,\n                all_tags=self.args.all_tags,\n                recursive=self.args.recursive,\n            )\n\n            show_metrics(metrics, self.args.all_branches, self.args.all_tags)\n        except DvcException:\n            logger.error(\"failed to show metrics\")\n            return 1\n\n        return 0\n\n\nclass CmdMetricsModify(CmdBase):\n    def run(self):\n        try:\n            self.repo.metrics.modify(\n                self.args.path, typ=self.args.type, xpath=self.args.xpath\n            )\n        except DvcException:\n            logger.error(\"failed to modify metric file settings\")\n            return 1\n\n        return 0\n\n\nclass CmdMetricsAdd(CmdBase):\n    def run(self):\n        try:\n            self.repo.metrics.add(\n                self.args.path, self.args.type, self.args.xpath\n            )\n        except DvcException:\n            msg = \"failed to add metric file '{}'\".format(self.args.path)\n            logger.error(msg)\n            return 1\n\n        return 0\n\n\nclass CmdMetricsRemove(CmdBase):\n    def run(self):\n        try:\n            self.repo.metrics.remove(self.args.path)\n        except DvcException:\n            msg = \"failed to remove metric file '{}'\".format(self.args.path)\n            logger.error(msg)\n            return 1\n\n        return 0\n\n\ndef add_parser(subparsers, parent_parser):\n    METRICS_HELP = \"Commands to add, manage, collect and display metrics.\"\n\n    metrics_parser = subparsers.add_parser(\n        \"metrics\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_HELP, \"metrics\"),\n        help=METRICS_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n\n    metrics_subparsers = metrics_parser.add_subparsers(\n        dest=\"cmd\",\n        help=\"Use dvc metrics CMD --help to display command-specific help.\",\n    )\n\n    fix_subparsers(metrics_subparsers)\n\n    METRICS_SHOW_HELP = \"Output metric values.\"\n    metrics_show_parser = metrics_subparsers.add_parser(\n        \"show\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_SHOW_HELP, \"metrics-show\"),\n        help=METRICS_SHOW_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_show_parser.add_argument(\n        \"path\", nargs=\"?\", help=\"Path to a metric file or a directory.\"\n    )\n    metrics_show_parser.add_argument(\n        \"-t\",\n        \"--type\",\n        help=(\n            \"Type of metrics (json/tsv/htsv/csv/hcsv). \"\n            \"It can be detected by the file extension automatically. \"\n            \"Unsupported types will be treated as raw.\"\n        ),\n    )\n    metrics_show_parser.add_argument(\n        \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"\n    )\n    metrics_show_parser.add_argument(\n        \"-a\",\n        \"--all-branches\",\n        action=\"store_true\",\n        default=False,\n        help=\"Show metrics for all branches.\",\n    )\n    metrics_show_parser.add_argument(\n        \"-T\",\n        \"--all-tags\",\n        action=\"store_true\",\n        default=False,\n        help=\"Show metrics for all tags.\",\n    )\n    metrics_show_parser.add_argument(\n        \"-R\",\n        \"--recursive\",\n        action=\"store_true\",\n        default=False,\n        help=(\n            \"If path is a directory, recursively search and process metric \"\n            \"files in path.\"\n        ),\n    )\n    metrics_show_parser.set_defaults(func=CmdMetricsShow)\n\n    METRICS_ADD_HELP = \"Tag file as a metric file.\"\n    metrics_add_parser = metrics_subparsers.add_parser(\n        \"add\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_ADD_HELP, \"metrics-add\"),\n        help=METRICS_ADD_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_add_parser.add_argument(\n        \"-t\", \"--type\", help=\"Type of metrics (raw/json/tsv/htsv/csv/hcsv).\"\n    )\n    metrics_add_parser.add_argument(\n        \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"\n    )\n    metrics_add_parser.add_argument(\"path\", help=\"Path to a metric file.\")\n    metrics_add_parser.set_defaults(func=CmdMetricsAdd)\n\n    METRICS_MODIFY_HELP = \"Modify metric file options.\"\n    metrics_modify_parser = metrics_subparsers.add_parser(\n        \"modify\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_MODIFY_HELP, \"metrics-modify\"),\n        help=METRICS_MODIFY_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_modify_parser.add_argument(\n        \"-t\", \"--type\", help=\"Type of metrics (raw/json/tsv/htsv/csv/hcsv).\"\n    )\n    metrics_modify_parser.add_argument(\n        \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"\n    )\n    metrics_modify_parser.add_argument(\"path\", help=\"Path to a metric file.\")\n    metrics_modify_parser.set_defaults(func=CmdMetricsModify)\n\n    METRICS_REMOVE_HELP = \"Remove files's metric tag.\"\n    metrics_remove_parser = metrics_subparsers.add_parser(\n        \"remove\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_REMOVE_HELP, \"metrics-remove\"),\n        help=METRICS_REMOVE_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_remove_parser.add_argument(\"path\", help=\"Path to a metric file.\")\n    metrics_remove_parser.set_defaults(func=CmdMetricsRemove)\n","header":{"file":{"path":"dvc/command/metrics.py"},"misc_line":null},"index_line":null,"is_binary_file":false,"binary_line":null,"minus_file":{"path":"a/dvc/command/metrics.py"},"plus_file":{"path":"b/dvc/command/metrics.py"},"hunks":[{"descriptor":{"old_range":{"start":107,"length":7},"new_range":{"start":107,"length":13},"section":"def add_parser(subparsers, parent_parser):"},"line_group":{"all_lines":[{"content":"        \"path\", nargs=\"?\", help=\"Path to a metric file or a directory.\"","type":"context"},{"content":"    )","type":"context"},{"content":"    metrics_show_parser.add_argument(","type":"context"},{"content":"        \"-t\", \"--type\", help=\"Type of metrics (raw/json/tsv/htsv/csv/hcsv).\"","type":"deleted"},{"content":"        \"-t\",","type":"added"},{"content":"        \"--type\",","type":"added"},{"content":"        help=(","type":"added"},{"content":"            \"Type of metrics (json/tsv/htsv/csv/hcsv). \"","type":"added"},{"content":"            \"It can be detected by the file extension automatically. \"","type":"added"},{"content":"            \"Unsupported types will be treated as raw.\"","type":"added"},{"content":"        ),","type":"added"},{"content":"    )","type":"context"},{"content":"    metrics_show_parser.add_argument(","type":"context"},{"content":"        \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"","type":"context"}]},"modified_entities":[],"added_entities":[],"deleted_entities":[]}]},{"old_file_content":"from __future__ import unicode_literals\n\nimport os\nimport csv\nimport json\nfrom jsonpath_rw import parse\n\nimport dvc.logger as logger\nfrom dvc.exceptions import OutputNotFoundError, BadMetricError, NoMetricsError\nfrom dvc.utils.compat import builtin_str, open, StringIO, csv_reader\n\n\ndef _read_metric_json(fd, json_path):\n    parser = parse(json_path)\n    return [x.value for x in parser.find(json.load(fd))]\n\n\ndef _get_values(row):\n    if isinstance(row, dict):\n        return list(row.values())\n    else:\n        return row\n\n\ndef _do_read_metric_xsv(reader, row, col):\n    if col is not None and row is not None:\n        return [reader[row][col]]\n    elif col is not None:\n        return [r[col] for r in reader]\n    elif row is not None:\n        return _get_values(reader[row])\n    return [_get_values(r) for r in reader]\n\n\ndef _read_metric_hxsv(fd, hxsv_path, delimiter):\n    indices = hxsv_path.split(\",\")\n    row = indices[0]\n    row = int(row) if row else None\n    col = indices[1] if len(indices) > 1 and indices[1] else None\n    reader = list(csv.DictReader(fd, delimiter=builtin_str(delimiter)))\n    return _do_read_metric_xsv(reader, row, col)\n\n\ndef _read_metric_xsv(fd, xsv_path, delimiter):\n    indices = xsv_path.split(\",\")\n    row = indices[0]\n    row = int(row) if row else None\n    col = int(indices[1]) if len(indices) > 1 and indices[1] else None\n    reader = list(csv.reader(fd, delimiter=builtin_str(delimiter)))\n    return _do_read_metric_xsv(reader, row, col)\n\n\ndef _read_typed_metric(typ, xpath, fd):\n    if typ == \"json\":\n        ret = _read_metric_json(fd, xpath)\n    elif typ == \"csv\":\n        ret = _read_metric_xsv(fd, xpath, \",\")\n    elif typ == \"tsv\":\n        ret = _read_metric_xsv(fd, xpath, \"\\t\")\n    elif typ == \"hcsv\":\n        ret = _read_metric_hxsv(fd, xpath, \",\")\n    elif typ == \"htsv\":\n        ret = _read_metric_hxsv(fd, xpath, \"\\t\")\n    else:\n        ret = fd.read().strip()\n    return ret\n\n\ndef _format_csv(content, delimiter):\n    \"\"\"Format delimited text to have same column width.\n\n    Args:\n        content (str): The content of a metric.\n        delimiter (str): Value separator\n\n    Returns:\n        str: Formatted content.\n\n    Example:\n\n        >>> content = (\n            \"value_mse,deviation_mse,data_set\\n\"\n            \"0.421601,0.173461,train\\n\"\n            \"0.67528,0.289545,testing\\n\"\n            \"0.671502,0.297848,validation\\n\"\n        )\n        >>> _format_csv(content, \",\")\n\n        \"value_mse  deviation_mse   data_set\\n\"\n        \"0.421601   0.173461        train\\n\"\n        \"0.67528    0.289545        testing\\n\"\n        \"0.671502   0.297848        validation\\n\"\n    \"\"\"\n    reader = csv_reader(StringIO(content), delimiter=builtin_str(delimiter))\n    rows = [row for row in reader]\n    max_widths = [max(map(len, column)) for column in zip(*rows)]\n\n    lines = [\n        \" \".join(\n            \"{entry:{width}}\".format(entry=entry, width=width + 2)\n            for entry, width in zip(row, max_widths)\n        )\n        for row in rows\n    ]\n\n    return \"\\n\".join(lines)\n\n\ndef _format_output(content, typ):\n    \"\"\"Tabularize the content according to its type.\n\n    Args:\n        content (str): The content of a metric.\n        typ (str): The type of metric -- (raw|json|tsv|htsv|csv|hcsv).\n\n    Returns:\n        str: Content in a raw or tabular format.\n    \"\"\"\n\n    if \"csv\" in str(typ):\n        return _format_csv(content, delimiter=\",\")\n\n    if \"tsv\" in str(typ):\n        return _format_csv(content, delimiter=\"\\t\")\n\n    return content\n\n\ndef _read_metric(fd, typ=None, xpath=None, rel_path=None, branch=None):\n    typ = typ.lower().strip() if typ else typ\n    try:\n        if xpath:\n            return _read_typed_metric(typ, xpath.strip(), fd)\n        else:\n            return _format_output(fd.read().strip(), typ)\n    # Json path library has to be replaced or wrapped in\n    # order to fix this too broad except clause.\n    except Exception:\n        logger.warning(\n            \"unable to read metric in '{}' in branch '{}'\".format(\n                rel_path, branch\n            ),\n            parse_exception=True,\n        )\n        return None\n\n\ndef _collect_metrics(self, path, recursive, typ, xpath, branch):\n    \"\"\"Gather all the metric outputs.\n\n    Args:\n        path (str): Path to a metric file or a directory.\n        recursive (bool): If path is a directory, do a recursive search for\n            metrics on the given path.\n        typ (str): The type of metric to search for, could be one of the\n            following (raw|json|tsv|htsv|csv|hcsv).\n        xpath (str): Path to search for.\n        branch (str): Branch to look up for metrics.\n\n    Returns:\n        list(tuple): (output, typ, xpath)\n            - output:\n            - typ:\n            - xpath:\n    \"\"\"\n    outs = [out for stage in self.stages() for out in stage.outs]\n\n    if path:\n        try:\n            outs = self.find_outs_by_path(path, outs=outs, recursive=recursive)\n        except OutputNotFoundError:\n            logger.debug(\n                \"stage file not for found for '{}' in branch '{}'\".format(\n                    path, branch\n                )\n            )\n            return []\n\n    res = []\n    for o in outs:\n        if not o.metric:\n            continue\n\n        if not typ and isinstance(o.metric, dict):\n            t = o.metric.get(o.PARAM_METRIC_TYPE, typ)\n            x = o.metric.get(o.PARAM_METRIC_XPATH, xpath)\n        else:\n            t = typ\n            x = xpath\n\n        res.append((o, t, x))\n\n    return res\n\n\ndef _read_metrics_filesystem(path, typ, xpath, rel_path, branch):\n    if not os.path.exists(path):\n        return None\n    with open(path, \"r\") as fd:\n        return _read_metric(\n            fd, typ=typ, xpath=xpath, rel_path=rel_path, branch=branch\n        )\n\n\ndef _read_metrics(self, metrics, branch):\n    \"\"\"Read the content of each metric file and format it.\n\n    Args:\n        metrics (list): List of metric touples\n        branch (str): Branch to look up for metrics.\n\n    Returns:\n        A dict mapping keys with metrics path name and content.\n        For example:\n\n        {'metric.csv': (\"value_mse  deviation_mse   data_set\\n\"\n                        \"0.421601   0.173461        train\\n\"\n                        \"0.67528    0.289545        testing\\n\"\n                        \"0.671502   0.297848        validation\\n\")}\n    \"\"\"\n    res = {}\n    for out, typ, xpath in metrics:\n        assert out.scheme == \"local\"\n        if out.use_cache:\n            metric = _read_metrics_filesystem(\n                self.cache.local.get(out.checksum),\n                typ=typ,\n                xpath=xpath,\n                rel_path=out.rel_path,\n                branch=branch,\n            )\n        else:\n            fd = self.tree.open(out.path)\n            metric = _read_metric(\n                fd, typ=typ, xpath=xpath, rel_path=out.rel_path, branch=branch\n            )\n\n        if not metric:\n            continue\n\n        res[out.rel_path] = metric\n\n    return res\n\n\ndef show(\n    self,\n    path=None,\n    typ=None,\n    xpath=None,\n    all_branches=False,\n    all_tags=False,\n    recursive=False,\n):\n    res = {}\n\n    for branch in self.brancher(all_branches=all_branches, all_tags=all_tags):\n        entries = _collect_metrics(self, path, recursive, typ, xpath, branch)\n        metrics = _read_metrics(self, entries, branch)\n        if metrics:\n            res[branch] = metrics\n\n    if not res:\n        if path:\n            raise BadMetricError(path)\n        raise NoMetricsError()\n\n    return res\n","new_file_content":"from __future__ import unicode_literals\n\nimport os\nimport csv\nimport json\nfrom jsonpath_rw import parse\n\nimport dvc.logger as logger\nfrom dvc.exceptions import OutputNotFoundError, BadMetricError, NoMetricsError\nfrom dvc.utils.compat import builtin_str, open\n\n\ndef _read_metric_json(fd, json_path):\n    parser = parse(json_path)\n    return [x.value for x in parser.find(json.load(fd))]\n\n\ndef _get_values(row):\n    if isinstance(row, dict):\n        return list(row.values())\n    else:\n        return row\n\n\ndef _do_read_metric_xsv(reader, row, col):\n    if col is not None and row is not None:\n        return [reader[row][col]]\n    elif col is not None:\n        return [r[col] for r in reader]\n    elif row is not None:\n        return _get_values(reader[row])\n    return [_get_values(r) for r in reader]\n\n\ndef _read_metric_hxsv(fd, hxsv_path, delimiter):\n    indices = hxsv_path.split(\",\")\n    row = indices[0]\n    row = int(row) if row else None\n    col = indices[1] if len(indices) > 1 and indices[1] else None\n    reader = list(csv.DictReader(fd, delimiter=builtin_str(delimiter)))\n    return _do_read_metric_xsv(reader, row, col)\n\n\ndef _read_metric_xsv(fd, xsv_path, delimiter):\n    indices = xsv_path.split(\",\")\n    row = indices[0]\n    row = int(row) if row else None\n    col = int(indices[1]) if len(indices) > 1 and indices[1] else None\n    reader = list(csv.reader(fd, delimiter=builtin_str(delimiter)))\n    return _do_read_metric_xsv(reader, row, col)\n\n\ndef _read_typed_metric(typ, xpath, fd):\n    if typ == \"json\":\n        ret = _read_metric_json(fd, xpath)\n    elif typ == \"csv\":\n        ret = _read_metric_xsv(fd, xpath, \",\")\n    elif typ == \"tsv\":\n        ret = _read_metric_xsv(fd, xpath, \"\\t\")\n    elif typ == \"hcsv\":\n        ret = _read_metric_hxsv(fd, xpath, \",\")\n    elif typ == \"htsv\":\n        ret = _read_metric_hxsv(fd, xpath, \"\\t\")\n    else:\n        ret = fd.read().strip()\n    return ret\n\n\ndef _read_metric(fd, typ=None, xpath=None, rel_path=None, branch=None):\n    typ = typ.lower().strip() if typ else typ\n    try:\n        if xpath:\n            return _read_typed_metric(typ, xpath.strip(), fd)\n        else:\n            return fd.read().strip()\n    # Json path library has to be replaced or wrapped in\n    # order to fix this too broad except clause.\n    except Exception:\n        logger.warning(\n            \"unable to read metric in '{}' in branch '{}'\".format(\n                rel_path, branch\n            ),\n            parse_exception=True,\n        )\n        return None\n\n\ndef _collect_metrics(self, path, recursive, typ, xpath, branch):\n    outs = [out for stage in self.stages() for out in stage.outs]\n\n    if path:\n        try:\n            outs = self.find_outs_by_path(path, outs=outs, recursive=recursive)\n        except OutputNotFoundError:\n            logger.debug(\n                \"stage file not for found for '{}' in branch '{}'\".format(\n                    path, branch\n                )\n            )\n            return []\n\n    res = []\n    for o in outs:\n        if not o.metric:\n            continue\n\n        if not typ and isinstance(o.metric, dict):\n            t = o.metric.get(o.PARAM_METRIC_TYPE, typ)\n            x = o.metric.get(o.PARAM_METRIC_XPATH, xpath)\n        else:\n            t = typ\n            x = xpath\n\n        res.append((o, t, x))\n\n    return res\n\n\ndef _read_metrics_filesystem(path, typ, xpath, rel_path, branch):\n    if not os.path.exists(path):\n        return None\n    with open(path, \"r\") as fd:\n        return _read_metric(\n            fd, typ=typ, xpath=xpath, rel_path=rel_path, branch=branch\n        )\n\n\ndef _read_metrics(self, metrics, branch):\n    res = {}\n    for out, typ, xpath in metrics:\n        assert out.scheme == \"local\"\n        if not typ:\n            typ = os.path.splitext(out.path.lower())[1].replace(\".\", \"\")\n        if out.use_cache:\n            metric = _read_metrics_filesystem(\n                self.cache.local.get(out.checksum),\n                typ=typ,\n                xpath=xpath,\n                rel_path=out.rel_path,\n                branch=branch,\n            )\n        else:\n            fd = self.tree.open(out.path)\n            metric = _read_metric(\n                fd, typ=typ, xpath=xpath, rel_path=out.rel_path, branch=branch\n            )\n\n        if not metric:\n            continue\n\n        res[out.rel_path] = metric\n\n    return res\n\n\ndef show(\n    self,\n    path=None,\n    typ=None,\n    xpath=None,\n    all_branches=False,\n    all_tags=False,\n    recursive=False,\n):\n    res = {}\n\n    for branch in self.brancher(all_branches=all_branches, all_tags=all_tags):\n        entries = _collect_metrics(self, path, recursive, typ, xpath, branch)\n        metrics = _read_metrics(self, entries, branch)\n        if metrics:\n            res[branch] = metrics\n\n    if not res:\n        if path:\n            raise BadMetricError(path)\n        raise NoMetricsError()\n\n    return res\n","header":{"file":{"path":"dvc/repo/metrics/show.py"},"misc_line":null},"index_line":null,"is_binary_file":false,"binary_line":null,"minus_file":{"path":"a/dvc/repo/metrics/show.py"},"plus_file":{"path":"b/dvc/repo/metrics/show.py"},"hunks":[{"descriptor":{"old_range":{"start":129,"length":6},"new_range":{"start":129,"length":8},"section":"def _read_metrics(self, metrics, branch):"},"line_group":{"all_lines":[{"content":"    res = {}","type":"context"},{"content":"    for out, typ, xpath in metrics:","type":"context"},{"content":"        assert out.scheme == \"local\"","type":"context"},{"content":"        if not typ:","type":"added"},{"content":"            typ = os.path.splitext(out.path.lower())[1].replace(\".\", \"\")","type":"added"},{"content":"        if out.use_cache:","type":"context"},{"content":"            metric = _read_metrics_filesystem(","type":"context"},{"content":"                self.cache.local.get(out.checksum),","type":"context"},{"content":"","type":"context"}]},"modified_entities":[],"added_entities":[],"deleted_entities":[]}]}],"old_commit_hash":"b3addbd2832ffda1a4ec9a9ac3958ed9a43437dd","new_commit_hash":"5d89701370d53b89f107418167fff84dd883a223","commit_message":"metrics: add tests","commit_date":"2019-04-01T00:26:43+02:00","metadata":{}}
problem_statement: metrics: automatic type detection
  E.g. if we see that output has `.json` suffix, we could safely assume that it is `--type json` without explicitly specifying it.
  
patch: diff --git a/dvc/command/metrics.py b/dvc/command/metrics.py
  --- a/dvc/command/metrics.py
  +++ b/dvc/command/metrics.py
  @@ -107,7 +107,13 @@ def add_parser(subparsers, parent_parser):
           "path", nargs="?", help="Path to a metric file or a directory."
       )
       metrics_show_parser.add_argument(
  -        "-t", "--type", help="Type of metrics (raw/json/tsv/htsv/csv/hcsv)."
  +        "-t",
  +        "--type",
  +        help=(
  +            "Type of metrics (json/tsv/htsv/csv/hcsv). "
  +            "It can be detected by the file extension automatically. "
  +            "Unsupported types will be treated as raw."
  +        ),
       )
       metrics_show_parser.add_argument(
           "-x", "--xpath", help="json/tsv/htsv/csv/hcsv path."
  diff --git a/dvc/repo/metrics/show.py b/dvc/repo/metrics/show.py
  --- a/dvc/repo/metrics/show.py
  +++ b/dvc/repo/metrics/show.py
  @@ -129,6 +129,8 @@ def _read_metrics(self, metrics, branch):
       res = {}
       for out, typ, xpath in metrics:
           assert out.scheme == "local"
  +        if not typ:
  +            typ = os.path.splitext(out.path.lower())[1].replace(".", "")
           if out.use_cache:
               metric = _read_metrics_filesystem(
                   self.cache.local.get(out.checksum),
   
  
file_context: {"dvc/command/metrics.py": "from __future__ import unicode_literals\n\nimport argparse\n\nimport dvc.logger as logger\nfrom dvc.exceptions import DvcException\nfrom dvc.command.base import CmdBase, fix_subparsers, append_doc_link\n\n\ndef show_metrics(metrics, all_branches=False, all_tags=False):\n    \"\"\"\n    Args:\n        metrics (list): Where each element is either a `list`\n            if an xpath was specified, otherwise a `str`\n    \"\"\"\n    for branch, val in metrics.items():\n        if all_branches or all_tags:\n            logger.info(\"{branch}:\".format(branch=branch))\n\n        for fname, metric in val.items():\n            lines = metric if type(metric) is list else metric.splitlines()\n\n            if len(lines) > 1:\n                logger.info(\"\\t{fname}:\".format(fname=fname))\n\n                for line in lines:\n                    logger.info(\"\\t\\t{content}\".format(content=line))\n\n            else:\n                logger.info(\"\\t{}: {}\".format(fname, metric))\n\n\nclass CmdMetricsShow(CmdBase):\n    def run(self):\n        typ = self.args.type\n        xpath = self.args.xpath\n        try:\n            metrics = self.repo.metrics.show(\n                self.args.path,\n                typ=typ,\n                xpath=xpath,\n                all_branches=self.args.all_branches,\n                all_tags=self.args.all_tags,\n                recursive=self.args.recursive,\n            )\n\n            show_metrics(metrics, self.args.all_branches, self.args.all_tags)\n        except DvcException:\n            logger.error(\"failed to show metrics\")\n            return 1\n\n        return 0\n\n\nclass CmdMetricsModify(CmdBase):\n    def run(self):\n        try:\n            self.repo.metrics.modify(\n                self.args.path, typ=self.args.type, xpath=self.args.xpath\n            )\n        except DvcException:\n            logger.error(\"failed to modify metric file settings\")\n            return 1\n\n        return 0\n\n\nclass CmdMetricsAdd(CmdBase):\n    def run(self):\n        try:\n            self.repo.metrics.add(\n                self.args.path, self.args.type, self.args.xpath\n            )\n        except DvcException:\n            msg = \"failed to add metric file '{}'\".format(self.args.path)\n            logger.error(msg)\n            return 1\n\n        return 0\n\n\nclass CmdMetricsRemove(CmdBase):\n    def run(self):\n        try:\n            self.repo.metrics.remove(self.args.path)\n        except DvcException:\n            msg = \"failed to remove metric file '{}'\".format(self.args.path)\n            logger.error(msg)\n            return 1\n\n        return 0\n\n\ndef add_parser(subparsers, parent_parser):\n    METRICS_HELP = \"Commands to add, manage, collect and display metrics.\"\n\n    metrics_parser = subparsers.add_parser(\n        \"metrics\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_HELP, \"metrics\"),\n        help=METRICS_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n\n    metrics_subparsers = metrics_parser.add_subparsers(\n        dest=\"cmd\",\n        help=\"Use dvc metrics CMD --help to display command-specific help.\",\n    )\n\n    fix_subparsers(metrics_subparsers)\n\n    METRICS_SHOW_HELP = \"Output metric values.\"\n    metrics_show_parser = metrics_subparsers.add_parser(\n        \"show\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_SHOW_HELP, \"metrics-show\"),\n        help=METRICS_SHOW_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_show_parser.add_argument(\n        \"path\", nargs=\"?\", help=\"Path to a metric file or a directory.\"\n    )\n    metrics_show_parser.add_argument(\n        \"-t\", \"--type\", help=\"Type of metrics (raw/json/tsv/htsv/csv/hcsv).\"\n    )\n    metrics_show_parser.add_argument(\n        \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"\n    )\n    metrics_show_parser.add_argument(\n        \"-a\",\n        \"--all-branches\",\n        action=\"store_true\",\n        default=False,\n        help=\"Show metrics for all branches.\",\n    )\n    metrics_show_parser.add_argument(\n        \"-T\",\n        \"--all-tags\",\n        action=\"store_true\",\n        default=False,\n        help=\"Show metrics for all tags.\",\n    )\n    metrics_show_parser.add_argument(\n        \"-R\",\n        \"--recursive\",\n        action=\"store_true\",\n        default=False,\n        help=(\n            \"If path is a directory, recursively search and process metric \"\n            \"files in path.\"\n        ),\n    )\n    metrics_show_parser.set_defaults(func=CmdMetricsShow)\n\n    METRICS_ADD_HELP = \"Tag file as a metric file.\"\n    metrics_add_parser = metrics_subparsers.add_parser(\n        \"add\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_ADD_HELP, \"metrics-add\"),\n        help=METRICS_ADD_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_add_parser.add_argument(\n        \"-t\", \"--type\", help=\"Type of metrics (raw/json/tsv/htsv/csv/hcsv).\"\n    )\n    metrics_add_parser.add_argument(\n        \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"\n    )\n    metrics_add_parser.add_argument(\"path\", help=\"Path to a metric file.\")\n    metrics_add_parser.set_defaults(func=CmdMetricsAdd)\n\n    METRICS_MODIFY_HELP = \"Modify metric file options.\"\n    metrics_modify_parser = metrics_subparsers.add_parser(\n        \"modify\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_MODIFY_HELP, \"metrics-modify\"),\n        help=METRICS_MODIFY_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_modify_parser.add_argument(\n        \"-t\", \"--type\", help=\"Type of metrics (raw/json/tsv/htsv/csv/hcsv).\"\n    )\n    metrics_modify_parser.add_argument(\n        \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"\n    )\n    metrics_modify_parser.add_argument(\"path\", help=\"Path to a metric file.\")\n    metrics_modify_parser.set_defaults(func=CmdMetricsModify)\n\n    METRICS_REMOVE_HELP = \"Remove files's metric tag.\"\n    metrics_remove_parser = metrics_subparsers.add_parser(\n        \"remove\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_REMOVE_HELP, \"metrics-remove\"),\n        help=METRICS_REMOVE_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_remove_parser.add_argument(\"path\", help=\"Path to a metric file.\")\n    metrics_remove_parser.set_defaults(func=CmdMetricsRemove)\n", "dvc/repo/metrics/show.py": "from __future__ import unicode_literals\n\nimport os\nimport csv\nimport json\nfrom jsonpath_rw import parse\n\nimport dvc.logger as logger\nfrom dvc.exceptions import OutputNotFoundError, BadMetricError, NoMetricsError\nfrom dvc.utils.compat import builtin_str, open, StringIO, csv_reader\n\n\ndef _read_metric_json(fd, json_path):\n    parser = parse(json_path)\n    return [x.value for x in parser.find(json.load(fd))]\n\n\ndef _get_values(row):\n    if isinstance(row, dict):\n        return list(row.values())\n    else:\n        return row\n\n\ndef _do_read_metric_xsv(reader, row, col):\n    if col is not None and row is not None:\n        return [reader[row][col]]\n    elif col is not None:\n        return [r[col] for r in reader]\n    elif row is not None:\n        return _get_values(reader[row])\n    return [_get_values(r) for r in reader]\n\n\ndef _read_metric_hxsv(fd, hxsv_path, delimiter):\n    indices = hxsv_path.split(\",\")\n    row = indices[0]\n    row = int(row) if row else None\n    col = indices[1] if len(indices) > 1 and indices[1] else None\n    reader = list(csv.DictReader(fd, delimiter=builtin_str(delimiter)))\n    return _do_read_metric_xsv(reader, row, col)\n\n\ndef _read_metric_xsv(fd, xsv_path, delimiter):\n    indices = xsv_path.split(\",\")\n    row = indices[0]\n    row = int(row) if row else None\n    col = int(indices[1]) if len(indices) > 1 and indices[1] else None\n    reader = list(csv.reader(fd, delimiter=builtin_str(delimiter)))\n    return _do_read_metric_xsv(reader, row, col)\n\n\ndef _read_typed_metric(typ, xpath, fd):\n    if typ == \"json\":\n        ret = _read_metric_json(fd, xpath)\n    elif typ == \"csv\":\n        ret = _read_metric_xsv(fd, xpath, \",\")\n    elif typ == \"tsv\":\n        ret = _read_metric_xsv(fd, xpath, \"\\t\")\n    elif typ == \"hcsv\":\n        ret = _read_metric_hxsv(fd, xpath, \",\")\n    elif typ == \"htsv\":\n        ret = _read_metric_hxsv(fd, xpath, \"\\t\")\n    else:\n        ret = fd.read().strip()\n    return ret\n\n\ndef _format_csv(content, delimiter):\n    \"\"\"Format delimited text to have same column width.\n\n    Args:\n        content (str): The content of a metric.\n        delimiter (str): Value separator\n\n    Returns:\n        str: Formatted content.\n\n    Example:\n\n        >>> content = (\n            \"value_mse,deviation_mse,data_set\\n\"\n            \"0.421601,0.173461,train\\n\"\n            \"0.67528,0.289545,testing\\n\"\n            \"0.671502,0.297848,validation\\n\"\n        )\n        >>> _format_csv(content, \",\")\n\n        \"value_mse  deviation_mse   data_set\\n\"\n        \"0.421601   0.173461        train\\n\"\n        \"0.67528    0.289545        testing\\n\"\n        \"0.671502   0.297848        validation\\n\"\n    \"\"\"\n    reader = csv_reader(StringIO(content), delimiter=builtin_str(delimiter))\n    rows = [row for row in reader]\n    max_widths = [max(map(len, column)) for column in zip(*rows)]\n\n    lines = [\n        \" \".join(\n            \"{entry:{width}}\".format(entry=entry, width=width + 2)\n            for entry, width in zip(row, max_widths)\n        )\n        for row in rows\n    ]\n\n    return \"\\n\".join(lines)\n\n\ndef _format_output(content, typ):\n    \"\"\"Tabularize the content according to its type.\n\n    Args:\n        content (str): The content of a metric.\n        typ (str): The type of metric -- (raw|json|tsv|htsv|csv|hcsv).\n\n    Returns:\n        str: Content in a raw or tabular format.\n    \"\"\"\n\n    if \"csv\" in str(typ):\n        return _format_csv(content, delimiter=\",\")\n\n    if \"tsv\" in str(typ):\n        return _format_csv(content, delimiter=\"\\t\")\n\n    return content\n\n\ndef _read_metric(fd, typ=None, xpath=None, rel_path=None, branch=None):\n    typ = typ.lower().strip() if typ else typ\n    try:\n        if xpath:\n            return _read_typed_metric(typ, xpath.strip(), fd)\n        else:\n            return _format_output(fd.read().strip(), typ)\n    # Json path library has to be replaced or wrapped in\n    # order to fix this too broad except clause.\n    except Exception:\n        logger.warning(\n            \"unable to read metric in '{}' in branch '{}'\".format(\n                rel_path, branch\n            ),\n            parse_exception=True,\n        )\n        return None\n\n\ndef _collect_metrics(self, path, recursive, typ, xpath, branch):\n    \"\"\"Gather all the metric outputs.\n\n    Args:\n        path (str): Path to a metric file or a directory.\n        recursive (bool): If path is a directory, do a recursive search for\n            metrics on the given path.\n        typ (str): The type of metric to search for, could be one of the\n            following (raw|json|tsv|htsv|csv|hcsv).\n        xpath (str): Path to search for.\n        branch (str): Branch to look up for metrics.\n\n    Returns:\n        list(tuple): (output, typ, xpath)\n            - output:\n            - typ:\n            - xpath:\n    \"\"\"\n    outs = [out for stage in self.stages() for out in stage.outs]\n\n    if path:\n        try:\n            outs = self.find_outs_by_path(path, outs=outs, recursive=recursive)\n        except OutputNotFoundError:\n            logger.debug(\n                \"stage file not for found for '{}' in branch '{}'\".format(\n                    path, branch\n                )\n            )\n            return []\n\n    res = []\n    for o in outs:\n        if not o.metric:\n            continue\n\n        if not typ and isinstance(o.metric, dict):\n            t = o.metric.get(o.PARAM_METRIC_TYPE, typ)\n            x = o.metric.get(o.PARAM_METRIC_XPATH, xpath)\n        else:\n            t = typ\n            x = xpath\n\n        res.append((o, t, x))\n\n    return res\n\n\ndef _read_metrics_filesystem(path, typ, xpath, rel_path, branch):\n    if not os.path.exists(path):\n        return None\n    with open(path, \"r\") as fd:\n        return _read_metric(\n            fd, typ=typ, xpath=xpath, rel_path=rel_path, branch=branch\n        )\n\n\ndef _read_metrics(self, metrics, branch):\n    \"\"\"Read the content of each metric file and format it.\n\n    Args:\n        metrics (list): List of metric touples\n        branch (str): Branch to look up for metrics.\n\n    Returns:\n        A dict mapping keys with metrics path name and content.\n        For example:\n\n        {'metric.csv': (\"value_mse  deviation_mse   data_set\\n\"\n                        \"0.421601   0.173461        train\\n\"\n                        \"0.67528    0.289545        testing\\n\"\n                        \"0.671502   0.297848        validation\\n\")}\n    \"\"\"\n    res = {}\n    for out, typ, xpath in metrics:\n        assert out.scheme == \"local\"\n        if out.use_cache:\n            metric = _read_metrics_filesystem(\n                self.cache.local.get(out.checksum),\n                typ=typ,\n                xpath=xpath,\n                rel_path=out.rel_path,\n                branch=branch,\n            )\n        else:\n            fd = self.tree.open(out.path)\n            metric = _read_metric(\n                fd, typ=typ, xpath=xpath, rel_path=out.rel_path, branch=branch\n            )\n\n        if not metric:\n            continue\n\n        res[out.rel_path] = metric\n\n    return res\n\n\ndef show(\n    self,\n    path=None,\n    typ=None,\n    xpath=None,\n    all_branches=False,\n    all_tags=False,\n    recursive=False,\n):\n    res = {}\n\n    for branch in self.brancher(all_branches=all_branches, all_tags=all_tags):\n        entries = _collect_metrics(self, path, recursive, typ, xpath, branch)\n        metrics = _read_metrics(self, entries, branch)\n        if metrics:\n            res[branch] = metrics\n\n    if not res:\n        if path:\n            raise BadMetricError(path)\n        raise NoMetricsError()\n\n    return res\n"}
filelevel_patches: {"dvc/command/metrics.py": "@@ -107,7 +107,13 @@ def add_parser(subparsers, parent_parser):\n         \"path\", nargs=\"?\", help=\"Path to a metric file or a directory.\"\n     )\n     metrics_show_parser.add_argument(\n-        \"-t\", \"--type\", help=\"Type of metrics (raw/json/tsv/htsv/csv/hcsv).\"\n+        \"-t\",\n+        \"--type\",\n+        help=(\n+            \"Type of metrics (json/tsv/htsv/csv/hcsv). \"\n+            \"It can be detected by the file extension automatically. \"\n+            \"Unsupported types will be treated as raw.\"\n+        ),\n     )\n     metrics_show_parser.add_argument(\n         \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"", "dvc/repo/metrics/show.py": "@@ -129,6 +129,8 @@ def _read_metrics(self, metrics, branch):\n     res = {}\n     for out, typ, xpath in metrics:\n         assert out.scheme == \"local\"\n+        if not typ:\n+            typ = os.path.splitext(out.path.lower())[1].replace(\".\", \"\")\n         if out.use_cache:\n             metric = _read_metrics_filesystem(\n                 self.cache.local.get(out.checksum),"}
messages.content: 
  We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  metrics: automatic type detection
  E.g. if we see that output has `.json` suffix, we could safely assume that it is `--type json` without explicitly specifying it.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  
  --- BEGIN FILE ---
  ```
  ### dvc/command/metrics.py
  from __future__ import unicode_literals
  
  import argparse
  
  import dvc.logger as logger
  from dvc.exceptions import DvcException
  from dvc.command.base import CmdBase, fix_subparsers, append_doc_link
  
  
  def show_metrics(metrics, all_branches=False, all_tags=False):
      """
      Args:
          metrics (list): Where each element is either a `list`
              if an xpath was specified, otherwise a `str`
      """
      for branch, val in metrics.items():
          if all_branches or all_tags:
              logger.info("{branch}:".format(branch=branch))
  
          for fname, metric in val.items():
              lines = metric if type(metric) is list else metric.splitlines()
  
              if len(lines) > 1:
                  logger.info("\t{fname}:".format(fname=fname))
  
                  for line in lines:
                      logger.info("\t\t{content}".format(content=line))
  
              else:
                  logger.info("\t{}: {}".format(fname, metric))
  
  
  class CmdMetricsShow(CmdBase):
      def run(self):
          typ = self.args.type
          xpath = self.args.xpath
          try:
              metrics = self.repo.metrics.show(
                  self.args.path,
                  typ=typ,
                  xpath=xpath,
                  all_branches=self.args.all_branches,
                  all_tags=self.args.all_tags,
                  recursive=self.args.recursive,
              )
  
              show_metrics(metrics, self.args.all_branches, self.args.all_tags)
          except DvcException:
              logger.error("failed to show metrics")
              return 1
  
          return 0
  
  
  class CmdMetricsModify(CmdBase):
      def run(self):
          try:
              self.repo.metrics.modify(
                  self.args.path, typ=self.args.type, xpath=self.args.xpath
              )
          except DvcException:
              logger.error("failed to modify metric file settings")
              return 1
  
          return 0
  
  
  class CmdMetricsAdd(CmdBase):
      def run(self):
          try:
              self.repo.metrics.add(
                  self.args.path, self.args.type, self.args.xpath
              )
          except DvcException:
              msg = "failed to add metric file '{}'".format(self.args.path)
              logger.error(msg)
              return 1
  
          return 0
  
  
  class CmdMetricsRemove(CmdBase):
      def run(self):
          try:
              self.repo.metrics.remove(self.args.path)
          except DvcException:
              msg = "failed to remove metric file '{}'".format(self.args.path)
              logger.error(msg)
              return 1
  
          return 0
  
  
  def add_parser(subparsers, parent_parser):
      METRICS_HELP = "Commands to add, manage, collect and display metrics."
  
      metrics_parser = subparsers.add_parser(
          "metrics",
          parents=[parent_parser],
          description=append_doc_link(METRICS_HELP, "metrics"),
          help=METRICS_HELP,
          formatter_class=argparse.RawDescriptionHelpFormatter,
      )
  
      metrics_subparsers = metrics_parser.add_subparsers(
          dest="cmd",
          help="Use dvc metrics CMD --help to display command-specific help.",
      )
  
      fix_subparsers(metrics_subparsers)
  
      METRICS_SHOW_HELP = "Output metric values."
      metrics_show_parser = metrics_subparsers.add_parser(
          "show",
          parents=[parent_parser],
          description=append_doc_link(METRICS_SHOW_HELP, "metrics-show"),
          help=METRICS_SHOW_HELP,
          formatter_class=argparse.RawDescriptionHelpFormatter,
      )
      metrics_show_parser.add_argument(
          "path", nargs="?", help="Path to a metric file or a directory."
      )
      metrics_show_parser.add_argument(
          "-t", "--type", help="Type of metrics (raw/json/tsv/htsv/csv/hcsv)."
      )
      metrics_show_parser.add_argument(
          "-x", "--xpath", help="json/tsv/htsv/csv/hcsv path."
      )
      metrics_show_parser.add_argument(
          "-a",
          "--all-branches",
          action="store_true",
          default=False,
          help="Show metrics for all branches.",
      )
      metrics_show_parser.add_argument(
          "-T",
          "--all-tags",
          action="store_true",
          default=False,
          help="Show metrics for all tags.",
      )
      metrics_show_parser.add_argument(
          "-R",
          "--recursive",
          action="store_true",
          default=False,
          help=(
              "If path is a directory, recursively search and process metric "
              "files in path."
          ),
      )
      metrics_show_parser.set_defaults(func=CmdMetricsShow)
  
      METRICS_ADD_HELP = "Tag file as a metric file."
      metrics_add_parser = metrics_subparsers.add_parser(
          "add",
          parents=[parent_parser],
          description=append_doc_link(METRICS_ADD_HELP, "metrics-add"),
          help=METRICS_ADD_HELP,
          formatter_class=argparse.RawDescriptionHelpFormatter,
      )
      metrics_add_parser.add_argument(
          "-t", "--type", help="Type of metrics (raw/json/tsv/htsv/csv/hcsv)."
      )
      metrics_add_parser.add_argument(
          "-x", "--xpath", help="json/tsv/htsv/csv/hcsv path."
      )
      metrics_add_parser.add_argument("path", help="Path to a metric file.")
      metrics_add_parser.set_defaults(func=CmdMetricsAdd)
  
      METRICS_MODIFY_HELP = "Modify metric file options."
      metrics_modify_parser = metrics_subparsers.add_parser(
          "modify",
          parents=[parent_parser],
          description=append_doc_link(METRICS_MODIFY_HELP, "metrics-modify"),
          help=METRICS_MODIFY_HELP,
          formatter_class=argparse.RawDescriptionHelpFormatter,
      )
      metrics_modify_parser.add_argument(
          "-t", "--type", help="Type of metrics (raw/json/tsv/htsv/csv/hcsv)."
      )
      metrics_modify_parser.add_argument(
          "-x", "--xpath", help="json/tsv/htsv/csv/hcsv path."
      )
      metrics_modify_parser.add_argument("path", help="Path to a metric file.")
      metrics_modify_parser.set_defaults(func=CmdMetricsModify)
  
      METRICS_REMOVE_HELP = "Remove files's metric tag."
      metrics_remove_parser = metrics_subparsers.add_parser(
          "remove",
          parents=[parent_parser],
          description=append_doc_link(METRICS_REMOVE_HELP, "metrics-remove"),
          help=METRICS_REMOVE_HELP,
          formatter_class=argparse.RawDescriptionHelpFormatter,
      )
      metrics_remove_parser.add_argument("path", help="Path to a metric file.")
      metrics_remove_parser.set_defaults(func=CmdMetricsRemove)
  
  
  ### dvc/repo/metrics/show.py
  from __future__ import unicode_literals
  
  import os
  import csv
  import json
  from jsonpath_rw import parse
  
  import dvc.logger as logger
  from dvc.exceptions import OutputNotFoundError, BadMetricError, NoMetricsError
  from dvc.utils.compat import builtin_str, open, StringIO, csv_reader
  
  
  def _read_metric_json(fd, json_path):
      parser = parse(json_path)
      return [x.value for x in parser.find(json.load(fd))]
  
  
  def _get_values(row):
      if isinstance(row, dict):
          return list(row.values())
      else:
          return row
  
  
  def _do_read_metric_xsv(reader, row, col):
      if col is not None and row is not None:
          return [reader[row][col]]
      elif col is not None:
          return [r[col] for r in reader]
      elif row is not None:
          return _get_values(reader[row])
      return [_get_values(r) for r in reader]
  
  
  def _read_metric_hxsv(fd, hxsv_path, delimiter):
      indices = hxsv_path.split(",")
      row = indices[0]
      row = int(row) if row else None
      col = indices[1] if len(indices) > 1 and indices[1] else None
      reader = list(csv.DictReader(fd, delimiter=builtin_str(delimiter)))
      return _do_read_metric_xsv(reader, row, col)
  
  
  def _read_metric_xsv(fd, xsv_path, delimiter):
      indices = xsv_path.split(",")
      row = indices[0]
      row = int(row) if row else None
      col = int(indices[1]) if len(indices) > 1 and indices[1] else None
      reader = list(csv.reader(fd, delimiter=builtin_str(delimiter)))
      return _do_read_metric_xsv(reader, row, col)
  
  
  def _read_typed_metric(typ, xpath, fd):
      if typ == "json":
          ret = _read_metric_json(fd, xpath)
      elif typ == "csv":
          ret = _read_metric_xsv(fd, xpath, ",")
      elif typ == "tsv":
          ret = _read_metric_xsv(fd, xpath, "\t")
      elif typ == "hcsv":
          ret = _read_metric_hxsv(fd, xpath, ",")
      elif typ == "htsv":
          ret = _read_metric_hxsv(fd, xpath, "\t")
      else:
          ret = fd.read().strip()
      return ret
  
  
  def _format_csv(content, delimiter):
      """Format delimited text to have same column width.
  
      Args:
          content (str): The content of a metric.
          delimiter (str): Value separator
  
      Returns:
          str: Formatted content.
  
      Example:
  
          >>> content = (
              "value_mse,deviation_mse,data_set\n"
              "0.421601,0.173461,train\n"
              "0.67528,0.289545,testing\n"
              "0.671502,0.297848,validation\n"
          )
          >>> _format_csv(content, ",")
  
          "value_mse  deviation_mse   data_set\n"
          "0.421601   0.173461        train\n"
          "0.67528    0.289545        testing\n"
          "0.671502   0.297848        validation\n"
      """
      reader = csv_reader(StringIO(content), delimiter=builtin_str(delimiter))
      rows = [row for row in reader]
      max_widths = [max(map(len, column)) for column in zip(*rows)]
  
      lines = [
          " ".join(
              "{entry:{width}}".format(entry=entry, width=width + 2)
              for entry, width in zip(row, max_widths)
          )
          for row in rows
      ]
  
      return "\n".join(lines)
  
  
  def _format_output(content, typ):
      """Tabularize the content according to its type.
  
      Args:
          content (str): The content of a metric.
          typ (str): The type of metric -- (raw|json|tsv|htsv|csv|hcsv).
  
      Returns:
          str: Content in a raw or tabular format.
      """
  
      if "csv" in str(typ):
          return _format_csv(content, delimiter=",")
  
      if "tsv" in str(typ):
          return _format_csv(content, delimiter="\t")
  
      return content
  
  
  def _read_metric(fd, typ=None, xpath=None, rel_path=None, branch=None):
      typ = typ.lower().strip() if typ else typ
      try:
          if xpath:
              return _read_typed_metric(typ, xpath.strip(), fd)
          else:
              return _format_output(fd.read().strip(), typ)
      # Json path library has to be replaced or wrapped in
      # order to fix this too broad except clause.
      except Exception:
          logger.warning(
              "unable to read metric in '{}' in branch '{}'".format(
                  rel_path, branch
              ),
              parse_exception=True,
          )
          return None
  
  
  def _collect_metrics(self, path, recursive, typ, xpath, branch):
      """Gather all the metric outputs.
  
      Args:
          path (str): Path to a metric file or a directory.
          recursive (bool): If path is a directory, do a recursive search for
              metrics on the given path.
          typ (str): The type of metric to search for, could be one of the
              following (raw|json|tsv|htsv|csv|hcsv).
          xpath (str): Path to search for.
          branch (str): Branch to look up for metrics.
  
      Returns:
          list(tuple): (output, typ, xpath)
              - output:
              - typ:
              - xpath:
      """
      outs = [out for stage in self.stages() for out in stage.outs]
  
      if path:
          try:
              outs = self.find_outs_by_path(path, outs=outs, recursive=recursive)
          except OutputNotFoundError:
              logger.debug(
                  "stage file not for found for '{}' in branch '{}'".format(
                      path, branch
                  )
              )
              return []
  
      res = []
      for o in outs:
          if not o.metric:
              continue
  
          if not typ and isinstance(o.metric, dict):
              t = o.metric.get(o.PARAM_METRIC_TYPE, typ)
              x = o.metric.get(o.PARAM_METRIC_XPATH, xpath)
          else:
              t = typ
              x = xpath
  
          res.append((o, t, x))
  
      return res
  
  
  def _read_metrics_filesystem(path, typ, xpath, rel_path, branch):
      if not os.path.exists(path):
          return None
      with open(path, "r") as fd:
          return _read_metric(
              fd, typ=typ, xpath=xpath, rel_path=rel_path, branch=branch
          )
  
  
  def _read_metrics(self, metrics, branch):
      """Read the content of each metric file and format it.
  
      Args:
          metrics (list): List of metric touples
          branch (str): Branch to look up for metrics.
  
      Returns:
          A dict mapping keys with metrics path name and content.
          For example:
  
          {'metric.csv': ("value_mse  deviation_mse   data_set\n"
                          "0.421601   0.173461        train\n"
                          "0.67528    0.289545        testing\n"
                          "0.671502   0.297848        validation\n")}
      """
      res = {}
      for out, typ, xpath in metrics:
          assert out.scheme == "local"
          if out.use_cache:
              metric = _read_metrics_filesystem(
                  self.cache.local.get(out.checksum),
                  typ=typ,
                  xpath=xpath,
                  rel_path=out.rel_path,
                  branch=branch,
              )
          else:
              fd = self.tree.open(out.path)
              metric = _read_metric(
                  fd, typ=typ, xpath=xpath, rel_path=out.rel_path, branch=branch
              )
  
          if not metric:
              continue
  
          res[out.rel_path] = metric
  
      return res
  
  
  def show(
      self,
      path=None,
      typ=None,
      xpath=None,
      all_branches=False,
      all_tags=False,
      recursive=False,
  ):
      res = {}
  
      for branch in self.brancher(all_branches=all_branches, all_tags=all_tags):
          entries = _collect_metrics(self, path, recursive, typ, xpath, branch)
          metrics = _read_metrics(self, entries, branch)
          if metrics:
              res[branch] = metrics
  
      if not res:
          if path:
              raise BadMetricError(path)
          raise NoMetricsError()
  
      return res
  
  ```
  --- END FILE ---
  
  Please first localize the bug based on the issue statement, and then generate *SEARCH/REPLACE* edits to fix the issue.
  
  Every *SEARCH/REPLACE* edit must use this format:
  1. The file path
  2. The start of search block: <<<<<<< SEARCH
  3. A contiguous chunk of lines to search for in the existing source code
  4. The dividing line: =======
  5. The lines to replace into the source code
  6. The end of the replace block: >>>>>>> REPLACE
  
  Here is an example:
  
  ```python
  ### mathweb/flask/app.py
  <<<<<<< SEARCH
  from flask import Flask
  =======
  import math
  from flask import Flask
  >>>>>>> REPLACE
  ```
  
  Please note that the *SEARCH/REPLACE* edit REQUIRES PROPER INDENTATION. If you would like to add the line '        print(x)', you must fully write that out, with all those spaces before the code!
  Wrap the *SEARCH/REPLACE* edit in blocks ```python...```.
  
messages.role: user
verification_info: {"file_context": {"dvc/command/metrics.py": "from __future__ import unicode_literals\n\nimport argparse\n\nimport dvc.logger as logger\nfrom dvc.exceptions import DvcException\nfrom dvc.command.base import CmdBase, fix_subparsers, append_doc_link\n\n\ndef show_metrics(metrics, all_branches=False, all_tags=False):\n    \"\"\"\n    Args:\n        metrics (list): Where each element is either a `list`\n            if an xpath was specified, otherwise a `str`\n    \"\"\"\n    for branch, val in metrics.items():\n        if all_branches or all_tags:\n            logger.info(\"{branch}:\".format(branch=branch))\n\n        for fname, metric in val.items():\n            lines = metric if type(metric) is list else metric.splitlines()\n\n            if len(lines) > 1:\n                logger.info(\"\\t{fname}:\".format(fname=fname))\n\n                for line in lines:\n                    logger.info(\"\\t\\t{content}\".format(content=line))\n\n            else:\n                logger.info(\"\\t{}: {}\".format(fname, metric))\n\n\nclass CmdMetricsShow(CmdBase):\n    def run(self):\n        typ = self.args.type\n        xpath = self.args.xpath\n        try:\n            metrics = self.repo.metrics.show(\n                self.args.path,\n                typ=typ,\n                xpath=xpath,\n                all_branches=self.args.all_branches,\n                all_tags=self.args.all_tags,\n                recursive=self.args.recursive,\n            )\n\n            show_metrics(metrics, self.args.all_branches, self.args.all_tags)\n        except DvcException:\n            logger.error(\"failed to show metrics\")\n            return 1\n\n        return 0\n\n\nclass CmdMetricsModify(CmdBase):\n    def run(self):\n        try:\n            self.repo.metrics.modify(\n                self.args.path, typ=self.args.type, xpath=self.args.xpath\n            )\n        except DvcException:\n            logger.error(\"failed to modify metric file settings\")\n            return 1\n\n        return 0\n\n\nclass CmdMetricsAdd(CmdBase):\n    def run(self):\n        try:\n            self.repo.metrics.add(\n                self.args.path, self.args.type, self.args.xpath\n            )\n        except DvcException:\n            msg = \"failed to add metric file '{}'\".format(self.args.path)\n            logger.error(msg)\n            return 1\n\n        return 0\n\n\nclass CmdMetricsRemove(CmdBase):\n    def run(self):\n        try:\n            self.repo.metrics.remove(self.args.path)\n        except DvcException:\n            msg = \"failed to remove metric file '{}'\".format(self.args.path)\n            logger.error(msg)\n            return 1\n\n        return 0\n\n\ndef add_parser(subparsers, parent_parser):\n    METRICS_HELP = \"Commands to add, manage, collect and display metrics.\"\n\n    metrics_parser = subparsers.add_parser(\n        \"metrics\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_HELP, \"metrics\"),\n        help=METRICS_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n\n    metrics_subparsers = metrics_parser.add_subparsers(\n        dest=\"cmd\",\n        help=\"Use dvc metrics CMD --help to display command-specific help.\",\n    )\n\n    fix_subparsers(metrics_subparsers)\n\n    METRICS_SHOW_HELP = \"Output metric values.\"\n    metrics_show_parser = metrics_subparsers.add_parser(\n        \"show\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_SHOW_HELP, \"metrics-show\"),\n        help=METRICS_SHOW_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_show_parser.add_argument(\n        \"path\", nargs=\"?\", help=\"Path to a metric file or a directory.\"\n    )\n    metrics_show_parser.add_argument(\n        \"-t\", \"--type\", help=\"Type of metrics (raw/json/tsv/htsv/csv/hcsv).\"\n    )\n    metrics_show_parser.add_argument(\n        \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"\n    )\n    metrics_show_parser.add_argument(\n        \"-a\",\n        \"--all-branches\",\n        action=\"store_true\",\n        default=False,\n        help=\"Show metrics for all branches.\",\n    )\n    metrics_show_parser.add_argument(\n        \"-T\",\n        \"--all-tags\",\n        action=\"store_true\",\n        default=False,\n        help=\"Show metrics for all tags.\",\n    )\n    metrics_show_parser.add_argument(\n        \"-R\",\n        \"--recursive\",\n        action=\"store_true\",\n        default=False,\n        help=(\n            \"If path is a directory, recursively search and process metric \"\n            \"files in path.\"\n        ),\n    )\n    metrics_show_parser.set_defaults(func=CmdMetricsShow)\n\n    METRICS_ADD_HELP = \"Tag file as a metric file.\"\n    metrics_add_parser = metrics_subparsers.add_parser(\n        \"add\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_ADD_HELP, \"metrics-add\"),\n        help=METRICS_ADD_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_add_parser.add_argument(\n        \"-t\", \"--type\", help=\"Type of metrics (raw/json/tsv/htsv/csv/hcsv).\"\n    )\n    metrics_add_parser.add_argument(\n        \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"\n    )\n    metrics_add_parser.add_argument(\"path\", help=\"Path to a metric file.\")\n    metrics_add_parser.set_defaults(func=CmdMetricsAdd)\n\n    METRICS_MODIFY_HELP = \"Modify metric file options.\"\n    metrics_modify_parser = metrics_subparsers.add_parser(\n        \"modify\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_MODIFY_HELP, \"metrics-modify\"),\n        help=METRICS_MODIFY_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_modify_parser.add_argument(\n        \"-t\", \"--type\", help=\"Type of metrics (raw/json/tsv/htsv/csv/hcsv).\"\n    )\n    metrics_modify_parser.add_argument(\n        \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"\n    )\n    metrics_modify_parser.add_argument(\"path\", help=\"Path to a metric file.\")\n    metrics_modify_parser.set_defaults(func=CmdMetricsModify)\n\n    METRICS_REMOVE_HELP = \"Remove files's metric tag.\"\n    metrics_remove_parser = metrics_subparsers.add_parser(\n        \"remove\",\n        parents=[parent_parser],\n        description=append_doc_link(METRICS_REMOVE_HELP, \"metrics-remove\"),\n        help=METRICS_REMOVE_HELP,\n        formatter_class=argparse.RawDescriptionHelpFormatter,\n    )\n    metrics_remove_parser.add_argument(\"path\", help=\"Path to a metric file.\")\n    metrics_remove_parser.set_defaults(func=CmdMetricsRemove)\n", "dvc/repo/metrics/show.py": "from __future__ import unicode_literals\n\nimport os\nimport csv\nimport json\nfrom jsonpath_rw import parse\n\nimport dvc.logger as logger\nfrom dvc.exceptions import OutputNotFoundError, BadMetricError, NoMetricsError\nfrom dvc.utils.compat import builtin_str, open, StringIO, csv_reader\n\n\ndef _read_metric_json(fd, json_path):\n    parser = parse(json_path)\n    return [x.value for x in parser.find(json.load(fd))]\n\n\ndef _get_values(row):\n    if isinstance(row, dict):\n        return list(row.values())\n    else:\n        return row\n\n\ndef _do_read_metric_xsv(reader, row, col):\n    if col is not None and row is not None:\n        return [reader[row][col]]\n    elif col is not None:\n        return [r[col] for r in reader]\n    elif row is not None:\n        return _get_values(reader[row])\n    return [_get_values(r) for r in reader]\n\n\ndef _read_metric_hxsv(fd, hxsv_path, delimiter):\n    indices = hxsv_path.split(\",\")\n    row = indices[0]\n    row = int(row) if row else None\n    col = indices[1] if len(indices) > 1 and indices[1] else None\n    reader = list(csv.DictReader(fd, delimiter=builtin_str(delimiter)))\n    return _do_read_metric_xsv(reader, row, col)\n\n\ndef _read_metric_xsv(fd, xsv_path, delimiter):\n    indices = xsv_path.split(\",\")\n    row = indices[0]\n    row = int(row) if row else None\n    col = int(indices[1]) if len(indices) > 1 and indices[1] else None\n    reader = list(csv.reader(fd, delimiter=builtin_str(delimiter)))\n    return _do_read_metric_xsv(reader, row, col)\n\n\ndef _read_typed_metric(typ, xpath, fd):\n    if typ == \"json\":\n        ret = _read_metric_json(fd, xpath)\n    elif typ == \"csv\":\n        ret = _read_metric_xsv(fd, xpath, \",\")\n    elif typ == \"tsv\":\n        ret = _read_metric_xsv(fd, xpath, \"\\t\")\n    elif typ == \"hcsv\":\n        ret = _read_metric_hxsv(fd, xpath, \",\")\n    elif typ == \"htsv\":\n        ret = _read_metric_hxsv(fd, xpath, \"\\t\")\n    else:\n        ret = fd.read().strip()\n    return ret\n\n\ndef _format_csv(content, delimiter):\n    \"\"\"Format delimited text to have same column width.\n\n    Args:\n        content (str): The content of a metric.\n        delimiter (str): Value separator\n\n    Returns:\n        str: Formatted content.\n\n    Example:\n\n        >>> content = (\n            \"value_mse,deviation_mse,data_set\\n\"\n            \"0.421601,0.173461,train\\n\"\n            \"0.67528,0.289545,testing\\n\"\n            \"0.671502,0.297848,validation\\n\"\n        )\n        >>> _format_csv(content, \",\")\n\n        \"value_mse  deviation_mse   data_set\\n\"\n        \"0.421601   0.173461        train\\n\"\n        \"0.67528    0.289545        testing\\n\"\n        \"0.671502   0.297848        validation\\n\"\n    \"\"\"\n    reader = csv_reader(StringIO(content), delimiter=builtin_str(delimiter))\n    rows = [row for row in reader]\n    max_widths = [max(map(len, column)) for column in zip(*rows)]\n\n    lines = [\n        \" \".join(\n            \"{entry:{width}}\".format(entry=entry, width=width + 2)\n            for entry, width in zip(row, max_widths)\n        )\n        for row in rows\n    ]\n\n    return \"\\n\".join(lines)\n\n\ndef _format_output(content, typ):\n    \"\"\"Tabularize the content according to its type.\n\n    Args:\n        content (str): The content of a metric.\n        typ (str): The type of metric -- (raw|json|tsv|htsv|csv|hcsv).\n\n    Returns:\n        str: Content in a raw or tabular format.\n    \"\"\"\n\n    if \"csv\" in str(typ):\n        return _format_csv(content, delimiter=\",\")\n\n    if \"tsv\" in str(typ):\n        return _format_csv(content, delimiter=\"\\t\")\n\n    return content\n\n\ndef _read_metric(fd, typ=None, xpath=None, rel_path=None, branch=None):\n    typ = typ.lower().strip() if typ else typ\n    try:\n        if xpath:\n            return _read_typed_metric(typ, xpath.strip(), fd)\n        else:\n            return _format_output(fd.read().strip(), typ)\n    # Json path library has to be replaced or wrapped in\n    # order to fix this too broad except clause.\n    except Exception:\n        logger.warning(\n            \"unable to read metric in '{}' in branch '{}'\".format(\n                rel_path, branch\n            ),\n            parse_exception=True,\n        )\n        return None\n\n\ndef _collect_metrics(self, path, recursive, typ, xpath, branch):\n    \"\"\"Gather all the metric outputs.\n\n    Args:\n        path (str): Path to a metric file or a directory.\n        recursive (bool): If path is a directory, do a recursive search for\n            metrics on the given path.\n        typ (str): The type of metric to search for, could be one of the\n            following (raw|json|tsv|htsv|csv|hcsv).\n        xpath (str): Path to search for.\n        branch (str): Branch to look up for metrics.\n\n    Returns:\n        list(tuple): (output, typ, xpath)\n            - output:\n            - typ:\n            - xpath:\n    \"\"\"\n    outs = [out for stage in self.stages() for out in stage.outs]\n\n    if path:\n        try:\n            outs = self.find_outs_by_path(path, outs=outs, recursive=recursive)\n        except OutputNotFoundError:\n            logger.debug(\n                \"stage file not for found for '{}' in branch '{}'\".format(\n                    path, branch\n                )\n            )\n            return []\n\n    res = []\n    for o in outs:\n        if not o.metric:\n            continue\n\n        if not typ and isinstance(o.metric, dict):\n            t = o.metric.get(o.PARAM_METRIC_TYPE, typ)\n            x = o.metric.get(o.PARAM_METRIC_XPATH, xpath)\n        else:\n            t = typ\n            x = xpath\n\n        res.append((o, t, x))\n\n    return res\n\n\ndef _read_metrics_filesystem(path, typ, xpath, rel_path, branch):\n    if not os.path.exists(path):\n        return None\n    with open(path, \"r\") as fd:\n        return _read_metric(\n            fd, typ=typ, xpath=xpath, rel_path=rel_path, branch=branch\n        )\n\n\ndef _read_metrics(self, metrics, branch):\n    \"\"\"Read the content of each metric file and format it.\n\n    Args:\n        metrics (list): List of metric touples\n        branch (str): Branch to look up for metrics.\n\n    Returns:\n        A dict mapping keys with metrics path name and content.\n        For example:\n\n        {'metric.csv': (\"value_mse  deviation_mse   data_set\\n\"\n                        \"0.421601   0.173461        train\\n\"\n                        \"0.67528    0.289545        testing\\n\"\n                        \"0.671502   0.297848        validation\\n\")}\n    \"\"\"\n    res = {}\n    for out, typ, xpath in metrics:\n        assert out.scheme == \"local\"\n        if out.use_cache:\n            metric = _read_metrics_filesystem(\n                self.cache.local.get(out.checksum),\n                typ=typ,\n                xpath=xpath,\n                rel_path=out.rel_path,\n                branch=branch,\n            )\n        else:\n            fd = self.tree.open(out.path)\n            metric = _read_metric(\n                fd, typ=typ, xpath=xpath, rel_path=out.rel_path, branch=branch\n            )\n\n        if not metric:\n            continue\n\n        res[out.rel_path] = metric\n\n    return res\n\n\ndef show(\n    self,\n    path=None,\n    typ=None,\n    xpath=None,\n    all_branches=False,\n    all_tags=False,\n    recursive=False,\n):\n    res = {}\n\n    for branch in self.brancher(all_branches=all_branches, all_tags=all_tags):\n        entries = _collect_metrics(self, path, recursive, typ, xpath, branch)\n        metrics = _read_metrics(self, entries, branch)\n        if metrics:\n            res[branch] = metrics\n\n    if not res:\n        if path:\n            raise BadMetricError(path)\n        raise NoMetricsError()\n\n    return res\n"}, "filelevel_patches": {"dvc/command/metrics.py": "@@ -107,7 +107,13 @@ def add_parser(subparsers, parent_parser):\n         \"path\", nargs=\"?\", help=\"Path to a metric file or a directory.\"\n     )\n     metrics_show_parser.add_argument(\n-        \"-t\", \"--type\", help=\"Type of metrics (raw/json/tsv/htsv/csv/hcsv).\"\n+        \"-t\",\n+        \"--type\",\n+        help=(\n+            \"Type of metrics (json/tsv/htsv/csv/hcsv). \"\n+            \"It can be detected by the file extension automatically. \"\n+            \"Unsupported types will be treated as raw.\"\n+        ),\n     )\n     metrics_show_parser.add_argument(\n         \"-x\", \"--xpath\", help=\"json/tsv/htsv/csv/hcsv path.\"", "dvc/repo/metrics/show.py": "@@ -129,6 +129,8 @@ def _read_metrics(self, metrics, branch):\n     res = {}\n     for out, typ, xpath in metrics:\n         assert out.scheme == \"local\"\n+        if not typ:\n+            typ = os.path.splitext(out.path.lower())[1].replace(\".\", \"\")\n         if out.use_cache:\n             metric = _read_metrics_filesystem(\n                 self.cache.local.get(out.checksum),"}}