Make sure that each substream's buffer always gets fully emptied
when closing the stream, so that no data is missing when muxing
the output stream.
TODO: properly refactor FFMPEGMuxer class with full test coverage
- Rewrite and fix attribute list regex
- Be more strict when parsing multiple attributes and expect the
mandatory comma separator, but be lenient about spaces surrounding
attributes (off-spec), similar to the old implementation
- Add missing support for signed decimal floating point numbers
- Fix invalid range of hexadecimal sequences and allow uppercase prefix
- Fix character range of enumerated strings being too narrow
- Fix character range of quoted strings
- Discard entire attribute list on parsing failure and emit warning
- Add unit tests
- Raise `StreamlinkDeprecationWarning` when `is_global=True`
- Remove all global plugin arguments and replace them with simple
option lookups on the Streamlink session instance
- Remove global argument detection in custom Sphinx plugins extension
- Remove supported plugins list from custom Sphinx argparse extension
and remove respective setup from `setup_plugin_args` in the CLI module
- Add deprecation note to the docs
- Update tests
- Check whether builtin plugins define global plugin arguments
- Capture deprecation warnings
- Deprecate text alias and raise StreamlinkDeprecationWarning on access
- Add deprecation to docs
- Replace validate.text with str in remaining plugins
- Update test
- Add `StreamlinkWarning` and `StreamlinkDeprecationWarning`
and replace `FutureWarning`s
- Don't include the warning's origin in the warning logger if it's a
subclass of `StreamlinkWarning`
- Update tests
Add support for capturing warnings and logging them via Streamlink's
root logger on the warning log level. Use custom `WarningLogRecord`s
with a custom warning message format, and replace the record's
logger name with "warnings" and use the name of the warning type
as log level name when showing warnings.
This enables having proper `DeprecationWarning`s and `FutureWarning`s
in the code instead of just using the logger and its warning log level,
and those warnings can be filtered via the regular filtering mechanisms.
For example:
```
[warnings][deprecationwarning] Calling this method is deprecated
[warnings][futurewarning] Using this config file path is deprecated
```
- Make `NoPluginError` inherit from `StreamlinkError`
instead of `PluginError`
- Update and fix docstrings of all Streamlink exception classes
- Update list of exceptions in API docs
- Fix exports
Replace the logic of the `Streamlink.{get,set}_option()` methods with
a new `StreamlinkOptions` subclass which uses mapped option
getters+setters that apply the custom option logic instead.
This improves the runtime of said methods, as option mappers are
looked up in Python dictionaries in constant time, so option names
don't have to be checked one after another.
Also add deprecation messages when
- getting the deprecated `https-proxy` option
- setting the deprecated `{hls,dash}-segment-attempts` options
- setting the deprecated `{hls,dash}-segment-threads` options
- setting the deprecated `{hls,dash}-segment-timeout` options
- setting the deprecated `{hls,dash,http-stream}-timeout` options
- Store key names with dashes instead of underscore characters.
This makes it consistent with the default Streamlink session options.
- Add typing information
Replace `read_stream()` with a new `StreamRunner` class, refactor stream
reads and output writes, as well as the progress thread data feeding,
and move player polling into a separate thread which closes the stream
once the player process gets terminated/killed.
This fixes the player polling issue, or rather the detection of its
broken pipe while reading the stream, as stream read calls can stall
for various reasons, e.g. due to segmented streams or the filtering
of stream data which pauses the stream output and disables any timeouts.
- Implement `StreamRunner` and `PlayerPollThread` classes
in dedicated `streamlink_cli.streamrunner` module
- Remove old `streamlink_cli.main.read_stream()` implementation
- Keep the same log messages
- Make `StreamRunner.run()` raise `OSError` on read/write error and
catch `OSError`s in main module where `console.exit()` gets called
- Remove `Progress.iter()`, as it's not needed anymore
- Add extensive tests with full code coverage
Rename `Progress.put()` to `Progress.write()`, to make it consistent
with other output related interfaces:
`PlayerOutput`, `FileOutput` and `HTTPServer`
- Turn filename into a Path and accept "pathlike" values
- Fix file handle not being closed on error when serializing data
- Add typing information
- Add TO-DO comments
- Rewrite tests
- Switch to pytest
- Use pytests's tmp_path fixture instead of custom temp path stuff
- Properly freeze time during expiration tests
- Rename test file to match module file name
- Switch to pytest
- Add more strict assertions to existing tests
- Add more basic tests and new tests for threaded read/write calls of
the `RingBuffer` for full code coverage
- Refactor `TwitchAPI` class:
- Set `CLIENT_ID` as a class attribute (for test references)
- Allow `call()` to pass custom headers (currently unused)
- Remove unneeded `json.dumps()`
- Handle `PlaybackAccessToken` error response and log error messages
- Add `Options.clear()` for resetting plugin options state after tests
- Add access token API tests
Twitch doesn't include duration data for prefetch segments, which means
when more than one prefetch segment is included in the HLS playlist,
the start time of the second (or third) prefetch segment has to be
guessed from the duration of the regular segments. This is done by
calculating the average of all available regular segments and using that
as an offset of the last regular segment for each prefetch segment.
This however can cause issues when segment durations vary a lot and the
start time of an annotated ad block doesn't match the extrapolated start
time of the first ad segment due to the miscalculation. The ad segment
then gets incorrectly included in the output stream.
Since a discontinuity tag is always present, even between prefetch tags
with ads, we can make use of it and treat prefetch segments after a
discontinuity tag as ads. This won't cause any issues during the
transition to the regular stream content, as it only affects the logic
of prefetch segments.
- Fix channel ID lookup
- Fix validation schema on missing data
- Add more stream types to live streams: HTTPStream for content
restriction clips, and DASHStream where HLS is not available
- Apply minor code refactoring
- Add `certifi` as a direct dependency (already defined by `requests`)
and don't set a version range
- Set the `ca_certs` SSL option in `WebsocketClient` which defaults to
the CA certs file bundled by `certifi`, similar to HTTPS requests
made by `requests`
Streamlink currently sets the version range of its `requests` dependency
to `>=2.26.0,<3.0`. `requests` however still defines its `urllib3`
dependency version range as `>=1.21.1,<1.27` in its `2.26.0`-`2.28.1`
releases, including its current state in git.
Recent fixes in Streamlink's HLS implementation unfortunately were made
with methods which are only supported by `urllib3 >=1.26.0`.
This obviously breaks installs with older versions of `urllib3`
installed which are still supported by the defined version range.
In order to avoid having to backport more `urllib3` stuff, moving it
from a transitive dependency and defining it as a direct dependency
with a specific version range set to `>=1.26.0` makes more sense when
fixing the issue. This doesn't conflict with the version range defined
by `requests` and forces a bump of old installs of `urllib3`.
`urllib3==1.26.0` was released on 2020-11-10, whereas
`requests==2.26.0`, was released on 2021-07-13, the lowest version
of the version range defined by Streamlink.
---
In addition to defining the direct `urllib3` dependency, also remove
old compatibility workarounds/bugfixes from `plugin.api.http_session`.
- Move list of files from CI config to mypy config in pyproject.toml,
so that mypy can be run locally without having to specificy the same
inputs as CLI arguments. Keep --no-incremental exclusive to CI runner.
- Update Python version of mypy CI runner.
- Fix typing ignore comment when importing importlib_metadata fallback
in the streamlink_cli.compat module.