code: def scan_csv(
      source: str | Path | list[str] | list[Path],
      *,
      has_header: bool = True,
      separator: str = ",",
      comment_prefix: str | None = None,
      quote_char: str | None = '"',
      skip_rows: int = 0,
      dtypes: SchemaDict | Sequence[PolarsDataType] | None = None,
      schema: SchemaDict | None = None,
      null_values: str | Sequence[str] | dict[str, str] | None = None,
      missing_utf8_is_empty_string: bool = False,
      ignore_errors: bool = False,
      cache: bool = True,
      with_column_names: Callable[[list[str]], list[str]] | None = None,
      infer_schema_length: int | None = N_INFER_DEFAULT,
      n_rows: int | None = None,
      encoding: CsvEncoding = "utf8",
      low_memory: bool = False,
      rechunk: bool = True,
      skip_rows_after_header: int = 0,
      row_count_name: str | None = None,
      row_count_offset: int = 0,
      try_parse_dates: bool = False,
      eol_char: str = "\n",
      new_columns: Sequence[str] | None = None,
      raise_if_empty: bool = True,
      truncate_ragged_lines: bool = False,
  ) -> LazyFrame:
      r"""
      Lazily read from a CSV file or multiple files via glob patterns.
  
      This allows the query optimizer to push down predicates and
      projections to the scan level, thereby potentially reducing
      memory overhead.
  
      Parameters
      ----------
      source
          Path to a file.
      has_header
          Indicate if the first row of dataset is a header or not.
          If set to False, column names will be autogenerated in the
          following format: `column_x`, with `x` being an
          enumeration over every column in the dataset starting at 1.
      separator
          Single byte character to use as separator in the file.
      comment_prefix
          A string, which can be up to 5 symbols in length, used to indicate
          the start of a comment line. For instance, it can be set to `#` or `//`.
      quote_char
          Single byte character used for csv quoting, default = `"`.
          Set to None to turn off special handling and escaping of quotes.
      skip_rows
          Start reading after `skip_rows` lines. The header will be parsed at this
          offset.
      dtypes
          Overwrite dtypes during inference; should be a {colname:dtype,} dict or,
          if providing a list of strings to `new_columns`, a list of dtypes of
          the same length.
      schema
          Provide the schema. This means that polars doesn't do schema inference.
          This argument expects the complete schema, whereas `dtypes` can be used
          to partially overwrite a schema.
      null_values
          Values to interpret as null values. You can provide a:
  
          - `str`: All values equal to this string will be null.
          - `List[str]`: All values equal to any string in this list will be null.
          - `Dict[str, str]`: A dictionary that maps column name to a
            null value string.
      missing_utf8_is_empty_string
          By default a missing value is considered to be null; if you would prefer missing
          utf8 values to be treated as the empty string you can set this param True.
      ignore_errors
          Try to keep reading lines if some lines yield errors.
          First try `infer_schema_length=0` to read all columns as
          `pl.String` to check which values might cause an issue.
      cache
          Cache the result after reading.
      with_column_names
          Apply a function over the column names just in time (when they are determined);
          this function will receive (and should return) a list of column names.
      infer_schema_length
          Maximum number of lines to read to infer schema.
          If set to 0, all columns will be read as `pl.String`.
          If set to `None`, a full table scan will be done (slow).
      n_rows
          Stop reading from CSV file after reading `n_rows`.
      encoding : {'utf8', 'utf8-lossy'}
          Lossy means that invalid utf8 values are replaced with `�`
          characters. Defaults to "utf8".
      low_memory
          Reduce memory pressure at the expense of performance.
      rechunk
          Reallocate to contiguous memory when all chunks/ files are parsed.
      skip_rows_after_header
          Skip this number of rows when the header is parsed.
      row_count_name
          If not None, this will insert a row count column with the given name into
          the DataFrame.
      row_count_offset
          Offset to start the row_count column (only used if the name is set).
      try_parse_dates
          Try to automatically parse dates. Most ISO8601-like formats
          can be inferred, as well as a handful of others. If this does not succeed,
          the column remains of data type `pl.String`.
      eol_char
          Single byte end of line character (default: `\n`). When encountering a file
          with windows line endings (`\r\n`), one can go with the default `\n`. The extra
          `\r` will be removed when processed.
      new_columns
          Provide an explicit list of string column names to use (for example, when
          scanning a headerless CSV file). If the given list is shorter than the width of
          the DataFrame the remaining columns will have their original name.
      raise_if_empty
          When there is no data in the source,`NoDataError` is raised. If this parameter
          is set to False, an empty LazyFrame (with no columns) is returned instead.
      truncate_ragged_lines
          Truncate lines that are longer than the schema.
  
      Returns
      -------
      LazyFrame
  
      See Also
      --------
      read_csv : Read a CSV file into a DataFrame.
  
      Examples
      --------
      >>> import pathlib
      >>>
      >>> (
      ...     pl.scan_csv("my_long_file.csv")  # lazy, doesn't do a thing
      ...     .select(
      ...         ["a", "c"]
      ...     )  # select only 2 columns (other columns will not be read)
      ...     .filter(
      ...         pl.col("a") > 10
      ...     )  # the filter is pushed down the scan, so less data is read into memory
      ...     .fetch(100)  # pushed a limit of 100 rows to the scan level
      ... )  # doctest: +SKIP
  
      We can use `with_column_names` to modify the header before scanning:
  
      >>> df = pl.DataFrame(
      ...     {"BrEeZaH": [1, 2, 3, 4], "LaNgUaGe": ["is", "hard", "to", "read"]}
      ... )
      >>> path: pathlib.Path = dirpath / "mydf.csv"
      >>> df.write_csv(path)
      >>> pl.scan_csv(
      ...     path, with_column_names=lambda cols: [col.lower() for col in cols]
      ... ).collect()
      shape: (4, 2)
      ┌─────────┬──────────┐
      │ breezah ┆ language │
      │ ---     ┆ ---      │
      │ i64     ┆ str      │
      ╞═════════╪══════════╡
      │ 1       ┆ is       │
      │ 2       ┆ hard     │
      │ 3       ┆ to       │
      │ 4       ┆ read     │
      └─────────┴──────────┘
  
      You can also simply replace column names (or provide them if the file has none)
      by passing a list of new column names to the `new_columns` parameter:
  
      >>> df.write_csv(path)
      >>> pl.scan_csv(
      ...     path,
      ...     new_columns=["idx", "txt"],
      ...     dtypes=[pl.UInt16, pl.String],
      ... ).collect()
      shape: (4, 2)
      ┌─────┬──────┐
      │ idx ┆ txt  │
      │ --- ┆ ---  │
      │ u16 ┆ str  │
      ╞═════╪══════╡
      │ 1   ┆ is   │
      │ 2   ┆ hard │
      │ 3   ┆ to   │
      │ 4   ┆ read │
      └─────┴──────┘
  
      """
      if not new_columns and isinstance(dtypes, Sequence):
          raise TypeError(
              f"expected 'dtypes' dict, found {type(dtypes).__name__!r}"
          )
      elif new_columns:
          if with_column_names:
              raise ValueError(
                  "cannot set both `with_column_names` and `new_columns`; mutually exclusive"
              )
          if dtypes and isinstance(dtypes, Sequence):
              dtypes = dict(zip(new_columns, dtypes))
  
          # wrap new column names as a callable
          def with_column_names(cols: list[str]) -> list[str]:
              if len(cols) > len(new_columns):
                  return new_columns + cols[len(new_columns) :]  # type: ignore[operator]
              else:
                  return new_columns  # type: ignore[return-value]
  
      _check_arg_is_1byte("separator", separator, can_be_empty=False)
      _check_arg_is_1byte("quote_char", quote_char, can_be_empty=True)
  
      if isinstance(source, (str, Path)):
          source = normalize_filepath(source)
      else:
          source = [normalize_filepath(source) for source in source]
  
      return pl.LazyFrame._scan_csv(
          source,
          has_header=has_header,
          separator=separator,
          comment_prefix=comment_prefix,
          quote_char=quote_char,
          skip_rows=skip_rows,
          dtypes=dtypes,  # type: ignore[arg-type]
          schema=schema,
          null_values=null_values,
          missing_utf8_is_empty_string=missing_utf8_is_empty_string,
          ignore_errors=ignore_errors,
          cache=cache,
          with_column_names=with_column_names,
          infer_schema_length=infer_schema_length,
          n_rows=n_rows,
          low_memory=low_memory,
          rechunk=rechunk,
          skip_rows_after_header=skip_rows_after_header,
          encoding=encoding,
          row_count_name=row_count_name,
          row_count_offset=row_count_offset,
          try_parse_dates=try_parse_dates,
          eol_char=eol_char,
          raise_if_empty=raise_if_empty,
          truncate_ragged_lines=truncate_ragged_lines,
      )
  
file_path: polars/py-polars/polars/io/csv/functions.py
imports: from __future__ import annotations
  from pathlib import Path
  from typing import TYPE_CHECKING, Any, BinaryIO, Callable, Mapping, Sequence, TextIO
  import polars._reexport
  from polars.datatypes import N_INFER_DEFAULT, String
  from polars.io._utils import _prepare_file_arg
  from polars.io.csv._utils import _check_arg_is_1byte, _update_columns
  from polars.io.csv.batched_reader import BatchedCsvReader
  from polars.utils.deprecation import deprecate_renamed_parameter
  from polars.utils.various import handle_projection_columns, normalize_filepath
label_desc: Use image node_id 3 for calling a global function with example usage: scan_csv(source) and returns: pl, unknown, new_columns