code: def import_table(
      paths,
      key=None,
      min_partitions=None,
      impute=False,
      no_header=False,
      comment=(),
      delimiter="\t",
      missing="NA",
      types={},
      quote=None,
      skip_blank_lines=False,
      force_bgz=False,
      filter=None,
      find_replace=None,
      force=False,
      source_file_field=None,
  ) -> Table:
      """Import delimited text file (text table) as :class:`.Table`.
  
      The resulting :class:`.Table` will have no key fields. Use
      :meth:`.Table.key_by` to specify keys. See also:
      :func:`.import_matrix_table`.
  
      Examples
      --------
  
      Consider this file:
  
      .. code-block:: text
  
          $ cat data/samples1.tsv
          Sample     Height  Status  Age
          PT-1234    154.1   ADHD    24
          PT-1236    160.9   Control 19
          PT-1238    NA      ADHD    89
          PT-1239    170.3   Control 55
  
      The field ``Height`` contains floating-point numbers and the field ``Age``
      contains integers.
  
      To import this table using field types:
  
      >>> table = hl.import_table('data/samples1.tsv',
      ...                              types={'Height': hl.tfloat64, 'Age': hl.tint32})
  
      Note ``Sample`` and ``Status`` need no type, because :py:data:`.tstr` is
      the default type.
  
      To import a table using type imputation (which causes the file to be parsed
      twice):
  
      >>> table = hl.import_table('data/samples1.tsv', impute=True)
  
      **Detailed examples**
  
      Let's import fields from a CSV file with missing data and special characters:
  
      .. code-block:: text
  
          $ cat data/samples2.csv
          Batch,PT-ID
          1kg,PT-0001
          1kg,PT-0002
          study1,PT-0003
          study3,PT-0003
          .,PT-0004
          1kg,PT-0005
          .,PT-0006
          1kg,PT-0007
  
      In this case, we should:
  
      - Pass the non-default delimiter ``,``
  
      - Pass the non-default missing value ``.``
  
      >>> table = hl.import_table('data/samples2.csv', delimiter=',', missing='.')
  
      Let's import a table from a file with no header and sample IDs that need to
      be transformed.  Suppose the sample IDs are of the form ``NA#####``. This
      file has no header line, and the sample ID is hidden in a field with other
      information.
  
      .. code-block: text
  
          $ cat data/samples3.tsv
          1kg_NA12345   female
          1kg_NA12346   male
          1kg_NA12348   female
          pgc_NA23415   male
          pgc_NA23418   male
  
      To import:
  
      >>> t = hl.import_table('data/samples3.tsv', no_header=True)
      >>> t = t.annotate(sample = t.f0.split("_")[1]).key_by('sample')
  
      Let's import a table from a file where one of the fields is a JSON object.
  
      .. code-block: text
  
          $cat data/table_with_json.tsv
          id     json_field
          1      {"foo": "bar", "x": 7}
          4      {"foo": "baz", "x": 100}
  
      To import, we need to specify the types argument.
  
      >>> my_types = {"id": hl.tint32, "json_field":hl.tstruct(foo=hl.tstr, x=hl.tint32)}
      >>> ht_with_json = hl.import_table('data/table_with_json.tsv', types=my_types)
  
      Notes
      -----
  
      The `impute` parameter tells Hail to scan the file an extra time to gather
      information about possible field types. While this is a bit slower for large
      files because the file is parsed twice, the convenience is often worth this
      cost.
  
      The `delimiter` parameter is either a delimiter character (if a single
      character) or a field separator regex (2 or more characters). This regex
      follows the `Java regex standard
      <http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html>`_.
  
      .. note::
  
          Use ``delimiter='\\s+'`` to specify whitespace delimited files.
  
      If set, the `comment` parameter causes Hail to skip any line that starts
      with the given string(s). For example, passing ``comment='#'`` will skip any
      line beginning in a pound sign. If the string given is a single character,
      Hail will skip any line beginning with the character. Otherwise if the
      length of the string is greater than 1, Hail will interpret the string as a
      regex and will filter out lines matching the regex. For example, passing
      ``comment=['#', '^track.*']`` will filter out lines beginning in a pound sign
      and any lines that match the regex ``'^track.*'``.
  
      The `missing` parameter defines the representation of missing data in the table.
  
      .. note::
  
          The `missing` parameter is **NOT** a regex. The `comment` parameter is
          treated as a regex **ONLY** if the length of the string is greater than
          1 (not a single character).
  
      The `no_header` parameter indicates that the file has no header line. If
      this option is passed, then the field names will be `f0`, `f1`,
      ... `fN` (0-indexed).
  
      The `types` parameter allows the user to pass the types of fields in the
      table. It is an :obj:`dict` keyed by :class:`str`, with :class:`.HailType` values.
      See the examples above for a standard usage. Additionally, this option can
      be used to override type imputation. For example, if the field
      ``Chromosome`` only contains the values ``1`` through ``22``, it will be
      imputed to have type :py:data:`.tint32`, whereas most Hail methods expect
      that a chromosome field will be of type :py:data:`.tstr`. Setting
      ``impute=True`` and ``types={'Chromosome': hl.tstr}`` solves this problem.
  
      Parameters
      ----------
  
      paths : :class:`str` or :obj:`list` of :obj:`str`
          Files to import.
      key : :class:`str` or :obj:`list` of :obj:`str`
          Key fields(s).
      min_partitions : :obj:`int` or :obj:`None`
          Minimum number of partitions.
      no_header : :obj:`bool`
          If ``True```, assume the file has no header and name the N fields `f0`,
          `f1`, ... `fN` (0-indexed).
      impute : :obj:`bool`
          If ``True``, Impute field types from the file.
      comment : :class:`str` or :obj:`list` of :obj:`str`
          Skip lines beginning with the given string if the string is a single
          character. Otherwise, skip lines that match the regex specified. Multiple
          comment characters or patterns should be passed as a list.
      delimiter : :class:`str`
          Field delimiter regex.
      missing : :class:`str` or :obj:`list` [:obj:`str`]
          Identifier(s) to be treated as missing.
      types : :obj:`dict` mapping :class:`str` to :class:`.HailType`
          Dictionary defining field types.
      quote : :class:`str` or :obj:`None`
          Quote character.
      skip_blank_lines : :obj:`bool`
          If ``True``, ignore empty lines. Otherwise, throw an error if an empty
          line is found.
      force_bgz : :obj:`bool`
          If ``True``, load files as blocked gzip files, assuming
          that they were actually compressed using the BGZ codec. This option is
          useful when the file extension is not ``'.bgz'``, but the file is
          blocked gzip, so that the file can be read in parallel and not on a
          single node.
      filter : :class:`str`, optional
          Line filter regex. A partial match results in the line being removed
          from the file. Applies before `find_replace`, if both are defined.
      find_replace : (:class:`str`, :obj:`str`)
          Line substitution regex. Functions like ``re.sub``, but obeys the exact
          semantics of Java's
          `String.replaceAll <https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#replaceAll-java.lang.String-java.lang.String->`__.
      force : :obj:`bool`
          If ``True``, load gzipped files serially on one core. This should
          be used only when absolutely necessary, as processing time will be
          increased due to lack of parallelism.
      source_file_field : :class:`str`, optional
          If defined, the source file name for each line will be a field of the table
          with this name. Can be useful when importing multiple tables using glob patterns.
      Returns
      -------
      :class:`.Table`
      """
      if len(delimiter) < 1:
          raise ValueError(
              "import_table: empty delimiter is not supported"
          )
  
      paths = wrap_to_list(paths)
      comment = wrap_to_list(comment)
      missing = wrap_to_list(missing)
  
      ht = hl.import_lines(paths, min_partitions, force_bgz, force)
  
      should_remove_line_expr = should_remove_line(
          ht.text,
          filter=filter,
          comment=comment,
          skip_blank_lines=skip_blank_lines,
      )
      if should_remove_line_expr is not None:
          ht = ht.filter(should_remove_line_expr, keep=False)
  
      try:
          if len(paths) <= 1:
              # With zero or one files and no filters, the first row, if it exists must be in the first
              # partition, so we take this one-pass fast-path.
              first_row_ht = ht._filter_partitions([0]).head(1)
          else:
              first_row_ht = ht.head(1)
  
          if find_replace is not None:
              ht = ht.annotate(text=ht["text"].replace(*find_replace))
  
          first_rows = first_row_ht.annotate(
              header=first_row_ht.text._split_line(
                  delimiter,
                  missing=hl.empty_array(hl.tstr),
                  quote=quote,
                  regex=len(delimiter) > 1,
              )
          ).collect()
      except FatalError as err:
          if (
              "_filter_partitions: no partition with index 0"
              in err.args[0]
          ):
              first_rows = []
          else:
              raise
  
      if len(first_rows) == 0:
          raise ValueError(
              f"Invalid file: no lines remaining after filters\n Files provided: {', '.join(paths)}"
          )
      first_row = first_rows[0]
  
      if no_header:
          fields = [
              f"f{index}" for index in range(0, len(first_row.header))
          ]
      else:
          maybe_duplicated_fields = first_row.header
          renamings, fields = deduplicate(maybe_duplicated_fields)
          ht = ht.filter(
              ht.text == first_row.text, keep=False
          )  # FIXME: seems wrong. Could easily fix with partition index and row_within_partition_index.
          if renamings:
              hl.utils.warning(
                  f'import_table: renamed the following {plural("field", len(renamings))} to avoid name conflicts:'
                  + "".join(
                      f"\n    {repr(k)} -> {repr(v)}"
                      for k, v in renamings
                  )
              )
  
      ht = ht.annotate(
          split_text=(
              hl.case()
              .when(
                  hl.len(ht.text) > 0,
                  split_lines(
                      ht,
                      fields,
                      delimiter=delimiter,
                      missing=missing,
                      quote=quote,
                  ),
              )
              .or_error(hl.str("Blank line found in file ") + ht.file)
          )
      )
      ht = ht.drop("text")
  
      fields_to_value = {}
      strs = []
      if impute:
          fields_to_impute_idx = []
          fields_to_guess = []
          for idx, field in enumerate(fields):
              if types.get(field) is None:
                  fields_to_impute_idx.append(idx)
                  fields_to_guess.append(field)
  
          hl.utils.info("Reading table to impute column types")
          guessed = ht.aggregate(
              hl.agg.array_agg(
                  lambda x: hl.agg._impute_type(x),
                  [ht.split_text[i] for i in fields_to_impute_idx],
              )
          )
  
          reasons = {f: "user-supplied type" for f in types}
          imputed_types = dict()
          for field, s in zip(fields_to_guess, guessed):
              if not s["anyNonMissing"]:
                  imputed_types[field] = hl.tstr
                  reasons[field] = "no non-missing observations"
              else:
                  if s["supportsBool"]:
                      imputed_types[field] = hl.tbool
                  elif s["supportsInt32"]:
                      imputed_types[field] = hl.tint32
                  elif s["supportsInt64"]:
                      imputed_types[field] = hl.tint64
                  elif s["supportsFloat64"]:
                      imputed_types[field] = hl.tfloat64
                  else:
                      imputed_types[field] = hl.tstr
                  reasons[field] = "imputed"
  
          strs.append("Finished type imputation")
  
          all_types = dict(**types, **imputed_types)
  
          for f_idx, field in enumerate(fields):
              strs.append(
                  f"  Loading field {field!r} as type {all_types[field]} ({reasons[field]})"
              )
              fields_to_value[field] = parse_type(
                  ht.split_text[f_idx], all_types[field]
              )
      else:
          strs.append("Reading table without type imputation")
          for f_idx, field in enumerate(fields):
              reason = (
                  "user-supplied" if field in types else "not specified"
              )
              t = types.get(field, hl.tstr)
              fields_to_value[field] = parse_type(
                  ht.split_text[f_idx], t
              )
              strs.append(
                  f"  Loading field {field!r} as type {t} ({reason})"
              )
  
      ht = ht.annotate(**fields_to_value).drop("split_text")
      if source_file_field is not None:
          source_file = {source_file_field: ht.file}
          ht = ht.annotate(**source_file)
      ht = ht.drop("file")
  
      if len(fields) < 30:
          hl.utils.info("\n".join(strs))
      else:
          from collections import Counter
  
          strs2 = [f"Loading {ht.row} fields. Counts by type:"]
          for name, count in Counter(
              ht[f].dtype for f in fields
          ).most_common():
              strs2.append(f"  {name}: {count}")
          hl.utils.info("\n".join(strs2))
  
      if key:
          key = wrap_to_list(key)
          ht = ht.key_by(*key)
      return ht
  
