code: def write_metadata(
      cls, parts, meta, fs, path, append=False, **kwargs
  ):
      _meta = copy.copy(meta)
      rgs = meta.row_groups
      if parts:
          for rg in parts:
              if rg is not None:
                  if isinstance(rg, list):
                      for r in rg:
                          rgs.append(r)
                  else:
                      rgs.append(rg)
          _meta.row_groups = rgs
          fn = fs.sep.join([path, "_metadata"])
          fastparquet.writer.write_common_metadata(
              fn, _meta, open_with=fs.open, no_row_groups=False
          )
  
      # if appending, could skip this, but would need to check existence
      fn = fs.sep.join([path, "_common_metadata"])
      fastparquet.writer.write_common_metadata(
          fn, _meta, open_with=fs.open
      )
  
imports: from __future__ import annotations
  import copy
  import pickle
  import threading
  import warnings
  from collections import OrderedDict, defaultdict
  from contextlib import ExitStack
  import numpy
  import pandas
  import tlz
  from packaging.version import parse
  from dask.core import flatten
  from dask.dataframe._compat import PANDAS_GE_201
  from dask.base import tokenize
  from dask.dataframe.io.parquet.utils import Engine, _get_aggregation_depth, _infer_split_row_groups, _normalize_index_columns, _parse_pandas_metadata, _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 _is_local_fs, _meta_from_dtypes, _open_input_files
  from dask.dataframe.utils import UNKNOWN_CATEGORIES
  from dask.delayed import Delayed
  from dask.utils import natural_sort_key
label_desc: Use image node_id 14 for calling the FastParquetEngine obj's underlying member method code with example usage: obj.write_metadata(cls, parts, meta, fs, path, append) without return types