# MolDF# Author: Ruibin Liu <ruibinliuphd@gmail.com># License: MIT# Code Repository: https://github.com/Ruibin-Liu/MolDF"""Write any dict of Pandas DataFrame to JCSV."""from__future__importannotationsimportosimportpandasaspd# type: ignore
[docs]defwrite_jcsv(data:dict[str,pd.DataFrame],file_name:str|os.PathLike|None=None,write_meta:bool=True,**kwargs,)->None:"""Write a dict of ``Pandas DataFrame`` s into a JCSV file. See https://github.com/Ruibin-Liu/JCSV for definitions. Args: data (required): a ``dict`` of ``Pandas DataFrame`` s to write. file_name (optional): file name to write a JCSV file. If ``None``, ``moldf_output.jcsv`` will be used as the file name if ``path_or_buf`` is not specified in ``**kwargs``. Defaults to **None**. write_meta (optional): whether to write meta data into the **first** category. Currently, only the first line number for each category is recorded. Defaults to **True**. **kwargs: keyword arguments for ``pd.DataFrame.to_csv``. Invalid ones are ignored. Check https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_csv.html Raises: TypeError: if ``data`` is not a valid dict of ``DataFrame``. ValueError: if ``"`` in any of the column names. """iffile_nameisNone:file_name=kwargs.get("path_or_buf")iffile_nameisNone:file_name="moldf_output.jcsv"ifnotisinstance(data,dict):raiseTypeError(f"'data' has to be a dict but {type(data)} is provided.")forkeyindata:ifnotisinstance(data[key],pd.DataFrame):raiseTypeError(f"{data[key]} is not a Pandas DataFrame object.")exclusion=["self","path_or_buf","df","formatter"]to_csv_kargs=[kargforkarginpd.DataFrame.to_csv.__code__.co_varnamesifkargnotinexclusion]kwargs={k:vfork,vinkwargs.items()ifkinto_csv_kargs}line_terminator=kwargs.get("lineterminator")ifline_terminatorisNone:line_terminator=kwargs.get("line_terminator")# old Pandas versionsifline_terminatorisNone:line_terminator=os.linesepwithopen(file_name,"w",encoding="utf-8")asout_file:ifwrite_meta:meta_line=f"#jcsv_meta{line_terminator}"out_file.write(meta_line)out_file.write(f"category,start_line_index{line_terminator}")out_file.write(f"meta,1{line_terminator}")# just to be self-consistentlast_cat_line_length=len(data)+3forkey,dfindata.items():if"'"inkey:key=f'"{key}"'elif'"'inkey:message='" is not supported in category names, but'message+=f" {key} has it."raiseValueError(message)out_file.write(f"{key},{last_cat_line_length+1}{line_terminator}")last_cat_line_length+=len(df)+2forkey,dfindata.items():key_line=f"#{key}{line_terminator}"out_file.write(key_line)out_file.write(df.to_csv(index=False,**kwargs))