code: def _filters_to_expression(
      filters, propagate_null=False, nan_is_null=True
  ):
      # Mostly copied from: pq.filters_to_expression
      # TODO: Use pq.filters_to_expression if/when null-value
      # handling is resolved.
      # See: https://github.com/dask/dask/issues/9845
  
      if isinstance(filters, pa_ds.Expression):
          return filters
  
      if filters is not None:
          if len(filters) == 0 or any(len(f) == 0 for f in filters):
              raise ValueError("Malformed filters")
          if isinstance(filters[0][0], str):
              # We have encountered the situation where we have one nesting level
              # too few:
              #   We have [(,,), ..] instead of [[(,,), ..]]
              filters = [filters]
  
      def convert_single_predicate(col, op, val):
          field = pa_ds.field(col)
  
          # Handle null-value comparison
          if val is None or (nan_is_null and val is np.nan):
              if op == "is":
                  return field.is_null(nan_is_null=nan_is_null)
              elif op == "is not":
                  return ~field.is_null(nan_is_null=nan_is_null)
              else:
                  raise ValueError(
                      f'"{(col, op, val)}" is not a supported predicate '
                      f'Please use "is" or "is not" for null comparison.'
                  )
  
          if op == "=" or op == "==":
              expr = field == val
          elif op == "!=":
              expr = field != val
          elif op == "<":
              expr = field < val
          elif op == ">":
              expr = field > val
          elif op == "<=":
              expr = field <= val
          elif op == ">=":
              expr = field >= val
          elif op == "in":
              expr = field.isin(val)
          elif op == "not in":
              expr = ~field.isin(val)
          else:
              raise ValueError(
                  f'"{(col, op, val)}" is not a valid operator in predicates.'
              )
  
          # (Optionally) Avoid null-value propagation
          if not propagate_null and op in ("!=", "not in"):
              return field.is_null(nan_is_null=nan_is_null) | expr
          return expr
  
      disjunction_members = []
  
      for conjunction in filters:
          conjunction_members = [
              convert_single_predicate(col, op, val)
              for col, op, val in conjunction
          ]
  
          disjunction_members.append(
              reduce(operator.and_, conjunction_members)
          )
  
      return reduce(operator.or_, disjunction_members)
  
imports: from __future__ import annotations
  import json
  import operator
  import textwrap
  import warnings
  from collections import defaultdict
  from datetime import datetime
  from functools import reduce
  import numpy
  import pandas
  import pyarrow
  import pyarrow.parquet
  from fsspec.core import expand_paths_if_needed, stringify_path
  from fsspec.implementations.arrow import ArrowFSWrapper
  from pyarrow import dataset
  from pyarrow import fs
  import dask
  from dask.base import tokenize
  from dask.core import flatten
  from dask.dataframe.backends import pyarrow_schema_dispatch
  from dask.dataframe.io.parquet.utils import Engine, _get_aggregation_depth, _infer_split_row_groups, _normalize_index_columns, _process_open_file_options, _row_groups_to_parts, _set_gather_statistics, _set_metadata_task_size, _sort_and_analyze_paths
  from dask.dataframe.io.utils import _get_pyarrow_dtypes, _is_local_fs, _open_input_files
  from dask.dataframe.utils import clear_known_categories, pyarrow_strings_enabled
  from dask.delayed import Delayed
  from dask.utils import getargspec, natural_sort_key
label_desc: Use image node_id 12 for calling a global function with example usage: _filters_to_expression(filters, propagate_null, nan_is_null) and returns: reduce, filters, expr, unknown, field, unknown