code: def __post_init__(self) -> None:
      if not self.parquet_path:
          raise ValueError(
              f"requires non-empty path got {self.parquet_path}"
          )
  
      if not ((self.batch_size is None) ^ (self.max_tokens is None)):
          raise ValueError(
              "need to provide either `batch_size` either `max_tokens`"
          )
      if self.max_tokens is not None and self.order_by_length is None:
          raise ValueError(
              "`order_by_length` should be given to deal with `max_tokens`"
          )
  
      if self.filters is not None and not isinstance(
          self.filters, pa.dataset.Expression
      ):
          self.filters = pq.filters_to_expression(self.filters)
  
file_path: fairseq2/recipes/parquet/parquet_dataloader.py
imports: from dataclasses import dataclass
  from enum import Enum
  from functools import partial
  from typing import Any, Generator, List, Optional, Union
  import pyarrow
  import pyarrow.parquet
  from fairseq2.data.data_pipeline import DataPipeline, DataPipelineBuilder
  from fairseq2.data.parquet_tools import BatchOutputType, _TableWrapper, _to_real_object, apply_filter, build_iterator_over_one_table, concat_table, list_parquet_fragments, load_one_fragment, pyarrow_cpu, pyarrow_table_to_torch_dict, table_func_wrap
label_desc: Use image node_id 1 for calling the ParquetBasicDataloaderConfig obj's underlying member method code with example usage: obj.__post_init__() without return types