imports: import os
  import re
  from collections import defaultdict
  import avro.schema
  from avro.datafile import DataFileReader
  from avro.io import DatumReader
  import hail
  from hail import ir
  from hail.expr import StructExpression, LocusExpression, expr_array, expr_float64, expr_str, expr_numeric, expr_call, expr_bool, expr_int32, to_expr, analyze
  from hail.expr.types import hail_type, tarray, tfloat64, tstr, tint32, tstruct, tcall, tbool, tint64, tfloat32
  from hail.genetics.reference_genome import reference_genome_type
  from hail.ir.utils import parse_type
  from hail.matrixtable import MatrixTable
  from hail.methods.misc import require_biallelic, require_row_key_variant, require_col_key_str
  from hail.table import Table
  from hail.typecheck import typecheck, nullable, oneof, dictof, anytype, sequenceof, enumeration, sized_tupleof, numeric, table_key_type, char
  from hail.utils import new_temp_file
  from hail.utils.deduplicate import deduplicate
  from hail.utils.java import Env, FatalError, jindexed_seq_args, warning
  from hail.utils.java import info
  from hail.utils.misc import wrap_to_list, plural
  from .import_lines_helpers import split_lines, should_remove_line
label_desc: Use image node_id 13 for calling a global function with example usage: import_table(paths, key, min_partitions, impute, no_header, comment, delimiter, missing, types, quote, skip_blank_lines, force_bgz, filter, find_replace, force, source_file_field) and returns: ht