ssato / python-anyconfig

Python library provides common APIs to load and dump configuration files in various formats
MIT License
275 stars 31 forks source link

crash when dumping to stdout with colorama enabled (windows only). #139

Closed gsemet closed 2 years ago

gsemet commented 2 years ago

When colorama is enabled, the factory crashes with an error

...
  File "C:\Some\Path\.venv\lib\site-packages\anyconfig\ioinfo\factory.py", line 69, in make
    return from_io_stream(obj)
  File "C:\Some\Path\.venv\lib\site-packages\anyconfig\ioinfo\factory.py", line 39, in from_io_stream
    (abs_path, file_ext) = utils.get_path_and_ext(pathlib.Path(path))
  File "C:\Some\Path\.venv\lib\site-packages\anyconfig\ioinfo\utils.py", line 17, in get_path_and_ext
    abs_path = path.expanduser().resolve()
  File "C:\Users\username\AppData\Local\Programs\Python\Python37\lib\pathlib.py", line 1166, in resolve
    s = self._flavour.resolve(self, strict=strict)
  File "C:\Users\username\AppData\Local\Programs\Python\Python37\lib\pathlib.py", line 205, in resolve
    s = self._ext_to_normal(_getfinalpathname(s))
OSError: [WinError 123] La syntaxe du nom de fichier, de r▒pertoire ou de volume est incorrecte: '<stdout>'

the anyconfig.ioinfo.factory.make function receives a colorama.ansitowin32.StreamWrapper object that fails in the call to get_path_and_ext, but only on windows.

gsemet commented 2 years ago

this probably comes the fact "\<stdout>" has invalid character for window filesystem, and it is just ignored on mac/linux...

this is not linked to colorama

ssato commented 2 years ago

Thanks for your report! I'll take a look at the issue this weekend.

gsemet commented 2 years ago

I have worked around it with this code:

def anydump_stdout(data: Any, fmt: str = "json") -> None:
    """Dump data structure to standart output sys.stdout.

    Supports the following format:

     - ``yaml```: Yaml
     - ``ini``: INI (do not use complex nested structure such as list, set, dict)
     - ``toml``: Toml
     - ``json``: JSON
    """

    # Standard Library
    from sys import stdout

    if fmt == "yaml":
        fmt = "ruamel.yaml"

    # manually create the IOInfo to skip the anyconfig magic which crashs on
    # Windows because it tries to create a pathlib.Path with the name "<name>",
    # which contains invalid character for a filename on Windows File system.
    # Third Party Libraries
    from anyconfig.ioinfo.factory import datatypes

    ioinfo = datatypes.IOInfo(stdout, datatypes.IOI_STREAM, "<stdout>", "")
    anyconfig.dump(data, ioinfo, ac_parser=fmt, **_anyconfig_kwargs())
    print("")
    stdout.flush()
ssato commented 2 years ago

I pushed an experimental fix as #140 and merged it into the next branch. Could you please try it if that fix is correct or not?