cli.console: refactor and split into two streams#6461
Conversation
def86ea to
4ef3669
Compare
gravyboat
left a comment
There was a problem hiding this comment.
Thanks for breaking this up in to several commits, made it much easier to review each chunk. Made a couple non-blocking notes. Feel free to address or not address whatever you prefer.
4ef3669 to
e89fb5c
Compare
|
Some quick checks... Will extend this later with the remaining checks... I have to go AFK now. I/O streamsmaster PR PromptsUsing a plugin which has required arguments and thus triggers a prompt without those args being set master PR --quietmaster PR |
c5a9226 to
9b01dca
Compare
|
f2b7764 is probably unnecessary if we re-arrange the commits. I'll have a look at this again some time next week. |
9b01dca to
3a33046
Compare
Use the same method name as the public interface of UserInputRequester
- Raise `OSError` instead of returning `None` on error - Check for valid input and output streams when prompting the user - Pass-through `KeyboardInterrupt` - Fix typing - Update tests
Allow the primary output stream to be `None`: Users should be able to disable console output as a whole via `--quiet` (upcoming changes). Use a secondary stream for writing messages into a file: Inherit the `--logfile` stream from the filehandler of Streamlink's root logger (upcoming changes), but skip it if it's a TTY stream, so `--logfile=/dev/stdout` doesn't result in log message duplication.
When `--logfile=file` is set, write console output messages both to the default output stream and the log file stream instead of overriding the console output stream with the log file stream. Log messages will still follow the log file stream, if `--logfile=file` is set, and won't appear on the default output stream, just like before. If `--logfile=/dev/tty` (and similar) is set, ignore the log file stream on the `ConsoleOutput`, so messages won't be duplicated. Refactor and split up `setup_logger_and_logger()` into `setup_console()` and `setup_logger()`. Add `silent_log` attribute on the `args` object (`argparse.Namespace`).
Before creating the `StreamHandler`, check if `stream` exists, rather than letting the stdlib check for its existence when initializing the handler object and falling back to `stderr`. If the passed stream does not exist, then don't attach any handlers to the root logger and prevent logging this way instead of using a devnull `FileHandler` if `stderr` also does not exist.
Let the `ConsoleOutput` use `stderr` if `stdout` does not exist. Since Streamlink's root logger inherits the `ConsoleOutput` stream, the fallback mechanism is also inherited (see previous commit).
3a33046 to
863094d
Compare
Original PR #6461 by bastimeyer Original: streamlink/streamlink#6461
Merged from original PR #6461 Original: streamlink/streamlink#6461
Replaces #6457
In preparation for #6449
This PR fixes a couple of console output issues and logger setup issues, and also splits the console output into two streams. The separation of console output streams is necessary in order for the download progress to be fixed later on. Progress output should never be written to a file, but since we want some console output to be written to log files as well, especially error messages, we need to use two streams.
Currently on master, the
ConsoleOutputalways inherits the stream of Streamlink's root logger. This is problematic because--logfile=...sets the logger stream to a file, which means allConsoleOutputincluding user prompts are written to the log file instead of being written to a TTY where the user has to write their input.Also,
--quietcurrently does only affect the log level, as it's treated as an alias of--loglevel=none, which means the inherited output stream is stillstdout, so all console messages and error messages are printed regardless.--quietshould mean no output at all.Another problem is that if there's no TTY output for user prompts, those prompts currently don't fail. If the user doesn't have a chance to know what's prompted, then the prompt must fail. And failure is currently also not handled correctly and
Noneis returned instead, which is wrong.I've decided to use one single PR branch for these changes, because they are all a bit intertwined. Splitting this up would make this unnecessarily complicated for me.
So, a quick overview of the individual commits:
ConsoleOutputpassword prompt according to Streamlink's public interface of theUserInputRequesterOSErroron failure, and most importantly, check for valid input and output TTY streams (must exist and must not be file streams).Streamlinksession'sUserInputRequesterand that instead calls theask()method of theConsoleOutputdirectly.ConsoleOutputand use two separate streams, one for console output and one for file output. Both are optional, asstdout/stderrcan be missing, or there's no log file stream. Also ensure that the file output is not a TTY, so that--logfile=/dev/ttydoesn't duplicate console messages (asmsg()andmsg_json()write to both streams).ConsoleOutputand Streamlink's root logger and actually use two separate streams. Make the root logger inherit the primary stream of theConsoleOutput(not the other way around). If there's a log file, attach the file stream to theConsoleOutputinstance.loggingmodule of Python's stdlib switched tostderrif the passed stream wasNone, and we also had to check ifstderrexisted and use an additional fallback to devnull as aFileHandlerin that case. Simply don't attach any log handlers to the root logger if there's the passed stream isNone.ConsoleOutputfall back fromstdouttostderrifstdoutdoesn't exist, to align with the previous fallback mechanic of the root logger that was removed in the previous commit. Since the primaryConsoleOutputstream is inherited by the logger now, the old behavior is restored. But now, both console and log output have a fallback.--quietsuppress all text output, not just log output.Considering that there are a lot of changes, this needs a bit of additional testing before I'm going to merge this. As always, I've added tests with full coverage for the changed code parts, but this doesn't cover all potential combinations of CLI arguments and environments.