- Add pytest config to pyproject.toml
- Set pytest 6.0.0 as minimum version via dev-requirements.txt
- Remove unneeded filterwarnings("always") calls from tests
- 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
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
The `parse_{cookies,headers,query_params}` methods were added when the
subclass of `requests.Session` was implemented in order to support
setting cookies, headers and query parameters via `k1=v1;k2=v2` strings
(in addition to key-value dicts) via the session API and via the CLI:
- 936e66dd90
- c6e54fd57a
Since these methods implement logic purely for the `Streamlink` session
interface and are not meant to be called by any plugin or stream
implementations which use the session's `HTTPSession` instance, they
should be removed. Cookies, headers and query string parameters should
be set directly on their respective `HTTPSession` attributes:
- `cookies`: instance of `requests.cookies.RequestsCookieJar`
- `headers`: instance of `requests.structures.CaseInsensitiveDict`
- `params`: instance of `dict`
Also, at least in regards to HTTP headers, the `key=value` syntax
does not reflect the syntax of raw HTTP requests/responses or interfaces
of other tools like cURL, etc., so having these methods on the
`HTTPSession` class makes it unnecessarily confusing. The method names
themselves are also confusing, as they suggest that the input gets
parsed and that some result gets returned, which is wrong.
This commit therefore moves the `k1=v1;k2=v2` string logic from the
`http_session` module to the `session` module where it belongs and it
also simplifies the option setter.
This changes the way how the Streamlink session and other objects like
the plugin cache and logger are stored on each plugin.
Previously, those objects were set as class attributes on every `Plugin`
class via `Plugin.bind()` when loading plugins via the session's
`load_plugins()` method that gets called on initialization.
This meant that whenever a new Streamlink session was initialized,
references to it (including a dict of every loaded plugin) were set
on each `Plugin` class as a class attribute, and Python's garbage
collector could not get rid of this memory when deleting the session
instance that was created last.
Removing `Plugin.bind()`, passing the session via the `Plugin.__init__`
constructor, and setting the cache, logger, etc. on `Plugin` instances
instead (only one gets initialized by `streamlink_cli`), removes those
static references that prevent the garbage collector to work.
Since the plugin "module" name now doesn't get set via `Plugin.bind()`
anymore, it derives its name via `self.__class__.__module__` on its own,
which means a change of the return type of `Streamlink.resolve_url()`
is necessary in order to pass the plugin name to `streamlink_cli`,
so that it can load config files and initialize plugin arguments, etc.
Breaking changes:
- Remove `Plugin.bind()`
- Pass the `session` instance via the Plugin constructor and set the
`module`, `cache` and `logger` on the plugin instance instead.
Derive `module` from the actual module name.
- Change the return type of `Session.resolve_url()` and include the
resolved plugin name in the returned tuple
Other changes:
- Remove `pluginclass.bind()` call from `Session.load_plugins()` and
use the loader's module name directly on the `Session.plugins` dict
- Remove initialization check from `Plugin` cookie methods
- Update streamlink_cli.main module according to breaking changes
- Update tests respectively
- Add explicit plugin initialization test
- Update tests with plugin constructors and custom plugin names
- Move testplugin override module, so that it shares the same module
name as the main testplugin module. Rel `Session.load_plugins()`
- Refactor most session tests and replace unneeded `resolve_url()`
wrappers in favor of calling `session.streams()`
- Import urllib3 directly instead of importing from requests.packages
- Remove unneeded urllib3.contrib.pyopenssl.DEFAULT_SSL_CIPHER_LIST
override, as it's not used on py3
- Update ipv4/ipv6 tests, add http-disable-dh tests
- drop RTMP stream implementation
- drop RTMP plugin
- drop RTMPDump dependency
- remove stream.streamprocess and utils.{rtmp,swf}
- remove "rtmp" from default stream types list
- remove "rtmp" from player-passthrough options list
- remove all `--rtmp*` CLI args and `rtmp-*` session options
- remove all `--subprocess-*` CLI args and `subprocess` session options,
as these were used only by StreamProcess which is no longer needed
- update tests
- update docs and CLI argument help texts
- drop HDS and AkamaiHD stream implementations
- drop HDS and AkamaiHD plugins
- drop streamlink.packages.flashmedia
- remove stream.flvconcat, stream.playlist and plugins.common_swf
- remove "hds" from default stream types list
- remove all `--hds-*` CLI arguments and `hds-*` session options
- remove unneeded flashmedia license text files
- update tests
- update docs and CLI argument help texts
Breaking change:
Instead of resolving a plugin instance in `Streamlink.resolve_url(url)`
from the provided input URL (which can be redirected), resolve the
plugin class and the resulting URL, and cache the tuple. Also affects
`Streamlink.resolve_url_no_redirect(url)`.
The main reason for this change is streamlink_cli and how the plugin
options get set. The plugin options need to be set on the class before
it gets initialized, so that the instance can access the options in its
constructor method. This also fixes any kind of state stored on the
plugin instance.
- resolve and cache a tuple of the plugin class and resulting URL
- initialize plugin in streamlink_cli after applying its options
- remove plugin variable from global scope in streamlink_cli
- fix, rewrite and add tests
- bump websocket-client requirement to >=1.2.1,<2.0
- avoid circular import by importing HTTPSession in session directly
- implement a common WebsocketClient based on the WebSocketApp API of
websocket-client, so that plugins don't have to re-implement basic
boilerplate code
- automatically apply User-Agent header
- automatically apply proxy settings
- set websocket log level (globally)
- add tests
Apply the https scheme to all input URLs if the scheme is missing:
- session:
- Session.resolve_url()
- session option `http-proxy` (`--http-proxy` CLI argument)
- plugins.akamaihd: `akamaihd://URL`
- plugins.dash: `dash://URL` or `URL.mpd`
- plugins.hds: `hds://URL` or `URL.f4m`
- plugins.hls: `hls://URL` or `URL.m3u8`
- plugins.http: `httpstream://URL`
Regular http URLs (non-https/TLS) will need to be set explicitly now.
Also
- update/fix test_session
- refactor/fix test_dash
- refactor/fix test_stream
Resolve deprecated plugins which are using the old
`can_handle_url(url)` and `priority(url)` methods.
Since the `Plugin` class doesn't implement the `priority` classmethod
with the NORMAL_PRIORITY return value anymore, the NORMAL_PRIORITY
gets set by the resolver if the method is missing on plugins which
implement `can_handle_url` and don't have the `matchers` list.
- drop `Plugin.can_handle_url` and `Plugin.priority`
- introduce `Plugin.matchers`
- implement `pluginmatcher` decorator
- automatically match url (on change) and store result
- update `Session.resolve_url`
- add and fix related tests
- move testplugin and its related files into their own `tests/plugin`
directory, so that tests don't have to unnecessarily import regular
plugin test files
- refactor test_session
- don't initialize session in `setUp`
- add test cases for ImportError and SyntaxError
- add assertion for plugin override debug log call
- rename "load_plugins" test cases
- rename some confusing variable names
- fix remaining tests in regards to the testplugin path changes
Refactor `utils.load_module`:
- move it to the top and add it to `__all__`
- move imports and loader_details to the global scope
Refactor `session`:
- replace plugin imports via `imp` with `utils.load_module`
- fix incorrect plugin module names
"streamlink.plugin.{name}" -> "streamlink.plugins.{name}"
- use `log.exception()` to print plugin load failures
- remove unused `print_small_exception`
Add / fix tests:
- remove session dependency from test_plugins
- add proper assertions for plugin modules, methods and their signatures
- add tests for invalid and for overridden plugins
Add special stream synonyms "best-unfiltered" and "worst-unfiltered" in
cases when all available streams have been filtered out by the
`--stream-sorting-excludes` parameter and the "best" and "worst" stream
synonyms don't exist. These new synonyms point towards the respective
streams of the unfiltered streams list so that the user is able to
select a fallback stream.
Example:
streamlink --stream-sorting-excludes '>=480p' URL best,best-unfiltered
Will try to open the best stream below 480p, but if none is available
will continue with the best of all streams as a fallback selection.
Resolves#1055
- removed versionchange references as Streamlink does not use it.
- removed old code that was deprecated in Livestreamer
- removed DeprecatedWarning for 2.6 as it is already mentioned in
`setup.py`
a14f170a04/setup.py (L82)
- removed unittest2
- Flake8 for some lines/files that I changed.
* tests: logger tests
* test: file stream
* test: missing sessions tests
* test: missing util tests
* tests: call can_handle_url for each plugin to ensure it won't error
* tests: speed up by 2 seconds, mocking sleep
* test for streamname lookups
* refactor test structure
* tests: rebase plugins tests
* tests: no need for Python 3.6 support
* tests: remove 2.6 from the travis build
* tests: rebase on master
* tests: rename plugin.api tests
* tests: add mock http resource
* move new plugin tests
* rebase master
* tests: coverage for ConsoleOutput
* API for plugins to request input from the user
* console: handle lack of TTY for user input
* New fatal plugin error, for unrecoverable errors
* tests: remove deprecated calls
* stream.dash: parser for dash manifest files
* stream.dash: stream player for dash with plugin to support dash:// prefixed urls
* cli.main: make sure that streams are closed on errors
* stream.dash: fix some parsing bugs
* stream.dash: tidy up the segment number generation
* plugins.dash: wip segment timeline
* stream.dash: update to segment timeline parsing
* stream.dash: py3 support
* stream.dash: raise an error for DRM protected streams
* stream.dash: fixes for timescaling and some segment templates
* docs: add DASHStream to docs with other Stream classes
* dash: fix for video only stream
* plugins.dash: fix bug where all URLs were matched
* stream.dash: fix issue with manifest reload
* plugin.dash: add tests and fix a couple of bugs found in testing
* stream.dash: add some tests to cover the DASHStream classes
* WIP: audio only streams
* add some debugging for threads and remove the thread joins
* dash: startNumber should default to 1
* dash: follow redirects to get the base url
* dash: fix bool parser, and segment template parser
* dash: fixed some issues...
...with some segment templates, as well as improving the presentation
delay handling
* dash: add a back-off for checking for manifest changes
* dash: fix broken tests
* dash: incomplete support for Segment@r
* dash: fixed audio/video sync issue
Added a `copyts` option to the FFMPEG muxer class so that the timestamps
given in the source files are maintained, this appears to fix the a/v
sync issues.
NB. The timestamp can get weird, but that's how it is :)
* dash: support for Time _and_ Number in segment timeline
* tests: add some dash parser tests + a little refactor
* tests: add dash to built in plugins
* tests: more coverage of dash_parser
Added a new module for tests, `freezegun`, for mocking time.
* dash: fix for missing publishTime
* dash: update available_at times to be datetime
This should fix any timezone or leap-second issues, etc.
* fixed timing issue for 1tv.ru
* dash: fix availability timeline for segment timeline
* dash: flake8 tweaks
* dash: add a few debug logging messages
Plugins can return a priority level for the URLs that they support.
If two plugins match the same URLs then the plugin with the higher
priority will be used. This means that the built-in HLS and HDS
plugins can support `.m3u8` and `.f4m` URLs with a lower priority
without causing issues with overlapping URL patterns.
By default plugins return NORMAL priority for any URL. It is expected
that the `priority` method will only be called with URLs that are
actually supported by the plugin.