docs: def parse_arguments(argv):
    """Parse command line arguments.
  
    Args:
      argv: list of command line arguments, including program name.
  
    Returns:
      An argparse Namespace object.
  
    Raises:
      ValueError: for bad parameters
    """
    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description=textwrap.dedent("""\
            Runs analysis on structured data and produces auxiliary files for
            training. The output files can also be used by the Transform step
            to materialize TF.Examples files, which for some problems can speed up
            training.
  
            Description of input files
            --------------------------
  
            1) If using csv files, the --schema parameter must be the file path to
               a schema file. The format of this file must be a valid BigQuery
               schema file, which is a JSON file containing a list of dicts.
               Consider the example schema file below:
  
               [
                  {"name": "column_name_1", "type": "integer"},
                  {"name": "column_name_2", "type": "float"},
                  {"name": "column_name_3", "type": "string"},
                  {"name": "column_name_4", "type": "string"},
               ]
  
               Note that the column names in the csv file much match the order
               in the schema list. Also, we only support three BigQuery types (
               integer, float, and string).
  
               If instead of csv files, --bigquery is used, the schema file
               is not needed as this program will extract it from
               the table directly.
  
            2) --features is a file path to a file describing the
               transformations. Below is an example features file:
  
               {
                  "column_name_1": {"transform": "scale"},
                  "column_name_3": {"transform": "target"},
                  "column_name_2": {"transform": "one_hot"},
                  "new_feature_name": {"transform": "multi_hot", "source_column": "column_name_4"},
               }
  
               The format of the dict is `name`: `transform-dict` where the
               `name` is the name of the transformed feature. The `source_column`
               value lists what column in the input data is the source for this
               transformation. If `source_column` is missing, it is assumed the
               `name` is a source column and the transformed feature will have
               the same name as the input column.
  
               A list of supported `transform-dict`s for xgboost is below:
  
               {"transform": "identity"}: does nothing (for numerical columns).
               {"transform": "scale", "value": x}: scale a numerical column to
                  [-a, a]. If value is missing, x defaults to 1.
               {"transform": "one_hot"}: makes a one-hot encoding of a string
                  column.
               {"transform": "multi_hot", "separator": ' '}: makes a multi-hot
                  encoding of a string column.
               {"transform": "image_to_vec", "checkpoint": "gs://b/o"}: From image
                  gs url to embeddings. "checkpoint" is a inception v3 checkpoint.
                  If absent, a default checkpoint is used.
               {"transform": "target"}: denotes what column is the target. If the
                  schema type of this column is string, a one_hot encoding is
                  automatically applied. If type is numerical, a identity transform
                  is automatically applied.
    """))
    parser.add_argument('--cloud',
                        action='store_true',
                        help='Analysis will use cloud services.')
    parser.add_argument('--output',
                        metavar='DIR',
                        type=str,
                        required=True,
                        help='GCS or local folder')
  
    input_group = parser.add_argument_group(
        title='Data Source Parameters',
        description='schema is only needed if using --csv')
  
    # CSV input
    input_group.add_argument('--csv',
                             metavar='FILE',
                             type=str,
                             required=False,
                             action='append',
                             help='Input CSV absolute file paths. May contain a '
                                  'file pattern.')
    input_group.add_argument('--schema',
                             metavar='FILE',
                             type=str,
                             required=False,
                             help='Schema file path. Only required if using csv files')
  
    # Bigquery input
    input_group.add_argument('--bigquery',
                             metavar='PROJECT_ID.DATASET.TABLE_NAME',
                             type=str,
                             required=False,
                             help=('Must be in the form project.dataset.table_name'))
  
    parser.add_argument('--features',
                        metavar='FILE',
                        type=str,
                        required=True,
                        help='Features file path')
  
    args = parser.parse_args(args=argv[1:])
  
    if args.cloud:
      if not args.output.startswith('gs://'):
        raise ValueError('--output must point to a location on GCS')
      if (args.csv and
         not all(x.startswith('gs://') for x in args.csv)):
        raise ValueError('--csv must point to a location on GCS')
      if args.schema and not args.schema.startswith('gs://'):
        raise ValueError('--schema must point to a location on GCS')
  
    if not args.cloud and args.bigquery:
      raise ValueError('--bigquery must be used with --cloud')
  
    if not ((args.bigquery and args.csv is None and
             args.schema is None) or
            (args.bigquery is None and args.csv and
             args.schema)):
      raise ValueError('either --csv and --schema must both'
                       ' be set or just --bigquery is set')
  
    return args