mirror of
				https://github.com/yt-dlp/yt-dlp.git
				synced 2025-11-04 08:35:12 +00:00 
			
		
		
		
	https://github.com/yt-dlp/yt-dlp/tree/master/yt_dlp/extractor/youtube/pot/README.md Authored by: coletdjnz
		
			
				
	
	
		
			630 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			630 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
import pytest
 | 
						|
 | 
						|
from yt_dlp.extractor.youtube.pot._provider import IEContentProvider
 | 
						|
from yt_dlp.cookies import YoutubeDLCookieJar
 | 
						|
from yt_dlp.utils.networking import HTTPHeaderDict
 | 
						|
from yt_dlp.extractor.youtube.pot.provider import (
 | 
						|
    PoTokenRequest,
 | 
						|
    PoTokenContext,
 | 
						|
    ExternalRequestFeature,
 | 
						|
 | 
						|
)
 | 
						|
 | 
						|
from yt_dlp.extractor.youtube.pot.cache import (
 | 
						|
    PoTokenCacheProvider,
 | 
						|
    PoTokenCacheSpec,
 | 
						|
    PoTokenCacheSpecProvider,
 | 
						|
    CacheProviderWritePolicy,
 | 
						|
)
 | 
						|
 | 
						|
import yt_dlp.extractor.youtube.pot.cache as cache
 | 
						|
 | 
						|
from yt_dlp.networking import Request
 | 
						|
from yt_dlp.extractor.youtube.pot.provider import (
 | 
						|
    PoTokenResponse,
 | 
						|
    PoTokenProvider,
 | 
						|
    PoTokenProviderRejectedRequest,
 | 
						|
    provider_bug_report_message,
 | 
						|
    register_provider,
 | 
						|
    register_preference,
 | 
						|
)
 | 
						|
 | 
						|
from yt_dlp.extractor.youtube.pot._registry import _pot_providers, _ptp_preferences, _pot_pcs_providers, _pot_cache_providers, _pot_cache_provider_preferences
 | 
						|
 | 
						|
 | 
						|
class ExamplePTP(PoTokenProvider):
 | 
						|
    PROVIDER_NAME = 'example'
 | 
						|
    PROVIDER_VERSION = '0.0.1'
 | 
						|
    BUG_REPORT_LOCATION = 'https://example.com/issues'
 | 
						|
 | 
						|
    _SUPPORTED_CLIENTS = ('WEB',)
 | 
						|
    _SUPPORTED_CONTEXTS = (PoTokenContext.GVS, )
 | 
						|
 | 
						|
    _SUPPORTED_EXTERNAL_REQUEST_FEATURES = (
 | 
						|
        ExternalRequestFeature.PROXY_SCHEME_HTTP,
 | 
						|
        ExternalRequestFeature.PROXY_SCHEME_SOCKS5H,
 | 
						|
    )
 | 
						|
 | 
						|
    def is_available(self) -> bool:
 | 
						|
        return True
 | 
						|
 | 
						|
    def _real_request_pot(self, request: PoTokenRequest) -> PoTokenResponse:
 | 
						|
        return PoTokenResponse('example-token', expires_at=123)
 | 
						|
 | 
						|
 | 
						|
class ExampleCacheProviderPCP(PoTokenCacheProvider):
 | 
						|
 | 
						|
    PROVIDER_NAME = 'example'
 | 
						|
    PROVIDER_VERSION = '0.0.1'
 | 
						|
    BUG_REPORT_LOCATION = 'https://example.com/issues'
 | 
						|
 | 
						|
    def is_available(self) -> bool:
 | 
						|
        return True
 | 
						|
 | 
						|
    def get(self, key: str):
 | 
						|
        return 'example-cache'
 | 
						|
 | 
						|
    def store(self, key: str, value: str, expires_at: int):
 | 
						|
        pass
 | 
						|
 | 
						|
    def delete(self, key: str):
 | 
						|
        pass
 | 
						|
 | 
						|
 | 
						|
