simfile ======= .. py:module:: simfile .. autoapi-nested-parse:: Convenience functions for loading & modifying simfiles. All functions take a `strict` parameter that defaults to False (except :func:`~.mutate`, which defaults to True). When `strict` is set to True, the underlying parser will throw an exception if it finds any stray text between parameters. Submodules ---------- .. toctree:: :maxdepth: 1 /autoapi/simfile/assets/index /autoapi/simfile/base/index /autoapi/simfile/convert/index /autoapi/simfile/dir/index /autoapi/simfile/notes/index /autoapi/simfile/sm/index /autoapi/simfile/ssc/index /autoapi/simfile/tidy/index /autoapi/simfile/timing/index /autoapi/simfile/types/index Exceptions ---------- .. autoapisummary:: simfile.CancelMutation Functions --------- .. autoapisummary:: simfile.load simfile.loads simfile.open simfile.open_with_detected_encoding simfile.opendir simfile.openpack simfile.mutate Package Contents ---------------- .. py:function:: load(file: TextIO, strict: bool = False, errors: str | None = None) -> types.Simfile Load a text file object as a simfile. If the file object has a filename with a matching extension, it will be used to infer the correct implementation. Otherwise, the first property in the file is peeked at. If its key is "VERSION", the file is treated as an SSC simfile; otherwise, it's treated as an SM simfile. .. py:function:: loads(string: str, strict: bool = False) -> types.Simfile Load a string containing simfile data as a simfile. .. py:function:: open(filename: str, strict: bool = False, filesystem: _private.fs.FS = NativeOSFS(), **kwargs) -> types.Simfile Load a simfile by filename. Keyword arguments are passed to the builtin `open` function. If no encoding is specified, this function will defer to :func:`open_with_detected_encoding`. .. py:function:: open_with_detected_encoding(filename: str, try_encodings: list[str] = ENCODINGS, strict: bool = False, filesystem: _private.fs.FS = NativeOSFS(), **kwargs) -> tuple[types.Simfile, str] Load a simfile by filename; returns the simfile and detected encoding. Tries decoding the simfile as UTF-8, CP1252 (English), CP932 (Japanese), and CP949 (Korean), mirroring the encodings supported by StepMania. This list can be overridden by supplying `try_encodings`. If all encodings fail in non-strict parsing, the simfile will instead be loaded using ASCII with surrogate escapes, which should never fail. Keep in mind that no heuristics are performed to "guess" the correct encoding - this function simply tries each encoding in order until one succeeds. As such, non-UTF-8 files may successfully parse as the wrong encoding, resulting in *mojibake*. If you intend to write the simfile back to disk, make sure to use the same encoding that was detected to preserve the true byte sequence. In general, you only need to use this function directly if you need to know the file's encoding. :func:`.open` and :func:`.mutate` both defer to this function to detect the encoding behind the scenes. .. py:function:: opendir(simfile_dir: str, filesystem: _private.fs.FS = NativeOSFS(), **kwargs) -> tuple[types.Simfile, str] Open a simfile from its directory path; returns a (simfile, filename) tuple. If both SSC and SM are present, SSC is preferred. Keyword arguments are passed down to :func:`simfile.open`. If you need more flexibility (for example, if you need both the SM and SSC files), try using :class:`.SimfileDirectory`. .. py:function:: openpack(pack_dir: str, filesystem: _private.fs.FS = NativeOSFS(), **kwargs) -> collections.abc.Iterator[tuple[types.Simfile, str]] Open a pack of simfiles from the pack's directory path; yields (simfile, filename) tuples. Only immediate subdirectories of :code:`pack_dir` containing an SM or SSC file are included. Simfiles aren't guaranteed to appear in any particular order. If both SSC and SM are present, SSC is preferred. Keyword arguments are passed down to :func:`simfile.open`. If you need more flexibility (for example, if you need the pack's banner, or both the SM and SSC files), try using :class:`.SimfilePack`. .. py:exception:: CancelMutation Bases: :py:obj:`BaseException` Raise this exception from inside a :func:`mutate` block to prevent saving the simfile. .. py:function:: mutate(input_filename: str, output_filename: str | None = None, backup_filename: str | None = None, try_encodings: list[str] = ENCODINGS, strict: bool = True, filesystem: _private.fs.FS = NativeOSFS(), **kwargs) -> collections.abc.Iterator[types.Simfile] Context manager that loads a simfile by filename, runs its `with` block, then saves the simfile back to disk. If an `output_filename` is provided, the modified simfile will be written to that filename upon exit from the context manager. If no `output_filename` is provided, the modified simfile will be written back to the `input_filename` instead. If a `backup_filename` is provided, the *original* simfile will additionally be written to that filename upon exit from the context manager. Otherwise, no backup copy will be written. `backup_filename` must be distinct from `input_filename` and `output_filename` if present. If the context manager catches an exception, nothing will be written to disk, and the exception will be re-thrown. To prevent saving without causing the context manager to re-throw an exception, raise :class:`CancelMutation`. This function uses :func:`open_with_detected_encoding` under the hood to detect & preserve the input file's encoding. The list of encodings can be overridden by supplying `try_encodings`. Any extra `kwargs` are passed to the builtin :code:`open` function.