Reading/Writing From File or Stdin/Stdout

In many CLI applications, it's common to be able to read from a file or stdin, and write to a file or stdout. This allows for the chaining of many CLI applications via pipes |. The following code demonstrates how to do this with Cyclopts:

import sys
from cyclopts import App
from pathlib import Path
from typing import Optional

def read_str(input_: Optional[Path]) -> str:
    return sys.stdin.read() if input_ is None else input_.read_text()

def write_str(output: Optional[Path], data: str):
    sys.stdout.write(data) if output is None else output.write_text(data)

def read_bytes(input_: Optional[Path]) -> bytes:
    return sys.stdin.buffer.read() if input_ is None else input_.read_bytes()

def write_bytes(output: Optional[Path], data: bytes):
    sys.stdout.buffer.write(data) if output is None else output.write_bytes(data)

app = App()

@app.default
def scream(input_: Optional[Path] = None, output_: Optional[Path] = None):
    """Uppercase all input data.

    Parameters
    ----------
    input_ : Optional[Path]
        If provided, read data from file. If not provided, read from stdin.
    output_ : Optional[Path]
        If provided, write data to file. If not provided, write to stdout.
    """
    data = read_str(input_)
    processed = data.upper()
    write_str(output_, processed)

if __name__ == "__main__":
    app()
$ echo "hello cyclopts users." > demo.txt
$ python scream.py demo.txt
HELLO CYCLOPTS USERS.
$ python scream.py demo.txt output.txt
$ cat output.txt
HELLO CYCLOPTS USERS.
$ echo "foo" | python scream.py
FOO