class ExampleCacheSpecProviderPCSP(PoTokenCacheSpecProvider):
 | 
						|
 | 
						|
    PROVIDER_NAME = 'example'
 | 
						|
    PROVIDER_VERSION = '0.0.1'
 | 
						|
    BUG_REPORT_LOCATION = 'https://example.com/issues'
 | 
						|
 | 
						|
    def generate_cache_spec(self, request: PoTokenRequest):
 | 
						|
        return PoTokenCacheSpec(
 | 
						|
            key_bindings={'field': 'example-key'},
 | 
						|
            default_ttl=60,
 | 
						|
            write_policy=CacheProviderWritePolicy.WRITE_FIRST,
 | 
						|
        )
 | 
						|
 | 
						|
 | 
						|
class TestPoTokenProvider:
 | 
						|
 | 
						|
    def test_base_type(self):
 | 
						|
        assert issubclass(PoTokenProvider, IEContentProvider)
 | 
						|
 | 
						|
    def test_create_provider_missing_fetch_method(self, ie, logger):
 | 
						|
        class MissingMethodsPTP(PoTokenProvider):
 | 
						|
            def is_available(self) -> bool:
 | 
						|
                return True
 | 
						|
 | 
						|
        with pytest.raises(TypeError):
 | 
						|
            MissingMethodsPTP(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
    def test_create_provider_missing_available_method(self, ie, logger):
 | 
						|
        class MissingMethodsPTP(PoTokenProvider):
 | 
						|
            def _real_request_pot(self, request: PoTokenRequest) -> PoTokenResponse:
 | 
						|
                raise PoTokenProviderRejectedRequest('Not implemented')
 | 
						|
 | 
						|
        with pytest.raises(TypeError):
 | 
						|
            MissingMethodsPTP(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
    def test_barebones_provider(self, ie, logger):
 | 
						|
        class BarebonesProviderPTP(PoTokenProvider):
 | 
						|
            def is_available(self) -> bool:
 | 
						|
                return True
 | 
						|
 | 
						|
            def _real_request_pot(self, request: PoTokenRequest) -> PoTokenResponse:
 | 
						|
                raise PoTokenProviderRejectedRequest('Not implemented')
 | 
						|
 | 
						|
        provider = BarebonesProviderPTP(ie=ie, logger=logger, settings={})
 | 
						|
        assert provider.PROVIDER_NAME == 'BarebonesProvider'
 | 
						|
        assert provider.PROVIDER_KEY == 'BarebonesProvider'
 | 
						|
        assert provider.PROVIDER_VERSION == '0.0.0'
 | 
						|
        assert provider.BUG_REPORT_MESSAGE == 'please report this issue to the provider developer at  (developer has not provided a bug report location)  .'
 | 
						|
 | 
						|
    def test_example_provider_success(self, ie, logger, pot_request):
 | 
						|
        provider = ExamplePTP(ie=ie, logger=logger, settings={})
 | 
						|
        assert provider.PROVIDER_NAME == 'example'
 | 
						|
        assert provider.PROVIDER_KEY == 'Example'
 | 
						|
        assert provider.PROVIDER_VERSION == '0.0.1'
 | 
						|
        assert provider.BUG_REPORT_MESSAGE == 'please report this issue to the provider developer at  https://example.com/issues  .'
 | 
						|
        assert provider.is_available()
 | 
						|
 | 
						|
        response = provider.request_pot(pot_request)
 | 
						|
 | 
						|
        assert response.po_token == 'example-token'
 | 
						|
        assert response.expires_at == 123
 | 
						|
 | 
						|
    def test_provider_unsupported_context(self, ie, logger, pot_request):
 | 
						|
        provider = ExamplePTP(ie=ie, logger=logger, settings={})
 | 
						|
        pot_request.context = PoTokenContext.PLAYER
 | 
						|
 | 
						|
        with pytest.raises(PoTokenProviderRejectedRequest):
 | 
						|
            provider.request_pot(pot_request)
 | 
						|
 | 
						|
    def test_provider_unsupported_client(self, ie, logger, pot_request):
 | 
						|
        provider = ExamplePTP(ie=ie, logger=logger, settings={})
 | 
						|
        pot_request.innertube_context['client']['clientName'] = 'ANDROID'
 | 
						|
 | 
						|
        with pytest.raises(PoTokenProviderRejectedRequest):
 | 
						|
            provider.request_pot(pot_request)
 | 
						|
 | 
						|
    def test_provider_unsupported_proxy_scheme(self, ie, logger, pot_request):
 | 
						|
        provider = ExamplePTP(ie=ie, logger=logger, settings={})
 | 
						|
        pot_request.request_proxy = 'socks4://example.com'
 | 
						|
 | 
						|
        with pytest.raises(
 | 
						|
            PoTokenProviderRejectedRequest,
 | 
						|
            match='External requests by "example" provider do not support proxy scheme "socks4". Supported proxy '
 | 
						|
            'schemes: http, socks5h',
 | 
						|
        ):
 | 
						|
            provider.request_pot(pot_request)
 | 
						|
 | 
						|
        pot_request.request_proxy = 'http://example.com'
 | 
						|
 | 
						|
        assert provider.request_pot(pot_request)
 | 
						|
 | 
						|
    def test_provider_ignore_external_request_features(self, ie, logger, pot_request):
 | 
						|
        class InternalPTP(ExamplePTP):
 | 
						|
            _SUPPORTED_EXTERNAL_REQUEST_FEATURES = None
 | 
						|
 | 
						|
        provider = InternalPTP(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
        pot_request.request_proxy = 'socks5://example.com'
 | 
						|
        assert provider.request_pot(pot_request)
 | 
						|
        pot_request.request_source_address = '0.0.0.0'
 | 
						|
        assert provider.request_pot(pot_request)
 | 
						|
 | 
						|
    def test_provider_unsupported_external_request_source_address(self, ie, logger, pot_request):
 | 
						|
        class InternalPTP(ExamplePTP):
 | 
						|
            _SUPPORTED_EXTERNAL_REQUEST_FEATURES = tuple()
 | 
						|
 | 
						|
        provider = InternalPTP(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
        pot_request.request_source_address = None
 | 
						|
        assert provider.request_pot(pot_request)
 | 
						|
 | 
						|
        pot_request.request_source_address = '0.0.0.0'
 | 
						|
        with pytest.raises(
 | 
						|
            PoTokenProviderRejectedRequest,
 | 
						|
            match='External requests by "example" provider do not support setting source address',
 | 
						|
        ):
 | 
						|
            provider.request_pot(pot_request)
 | 
						|
 | 
						|
    def test_provider_supported_external_request_source_address(self, ie, logger, pot_request):
 | 
						|
        class InternalPTP(ExamplePTP):
 | 
						|
            _SUPPORTED_EXTERNAL_REQUEST_FEATURES = (
 | 
						|
                ExternalRequestFeature.SOURCE_ADDRESS,
 | 
						|
            )
 | 
						|
 | 
						|
        provider = InternalPTP(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
        pot_request.request_source_address = None
 | 
						|
        assert provider.request_pot(pot_request)
 | 
						|
 | 
						|
        pot_request.request_source_address = '0.0.0.0'
 | 
						|
        assert provider.request_pot(pot_request)
 | 
						|
 | 
						|
    def test_provider_unsupported_external_request_tls_verification(self, ie, logger, pot_request):
 | 
						|
        class InternalPTP(ExamplePTP):
 | 
						|
            _SUPPORTED_EXTERNAL_REQUEST_FEATURES = tuple()
 | 
						|
 | 
						|
        provider = InternalPTP(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
        pot_request.request_verify_tls = True
 | 
						|
        assert provider.request_pot(pot_request)
 | 
						|
 | 
						|
        pot_request.request_verify_tls = False
 | 
						|
        with pytest.raises(
 | 
						|
            PoTokenProviderRejectedRequest,
 | 
						|
            match='External requests by "example" provider do not support ignoring TLS certificate failures',
 | 
						|
        ):
 | 
						|
            provider.request_pot(pot_request)
 | 
						|
 | 
						|
    def test_provider_supported_external_request_tls_verification(self, ie, logger, pot_request):
 | 
						|
        class InternalPTP(ExamplePTP):
 | 
						|
            _SUPPORTED_EXTERNAL_REQUEST_FEATURES = (
 | 
						|
                ExternalRequestFeature.DISABLE_TLS_VERIFICATION,
 | 
						|
            )
 | 
						|
 | 
						|
        provider = InternalPTP(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
        pot_request.request_verify_tls = True
 | 
						|
        assert provider.request_pot(pot_request)
 | 
						|
 | 
						|
        pot_request.request_verify_tls = False
 | 
						|
        assert provider.request_pot(pot_request)
 | 
						|
 | 
						|
    def test_provider_request_webpage(self, ie, logger, pot_request):
 | 
						|
        provider = ExamplePTP(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
        cookiejar = YoutubeDLCookieJar()
 | 
						|
        pot_request.request_headers = HTTPHeaderDict({'User-Agent': 'example-user-agent'})
 | 
						|
        pot_request.request_proxy = 'socks5://example-proxy.com'
 | 
						|
        pot_request.request_cookiejar = cookiejar
 | 
						|
 | 
						|
        def mock_urlopen(request):
 | 
						|
            return request
 | 
						|
 | 
						|
        ie._downloader.urlopen = mock_urlopen
 | 
						|
 | 
						|
        sent_request = provider._request_webpage(Request(
 | 
						|
            'https://example.com',
 | 
						|
        ), pot_request=pot_request)
 | 
						|
 | 
						|
        assert sent_request.url == 'https://example.com'
 | 
						|
        assert sent_request.headers['User-Agent'] == 'example-user-agent'
 | 
						|
        assert sent_request.proxies == {'all': 'socks5://example-proxy.com'}
 | 
						|
        assert sent_request.extensions['cookiejar'] is cookiejar
 | 
						|
        assert 'Requesting webpage' in logger.messages['info']
 | 
						|
 | 
						|
    def test_provider_request_webpage_override(self, ie, logger, pot_request):
 | 
						|
        provider = ExamplePTP(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
        cookiejar_request = YoutubeDLCookieJar()
 | 
						|
        pot_request.request_headers = HTTPHeaderDict({'User-Agent': 'example-user-agent'})
 | 
						|
        pot_request.request_proxy = 'socks5://example-proxy.com'
 | 
						|
        pot_request.request_cookiejar = cookiejar_request
 | 
						|
 | 
						|
        def mock_urlopen(request):
 | 
						|
            return request
 | 
						|
 | 
						|
        ie._downloader.urlopen = mock_urlopen
 | 
						|
 | 
						|
        sent_request = provider._request_webpage(Request(
 | 
						|
            'https://example.com',
 | 
						|
            headers={'User-Agent': 'override-user-agent-override'},
 | 
						|
            proxies={'http': 'http://example-proxy-override.com'},
 | 
						|
            extensions={'cookiejar': YoutubeDLCookieJar()},
 | 
						|
        ), pot_request=pot_request, note='Custom requesting webpage')
 | 
						|
 | 
						|
        assert sent_request.url == 'https://example.com'
 | 
						|
        assert sent_request.headers['User-Agent'] == 'override-user-agent-override'
 | 
						|
        assert sent_request.proxies == {'http': 'http://example-proxy-override.com'}
 | 
						|
        assert sent_request.extensions['cookiejar'] is not cookiejar_request
 | 
						|
        assert 'Custom requesting webpage' in logger.messages['info']
 | 
						|
 | 
						|
    def test_provider_request_webpage_no_log(self, ie, logger, pot_request):
 | 
						|
        provider = ExamplePTP(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
        def mock_urlopen(request):
 | 
						|
            return request
 | 
						|
 | 
						|
        ie._downloader.urlopen = mock_urlopen
 | 
						|
 | 
						|
        sent_request = provider._request_webpage(Request(
 | 
						|
            'https://example.com',
 | 
						|
        ), note=False)
 | 
						|
 | 
						|
        assert sent_request.url == 'https://example.com'
 | 
						|
        assert 'info' not in logger.messages
 | 
						|
 | 
						|
    def test_provider_request_webpage_no_pot_request(self, ie, logger):
 | 
						|
        provider = ExamplePTP(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
        def mock_urlopen(request):
 | 
						|
            return request
 | 
						|
 | 
						|
        ie._downloader.urlopen = mock_urlopen
 | 
						|
 | 
						|
        sent_request = provider._request_webpage(Request(
 | 
						|
            'https://example.com',
 | 
						|
        ), pot_request=None)
 | 
						|
 | 
						|
        assert sent_request.url == 'https://example.com'
 | 
						|
 | 
						|
    def test_get_config_arg(self, ie, logger):
 | 
						|
        provider = ExamplePTP(ie=ie, logger=logger, settings={'abc': ['123D'], 'xyz': ['456a', '789B']})
 | 
						|
 | 
						|
        assert provider._configuration_arg('abc') == ['123d']
 | 
						|
        assert provider._configuration_arg('abc', default=['default']) == ['123d']
 | 
						|
        assert provider._configuration_arg('ABC', default=['default']) == ['default']
 | 
						|
        assert provider._configuration_arg('abc', casesense=True) == ['123D']
 | 
						|
        assert provider._configuration_arg('xyz', casesense=False) == ['456a', '789b']
 | 
						|
 | 
						|
    def test_require_class_end_with_suffix(self, ie, logger):
 | 
						|
        class InvalidSuffix(PoTokenProvider):
 | 
						|
            PROVIDER_NAME = 'invalid-suffix'
 | 
						|
 | 
						|
            def _real_request_pot(self, request: PoTokenRequest) -> PoTokenResponse:
 | 
						|
                raise PoTokenProviderRejectedRequest('Not implemented')
 | 
						|
 | 
						|
            def is_available(self) -> bool:
 | 
						|
                return True
 | 
						|
 | 
						|
        provider = InvalidSuffix(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
        with pytest.raises(AssertionError):
 | 
						|
            provider.PROVIDER_KEY  # noqa: B018
 | 
						|
 | 
						|
 | 
						|
class TestPoTokenCacheProvider:
 | 
						|
 | 
						|
    def test_base_type(self):
 | 
						|
        assert issubclass(PoTokenCacheProvider, IEContentProvider)
 | 
						|
 | 
						|
    def test_create_provider_missing_get_method(self, ie, logger):
 | 
						|
        class MissingMethodsPCP(PoTokenCacheProvider):
 | 
						|
            def store(self, key: str, value: str, expires_at: int):
 | 
						|
                pass
 | 
						|
 | 
						|
            def delete(self, key: str):
 | 
						|
                pass
 | 
						|
 | 
						|
                def is_available(self) -> bool:
 | 
						|
                    return True
 | 
						|
 | 
						|
        with pytest.raises(TypeError):
 | 
						|
            MissingMethodsPCP(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
    def test_create_provider_missing_store_method(self, ie, logger):
 | 
						|
        class MissingMethodsPCP(PoTokenCacheProvider):
 | 
						|
            def get(self, key: str):
 | 
						|
                pass
 | 
						|
 | 
						|
            def delete(self, key: str):
 | 
						|
                pass
 | 
						|
 | 
						|
            def is_available(self) -> bool:
 | 
						|
                return True
 | 
						|
 | 
						|
        with pytest.raises(TypeError):
 | 
						|
            MissingMethodsPCP(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
    def test_create_provider_missing_delete_method(self, ie, logger):
 | 
						|
        class MissingMethodsPCP(PoTokenCacheProvider):
 | 
						|
            def get(self, key: str):
 | 
						|
                pass
 | 
						|
 | 
						|
            def store(self, key: str, value: str, expires_at: int):
 | 
						|
                pass
 | 
						|
 | 
						|
            def is_available(self) -> bool:
 | 
						|
                return True
 | 
						|
 | 
						|
        with pytest.raises(TypeError):
 | 
						|
            MissingMethodsPCP(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
    def test_create_provider_missing_is_available_method(self, ie, logger):
 | 
						|
        class MissingMethodsPCP(PoTokenCacheProvider):
 | 
						|
            def get(self, key: str):
 | 
						|
                pass
 | 
						|
 | 
						|
            def store(self, key: str, value: str, expires_at: int):
 | 
						|
                pass
 | 
						|
 | 
						|
            def delete(self, key: str):
 | 
						|
                pass
 | 
						|
 | 
						|
        with pytest.raises(TypeError):
 | 
						|
            MissingMethodsPCP(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
    def test_barebones_provider(self, ie, logger):
 | 
						|
        class BarebonesProviderPCP(PoTokenCacheProvider):
 | 
						|
 | 
						|
            def is_available(self) -> bool:
 | 
						|
                return True
 | 
						|
 | 
						|
            def get(self, key: str):
 | 
						|
                return 'example-cache'
 | 
						|
 | 
						|
            def store(self, key: str, value: str, expires_at: int):
 | 
						|
                pass
 | 
						|
 | 
						|
            def delete(self, key: str):
 | 
						|
                pass
 | 
						|
 | 
						|
        provider = BarebonesProviderPCP(ie=ie, logger=logger, settings={})
 | 
						|
        assert provider.PROVIDER_NAME == 'BarebonesProvider'
 | 
						|
        assert provider.PROVIDER_KEY == 'BarebonesProvider'
 | 
						|
        assert provider.PROVIDER_VERSION == '0.0.0'
 | 
						|
        assert provider.BUG_REPORT_MESSAGE == 'please report this issue to the provider developer at  (developer has not provided a bug report location)  .'
 | 
						|
 | 
						|
    def test_create_provider_example(self, ie, logger):
 | 
						|
        provider = ExampleCacheProviderPCP(ie=ie, logger=logger, settings={})
 | 
						|
        assert provider.PROVIDER_NAME == 'example'
 | 
						|
        assert provider.PROVIDER_KEY == 'ExampleCacheProvider'
 | 
						|
        assert provider.PROVIDER_VERSION == '0.0.1'
 | 
						|
        assert provider.BUG_REPORT_MESSAGE == 'please report this issue to the provider developer at  https://example.com/issues  .'
 | 
						|
        assert provider.is_available()
 | 
						|
 | 
						|
    def test_get_config_arg(self, ie, logger):
 | 
						|
        provider = ExampleCacheProviderPCP(ie=ie, logger=logger, settings={'abc': ['123D'], 'xyz': ['456a', '789B']})
 | 
						|
        assert provider._configuration_arg('abc') == ['123d']
 | 
						|
        assert provider._configuration_arg('abc', default=['default']) == ['123d']
 | 
						|
        assert provider._configuration_arg('ABC', default=['default']) == ['default']
 | 
						|
        assert provider._configuration_arg('abc', casesense=True) == ['123D']
 | 
						|
        assert provider._configuration_arg('xyz', casesense=False) == ['456a', '789b']
 | 
						|
 | 
						|
    def test_require_class_end_with_suffix(self, ie, logger):
 | 
						|
        class InvalidSuffix(PoTokenCacheProvider):
 | 
						|
            def get(self, key: str):
 | 
						|
                return 'example-cache'
 | 
						|
 | 
						|
            def store(self, key: str, value: str, expires_at: int):
 | 
						|
                pass
 | 
						|
 | 
						|
            def delete(self, key: str):
 | 
						|
                pass
 | 
						|
 | 
						|
            def is_available(self) -> bool:
 | 
						|
                return True
 | 
						|
 | 
						|
        provider = InvalidSuffix(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
        with pytest.raises(AssertionError):
 | 
						|
            provider.PROVIDER_KEY  # noqa: B018
 | 
						|
 | 
						|
 | 
						|
class TestPoTokenCacheSpecProvider:
 | 
						|
 | 
						|
    def test_base_type(self):
 | 
						|
        assert issubclass(PoTokenCacheSpecProvider, IEContentProvider)
 | 
						|
 | 
						|
    def test_create_provider_missing_supports_method(self, ie, logger):
 | 
						|
        class MissingMethodsPCS(PoTokenCacheSpecProvider):
 | 
						|
            pass
 | 
						|
 | 
						|
        with pytest.raises(TypeError):
 | 
						|
            MissingMethodsPCS(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
    def test_create_provider_barebones(self, ie, pot_request, logger):
 | 
						|
        class BarebonesProviderPCSP(PoTokenCacheSpecProvider):
 | 
						|
            def generate_cache_spec(self, request: PoTokenRequest):
 | 
						|
                return PoTokenCacheSpec(
 | 
						|
                    default_ttl=100,
 | 
						|
                    key_bindings={},
 | 
						|
                )
 | 
						|
 | 
						|
        provider = BarebonesProviderPCSP(ie=ie, logger=logger, settings={})
 | 
						|
        assert provider.PROVIDER_NAME == 'BarebonesProvider'
 | 
						|
        assert provider.PROVIDER_KEY == 'BarebonesProvider'
 | 
						|
        assert provider.PROVIDER_VERSION == '0.0.0'
 | 
						|
        assert provider.BUG_REPORT_MESSAGE == 'please report this issue to the provider developer at  (developer has not provided a bug report location)  .'
 | 
						|
        assert provider.is_available()
 | 
						|
        assert provider.generate_cache_spec(request=pot_request).default_ttl == 100
 | 
						|
        assert provider.generate_cache_spec(request=pot_request).key_bindings == {}
 | 
						|
        assert provider.generate_cache_spec(request=pot_request).write_policy == CacheProviderWritePolicy.WRITE_ALL
 | 
						|
 | 
						|
    def test_create_provider_example(self, ie, pot_request, logger):
 | 
						|
        provider = ExampleCacheSpecProviderPCSP(ie=ie, logger=logger, settings={})
 | 
						|
        assert provider.PROVIDER_NAME == 'example'
 | 
						|
        assert provider.PROVIDER_KEY == 'ExampleCacheSpecProvider'
 | 
						|
        assert provider.PROVIDER_VERSION == '0.0.1'
 | 
						|
        assert provider.BUG_REPORT_MESSAGE == 'please report this issue to the provider developer at  https://example.com/issues  .'
 | 
						|
        assert provider.is_available()
 | 
						|
        assert provider.generate_cache_spec(pot_request)
 | 
						|
        assert provider.generate_cache_spec(pot_request).key_bindings == {'field': 'example-key'}
 | 
						|
        assert provider.generate_cache_spec(pot_request).default_ttl == 60
 | 
						|
        assert provider.generate_cache_spec(pot_request).write_policy == CacheProviderWritePolicy.WRITE_FIRST
 | 
						|
 | 
						|
    def test_get_config_arg(self, ie, logger):
 | 
						|
        provider = ExampleCacheSpecProviderPCSP(ie=ie, logger=logger, settings={'abc': ['123D'], 'xyz': ['456a', '789B']})
 | 
						|
 | 
						|
        assert provider._configuration_arg('abc') == ['123d']
 | 
						|
        assert provider._configuration_arg('abc', default=['default']) == ['123d']
 | 
						|
        assert provider._configuration_arg('ABC', default=['default']) == ['default']
 | 
						|
        assert provider._configuration_arg('abc', casesense=True) == ['123D']
 | 
						|
        assert provider._configuration_arg('xyz', casesense=False) == ['456a', '789b']
 | 
						|
 | 
						|
    def test_require_class_end_with_suffix(self, ie, logger):
 | 
						|
        class InvalidSuffix(PoTokenCacheSpecProvider):
 | 
						|
            def generate_cache_spec(self, request: PoTokenRequest):
 | 
						|
                return None
 | 
						|
 | 
						|
        provider = InvalidSuffix(ie=ie, logger=logger, settings={})
 | 
						|
 | 
						|
        with pytest.raises(AssertionError):
 | 
						|
            provider.PROVIDER_KEY  # noqa: B018
 | 
						|
 | 
						|
 | 
						|
class TestPoTokenRequest:
 | 
						|
    def test_copy_request(self, pot_request):
 | 
						|
        copied_request = pot_request.copy()
 | 
						|
 | 
						|
        assert copied_request is not pot_request
 | 
						|
        assert copied_request.context == pot_request.context
 | 
						|
        assert copied_request.innertube_context == pot_request.innertube_context
 | 
						|
        assert copied_request.innertube_context is not pot_request.innertube_context
 | 
						|
        copied_request.innertube_context['client']['clientName'] = 'ANDROID'
 | 
						|
        assert pot_request.innertube_context['client']['clientName'] != 'ANDROID'
 | 
						|
        assert copied_request.innertube_host == pot_request.innertube_host
 | 
						|
        assert copied_request.session_index == pot_request.session_index
 | 
						|
        assert copied_request.player_url == pot_request.player_url
 | 
						|
        assert copied_request.is_authenticated == pot_request.is_authenticated
 | 
						|
        assert copied_request.visitor_data == pot_request.visitor_data
 | 
						|
        assert copied_request.data_sync_id == pot_request.data_sync_id
 | 
						|
        assert copied_request.video_id == pot_request.video_id
 | 
						|
        assert copied_request.request_cookiejar is pot_request.request_cookiejar
 | 
						|
        assert copied_request.request_proxy == pot_request.request_proxy
 | 
						|
        assert copied_request.request_headers == pot_request.request_headers
 | 
						|
        assert copied_request.request_headers is not pot_request.request_headers
 | 
						|
        assert copied_request.request_timeout == pot_request.request_timeout
 | 
						|
        assert copied_request.request_source_address == pot_request.request_source_address
 | 
						|
        assert copied_request.request_verify_tls == pot_request.request_verify_tls
 | 
						|
        assert copied_request.bypass_cache == pot_request.bypass_cache
 | 
						|
 | 
						|
 | 
						|
def test_provider_bug_report_message(ie, logger):
 | 
						|
    provider = ExamplePTP(ie=ie, logger=logger, settings={})
 | 
						|
    assert provider.BUG_REPORT_MESSAGE == 'please report this issue to the provider developer at  https://example.com/issues  .'
 | 
						|
 | 
						|
    message = provider_bug_report_message(provider)
 | 
						|
    assert message == '; please report this issue to the provider developer at  https://example.com/issues  .'
 | 
						|
 | 
						|
    message_before = provider_bug_report_message(provider, before='custom message!')
 | 
						|
    assert message_before == 'custom message! Please report this issue to the provider developer at  https://example.com/issues  .'
 | 
						|
 | 
						|
 | 
						|
def test_register_provider(ie):
 | 
						|
 | 
						|
    @register_provider
 | 
						|
    class UnavailableProviderPTP(PoTokenProvider):
 | 
						|
        def is_available(self) -> bool:
 | 
						|
            return False
 | 
						|
 | 
						|
        def _real_request_pot(self, request: PoTokenRequest) -> PoTokenResponse:
 | 
						|
            raise PoTokenProviderRejectedRequest('Not implemented')
 | 
						|
 | 
						|
    assert _pot_providers.value.get('UnavailableProvider') == UnavailableProviderPTP
 | 
						|
    _pot_providers.value.pop('UnavailableProvider')
 | 
						|
 | 
						|
 | 
						|
def test_register_pot_preference(ie):
 | 
						|
    before = len(_ptp_preferences.value)
 | 
						|
 | 
						|
    @register_preference(ExamplePTP)
 | 
						|
    def unavailable_preference(provider: PoTokenProvider, request: PoTokenRequest):
 | 
						|
        return 1
 | 
						|
 | 
						|
    assert len(_ptp_preferences.value) == before + 1
 | 
						|
 | 
						|
 | 
						|
def test_register_cache_provider(ie):
 | 
						|
 | 
						|
    @cache.register_provider
 | 
						|
    class UnavailableCacheProviderPCP(PoTokenCacheProvider):
 | 
						|
        def is_available(self) -> bool:
 | 
						|
            return False
 | 
						|
 | 
						|
        def get(self, key: str):
 | 
						|
            return 'example-cache'
 | 
						|
 | 
						|
        def store(self, key: str, value: str, expires_at: int):
 | 
						|
            pass
 | 
						|
 | 
						|
        def delete(self, key: str):
 | 
						|
            pass
 | 
						|
 | 
						|
    assert _pot_cache_providers.value.get('UnavailableCacheProvider') == UnavailableCacheProviderPCP
 | 
						|
    _pot_cache_providers.value.pop('UnavailableCacheProvider')
 | 
						|
 | 
						|
 | 
						|
def test_register_cache_provider_spec(ie):
 | 
						|
 | 
						|
    @cache.register_spec
 | 
						|
    class UnavailableCacheProviderPCSP(PoTokenCacheSpecProvider):
 | 
						|
        def is_available(self) -> bool:
 | 
						|
            return False
 | 
						|
 | 
						|
        def generate_cache_spec(self, request: PoTokenRequest):
 | 
						|
            return None
 | 
						|
 | 
						|
    assert _pot_pcs_providers.value.get('UnavailableCacheProvider') == UnavailableCacheProviderPCSP
 | 
						|
    _pot_pcs_providers.value.pop('UnavailableCacheProvider')
 | 
						|
 | 
						|
 | 
						|
def test_register_cache_provider_preference(ie):
 | 
						|
    before = len(_pot_cache_provider_preferences.value)
 | 
						|
 | 
						|
    @cache.register_preference(ExampleCacheProviderPCP)
 | 
						|
    def unavailable_preference(provider: PoTokenCacheProvider, request: PoTokenRequest):
 | 
						|
        return 1
 | 
						|
 | 
						|
    assert len(_pot_cache_provider_preferences.value) == before + 1
 | 
						|
 | 
						|
 | 
						|
def test_logger_log_level(logger):
 | 
						|
    assert logger.LogLevel('INFO') == logger.LogLevel.INFO
 | 
						|
    assert logger.LogLevel('debuG') == logger.LogLevel.DEBUG
 | 
						|
    assert logger.LogLevel(10) == logger.LogLevel.DEBUG
 | 
						|
    assert logger.LogLevel('UNKNOWN') == logger.LogLevel.INFO
 |