Files
unshackle/reference/api/service/index.html
T
2026-10-10 21:22:08 +00:00

5291 lines
294 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="Movie, TV, and Music archival software. User guide and REST API reference">
<link rel="canonical" href="https://docs.unshackle.dev/reference/api/service/">
<link rel="prev" href="../../../dev/rest-api/errors/">
<link rel="next" href="../config/">
<link rel="icon" href="../../../assets/favicon.svg">
<meta name="generator" content="mkdocs-1.6.1, mkdocs-material-9.7.7">
<title>Service - unshackle</title>
<link rel="stylesheet" href="../../../assets/stylesheets/main.ec1eaa64.min.css">
<link rel="stylesheet" href="../../../assets/stylesheets/palette.ab4e12ef.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
<link rel="stylesheet" href="../../../assets/_mkdocstrings.css">
<link rel="stylesheet" href="../../../assets/extra.css">
<script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
</head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="black" data-md-color-accent="indigo">
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#service-api" class="md-skip">
Skip to content
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="Header">
<a href="../../.." title="unshackle" class="md-header__button md-logo" aria-label="unshackle" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m800-274-80-80v-206H514l-80-80h166v-80q0-50-34.5-85T481-840q-50 0-84 34.5T363-720v9l-73-73q22-61 75-98.5T481-920q83 0 141 58.5T680-720v80h40q33 0 56.5 23.5T800-560v286Zm20 246-62-62q-11 5-20 7.5T720-80H240q-33 0-56.5-23.5T160-160v-400q0-25 14.5-46t37.5-30L28-820l56-56L876-84l-56 56ZM686-160 539-309q-11 11-25.5 17t-31.5 6q-33 0-56.5-23.5T402-366q0-17 6-31.5t17-25.5L286-560h-46v400h446ZM486-360Zm131-97Z"/></svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
unshackle
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
Service
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="(prefers-color-scheme)" data-md-color-scheme="default" data-md-color-primary="black" data-md-color-accent="indigo" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_0">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_1" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7a5 5 0 0 0-5 5 5 5 0 0 0 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1M8 13h8v-2H8zm9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4a5 5 0 0 0 5-5 5 5 0 0 0-5-5"/></svg>
</label>
<input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="black" data-md-color-accent="indigo" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_2" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 7H7a5 5 0 0 0-5 5 5 5 0 0 0 5 5h10a5 5 0 0 0 5-5 5 5 0 0 0-5-5m0 8a3 3 0 0 1-3-3 3 3 0 0 1 3-3 3 3 0 0 1 3 3 3 3 0 0 1-3 3"/></svg>
</label>
<input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="black" data-md-color-accent="indigo" aria-label="Switch to system preference" type="radio" name="__palette" id="__palette_2">
<label class="md-header__button md-icon" title="Switch to system preference" for="__palette_0" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 7H7a5 5 0 0 0-5 5 5 5 0 0 0 5 5h10a5 5 0 0 0 5-5 5 5 0 0 0-5-5M7 15a3 3 0 0 1-3-3 3 3 0 0 1 3-3 3 3 0 0 1 3 3 3 3 0 0 1-3 3"/></svg>
</label>
</form>
<script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
</label>
<nav class="md-search__options" aria-label="Search">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="Share" aria-label="Share" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"/></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
Initializing search
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
<div class="md-header__source">
<a href="https://github.com/unshackle-dl/unshackle" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"/></svg>
</div>
<div class="md-source__repository">
unshackle-dl/unshackle
</div>
</a>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<nav class="md-tabs" aria-label="Tabs" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="../../.." class="md-tabs__link">
Home
</a>
</li>
<li class="md-tabs__item">
<a href="../../../getting-started/installation/" class="md-tabs__link">
Getting Started
</a>
</li>
<li class="md-tabs__item">
<a href="../../../guide/downloading/" class="md-tabs__link">
User Guide
</a>
</li>
<li class="md-tabs__item">
<a href="../../configuration/" class="md-tabs__link">
Configuration
</a>
</li>
<li class="md-tabs__item">
<a href="../../../dev/creating-a-service/" class="md-tabs__link">
Developer
</a>
</li>
<li class="md-tabs__item md-tabs__item--active">
<a href="./" class="md-tabs__link">
API Reference
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="Navigation" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="../../.." title="unshackle" class="md-nav__button md-logo" aria-label="unshackle" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m800-274-80-80v-206H514l-80-80h166v-80q0-50-34.5-85T481-840q-50 0-84 34.5T363-720v9l-73-73q22-61 75-98.5T481-920q83 0 141 58.5T680-720v80h40q33 0 56.5 23.5T800-560v286Zm20 246-62-62q-11 5-20 7.5T720-80H240q-33 0-56.5-23.5T160-160v-400q0-25 14.5-46t37.5-30L28-820l56-56L876-84l-56 56ZM686-160 539-309q-11 11-25.5 17t-31.5 6q-33 0-56.5-23.5T402-366q0-17 6-31.5t17-25.5L286-560h-46v400h446ZM486-360Zm131-97Z"/></svg>
</a>
unshackle
</label>
<div class="md-nav__source">
<a href="https://github.com/unshackle-dl/unshackle" title="Go to repository" class="md-source" data-md-component="source">
<div class="md-source__icon md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M439.6 236.1 244 40.5c-5.4-5.5-12.8-8.5-20.4-8.5s-15 3-20.4 8.4L162.5 81l51.5 51.5c27.1-9.1 52.7 16.8 43.4 43.7l49.7 49.7c34.2-11.8 61.2 31 35.5 56.7-26.5 26.5-70.2-2.9-56-37.3L240.3 199v121.9c25.3 12.5 22.3 41.8 9.1 55-6.4 6.4-15.2 10.1-24.3 10.1s-17.8-3.6-24.3-10.1c-17.6-17.6-11.1-46.9 11.2-56v-123c-20.8-8.5-24.6-30.7-18.6-45L142.6 101 8.5 235.1C3 240.6 0 247.9 0 255.5s3 15 8.5 20.4l195.6 195.7c5.4 5.4 12.7 8.4 20.4 8.4s15-3 20.4-8.4l194.7-194.7c5.4-5.4 8.4-12.8 8.4-20.4s-3-15-8.4-20.4"/></svg>
</div>
<div class="md-source__repository">
unshackle-dl/unshackle
</div>
</a>
</div>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../.." class="md-nav__link">
<span class="md-ellipsis">
Home
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" >
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="0">
<span class="md-ellipsis">
Getting Started
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
Getting Started
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../getting-started/installation/" class="md-nav__link">
<span class="md-ellipsis">
Installation
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../getting-started/quickstart/" class="md-nav__link">
<span class="md-ellipsis">
Quick Start
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../getting-started/configuration-file/" class="md-nav__link">
<span class="md-ellipsis">
The Configuration File
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
<label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0">
<span class="md-ellipsis">
User Guide
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
User Guide
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../guide/downloading/" class="md-nav__link">
<span class="md-ellipsis">
Downloading
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../guide/cli-reference/" class="md-nav__link">
<span class="md-ellipsis">
CLI Reference
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../guide/drm-and-cdm/" class="md-nav__link">
<span class="md-ellipsis">
DRM & CDM Setup
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../guide/proxies-and-vpn/" class="md-nav__link">
<span class="md-ellipsis">
Proxies & VPN
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../guide/vaults/" class="md-nav__link">
<span class="md-ellipsis">
Key Vaults
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../guide/output-and-naming/" class="md-nav__link">
<span class="md-ellipsis">
Output & Naming
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../guide/subtitles/" class="md-nav__link">
<span class="md-ellipsis">
Subtitles
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../guide/troubleshooting/" class="md-nav__link">
<span class="md-ellipsis">
Troubleshooting
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4" >
<div class="md-nav__link md-nav__container">
<a href="../../configuration/" class="md-nav__link ">
<span class="md-ellipsis">
Configuration
</span>
</a>
<label class="md-nav__link " for="__nav_4" id="__nav_4_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
Configuration
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../configuration/directories/" class="md-nav__link">
<span class="md-ellipsis">
Directories
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../configuration/services/" class="md-nav__link">
<span class="md-ellipsis">
Services & Authentication
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../configuration/download/" class="md-nav__link">
<span class="md-ellipsis">
Download & Processing
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../configuration/output/" class="md-nav__link">
<span class="md-ellipsis">
Output & Naming
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../configuration/drm/" class="md-nav__link">
<span class="md-ellipsis">
DRM & CDM
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../configuration/network/" class="md-nav__link">
<span class="md-ellipsis">
Network & Proxy
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../configuration/vaults/" class="md-nav__link">
<span class="md-ellipsis">
Key Vaults
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../configuration/post-scripts/" class="md-nav__link">
<span class="md-ellipsis">
Post-Scripts
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../configuration/misc/" class="md-nav__link">
<span class="md-ellipsis">
Other Settings
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../configuration/example/" class="md-nav__link">
<span class="md-ellipsis">
Annotated Example
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0">
<span class="md-ellipsis">
Developer
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
Developer
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../dev/creating-a-service/" class="md-nav__link">
<span class="md-ellipsis">
Creating a Service
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../dev/service-architecture/" class="md-nav__link">
<span class="md-ellipsis">
Service Architecture
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5_3" >
<div class="md-nav__link md-nav__container">
<a href="../../../dev/rest-api/" class="md-nav__link ">
<span class="md-ellipsis">
REST API
</span>
</a>
<label class="md-nav__link " for="__nav_5_3" id="__nav_5_3_label" tabindex="0">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_5_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5_3">
<span class="md-nav__icon md-icon"></span>
REST API
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../dev/rest-api/quickstart/" class="md-nav__link">
<span class="md-ellipsis">
Quick Start
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../dev/rest-api/authentication/" class="md-nav__link">
<span class="md-ellipsis">
Authentication
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../dev/rest-api/endpoints/" class="md-nav__link">
<span class="md-ellipsis">
Endpoints
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../dev/rest-api/job-lifecycle/" class="md-nav__link">
<span class="md-ellipsis">
Job Lifecycle
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../dev/rest-api/dashboard/" class="md-nav__link">
<span class="md-ellipsis">
Dashboard
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../dev/rest-api/remote-sessions/" class="md-nav__link">
<span class="md-ellipsis">
Remote Sessions
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../dev/rest-api/errors/" class="md-nav__link">
<span class="md-ellipsis">
Error Responses
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6" checked>
<label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="">
<span class="md-ellipsis">
API Reference
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
API Reference
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
Service
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
Service
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#unshackle.core.service" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-module"></code>&nbsp;service
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.TimeoutSession" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-class"></code>&nbsp;TimeoutSession
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.TimeoutHTTPAdapter" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-class"></code>&nbsp;TimeoutHTTPAdapter
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.TrackRequest" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-class"></code>&nbsp;TrackRequest
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-class"></code>&nbsp;Service
</span>
</a>
<nav class="md-nav" aria-label=" Service">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.is_region_allowed" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;is_region_allowed
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_tracks_for_variants" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_tracks_for_variants
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_session" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_session
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_binaries" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_binaries
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.authenticate" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;authenticate
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.request_input" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;request_input
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.wait_for_approval" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;wait_for_approval
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.search" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;search
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_widevine_service_certificate" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_widevine_service_certificate
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_widevine_license" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_widevine_license
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_playready_license" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_playready_license
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_clearkey_license" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_clearkey_license
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_titles" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_titles
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_titles_cached" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_titles_cached
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.apply_title_map" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;apply_title_map
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_tracks" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_tracks
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_chapters" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_chapters
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.on_segment_downloaded" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;on_segment_downloaded
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.on_track_downloaded" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;on_track_downloaded
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.on_track_decrypted" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;on_track_decrypted
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.on_track_repacked" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;on_track_repacked
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.on_track_multiplex" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;on_track_multiplex
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.grow_session_pool" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-function"></code>&nbsp;grow_session_pool
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.sanitize_proxy_for_log" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-function"></code>&nbsp;sanitize_proxy_for_log
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../config/" class="md-nav__link">
<span class="md-ellipsis">
Config
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../tracks/" class="md-nav__link">
<span class="md-ellipsis">
Tracks
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../titles/" class="md-nav__link">
<span class="md-ellipsis">
Titles
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../drm/" class="md-nav__link">
<span class="md-ellipsis">
DRM
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="Table of contents">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
Table of contents
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#unshackle.core.service" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-module"></code>&nbsp;service
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.TimeoutSession" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-class"></code>&nbsp;TimeoutSession
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.TimeoutHTTPAdapter" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-class"></code>&nbsp;TimeoutHTTPAdapter
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.TrackRequest" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-class"></code>&nbsp;TrackRequest
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-class"></code>&nbsp;Service
</span>
</a>
<nav class="md-nav" aria-label=" Service">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.is_region_allowed" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;is_region_allowed
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_tracks_for_variants" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_tracks_for_variants
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_session" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_session
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_binaries" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_binaries
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.authenticate" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;authenticate
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.request_input" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;request_input
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.wait_for_approval" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;wait_for_approval
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.search" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;search
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_widevine_service_certificate" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_widevine_service_certificate
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_widevine_license" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_widevine_license
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_playready_license" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_playready_license
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_clearkey_license" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_clearkey_license
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_titles" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_titles
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_titles_cached" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_titles_cached
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.apply_title_map" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;apply_title_map
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_tracks" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_tracks
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.get_chapters" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;get_chapters
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.on_segment_downloaded" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;on_segment_downloaded
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.on_track_downloaded" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;on_track_downloaded
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.on_track_decrypted" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;on_track_decrypted
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.on_track_repacked" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;on_track_repacked
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.Service.on_track_multiplex" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-method"></code>&nbsp;on_track_multiplex
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.grow_session_pool" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-function"></code>&nbsp;grow_session_pool
</span>
</a>
</li>
<li class="md-nav__item">
<a href="#unshackle.core.service.sanitize_proxy_for_log" class="md-nav__link">
<span class="md-ellipsis">
<code class="doc-symbol doc-symbol-toc doc-symbol-function"></code>&nbsp;sanitize_proxy_for_log
</span>
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="service-api">Service API<a class="headerlink" href="#service-api" title="Permanent link">&para;</a></h1>
<p>Auto-generated reference for the <a class="autorefs autorefs-internal" title="&lt;code class=&quot;doc-symbol doc-symbol-heading doc-symbol-class&quot;&gt;&lt;/code&gt; &lt;span class=&quot;doc doc-object-name doc-class-name&quot;&gt;Service&lt;/span&gt;" href="#unshackle.core.service.Service"><code>Service</code></a> base class that every
service plugin subclasses. See <a href="../../../dev/creating-a-service/">Creating a Service</a> for a guided
walkthrough and <a href="../../../dev/service-architecture/">Service Architecture</a> for the wider object model.</p>
<div class="doc doc-object doc-module">
<a id="unshackle.core.service"></a>
<div class="doc doc-contents first">
<div class="doc doc-children">
<div class="doc doc-object doc-class">
<h2 id="unshackle.core.service.TimeoutSession" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-class"></code> <span class="doc doc-object-name doc-class-name">TimeoutSession</span>
<a href="#unshackle.core.service.TimeoutSession" class="headerlink" title="Permanent link">&para;</a></h2>
<div class="doc doc-contents ">
<p class="doc doc-class-bases">
Bases: <code><span title="requests.Session">Session</span></code></p>
<p>requests.Session applying DEFAULT_TIMEOUT when the caller passes none.</p>
<p>requests has no native default timeout. Without one, a stalled connect or
read hangs forever. RnetSession bounds every request through its client's
connect_timeout/read_timeout, so this mirrors that on the requests path.
A per-request non-None <code>timeout=</code> wins. :class:<code>TimeoutHTTPAdapter</code> on the
mounted adapters still replaces an explicit <code>timeout=None</code> with the default,
so there is no unbounded read, as with RnetSession where the client-level
timeouts always apply. Pass a large timeout instead.</p>
<div class="doc doc-children">
</div>
</div>
</div>
<div class="doc doc-object doc-class">
<h2 id="unshackle.core.service.TimeoutHTTPAdapter" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-class"></code> <span class="doc doc-object-name doc-class-name">TimeoutHTTPAdapter</span>
<a href="#unshackle.core.service.TimeoutHTTPAdapter" class="headerlink" title="Permanent link">&para;</a></h2>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">TimeoutHTTPAdapter</span><span class="p">(</span>
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="n"><span title="unshackle.core.service.DEFAULT_TIMEOUT">DEFAULT_TIMEOUT</span></span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span>
</span><span id="__span-0-3"><a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p class="doc doc-class-bases">
Bases: <code><span title="requests.adapters.HTTPAdapter">HTTPAdapter</span></code></p>
<p>HTTPAdapter applying DEFAULT_TIMEOUT when the caller passes none.</p>
<p>Backstops :class:<code>TimeoutSession</code> for the <code>session.send(prepared)</code> path,
which bypasses <code>Session.request</code>. RnetSession bounds those too through its
client, so this keeps parity. A per-request non-None <code>timeout=</code> wins.
<code>None</code> (unset, or explicitly passed) gets the default, because the adapter
cannot distinguish the two, and rnet has no unbounded mode either.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-81">81</a></span>
<span class="normal"><a href="#__codelineno-0-82">82</a></span>
<span class="normal"><a href="#__codelineno-0-83">83</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-81"><a id="__codelineno-0-81" name="__codelineno-0-81"></a><span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="n">timeout</span><span class="p">:</span> <span class="n">Any</span> <span class="o">=</span> <span class="n">DEFAULT_TIMEOUT</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">:</span> <span class="n">Any</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="__span-0-82"><a id="__codelineno-0-82" name="__codelineno-0-82"></a> <span class="bp">self</span><span class="o">.</span><span class="n">default_timeout</span> <span class="o">=</span> <span class="n">timeout</span>
</span><span id="__span-0-83"><a id="__codelineno-0-83" name="__codelineno-0-83"></a> <span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</span></code></pre></div></td></tr></table></div>
</details>
<div class="doc doc-children">
</div>
</div>
</div>
<div class="doc doc-object doc-class">
<h2 id="unshackle.core.service.TrackRequest" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-class"></code> <span class="doc doc-object-name doc-class-name">TrackRequest</span>
<span class="doc doc-labels">
<small class="doc doc-label doc-label-dataclass"><code>dataclass</code></small>
</span>
<a href="#unshackle.core.service.TrackRequest" class="headerlink" title="Permanent link">&para;</a></h2>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">TrackRequest</span><span class="p">(</span>
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a> <span class="n">codecs</span><span class="o">=</span><span class="n"><span title="list">list</span></span><span class="p">(),</span>
</span><span id="__span-0-3"><a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a> <span class="n">ranges</span><span class="o">=</span><span class="p">(</span><span class="k">lambda</span><span class="p">:</span> <span class="p">[</span><span class="n"><span title="unshackle.core.tracks.video.Video.Range.SDR">SDR</span></span><span class="p">])(),</span>
</span><span id="__span-0-4"><a id="__codelineno-0-4" name="__codelineno-0-4" href="#__codelineno-0-4"></a> <span class="n">best_available</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
</span><span id="__span-0-5"><a id="__codelineno-0-5" name="__codelineno-0-5" href="#__codelineno-0-5"></a><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Holds what the user requested for video codec and range selection.</p>
<p>Services read from this instead of ctx.parent.params for vcodec/range.</p>
<p><span class="doc-section-title">Attributes:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td><code><span title="unshackle.core.service.TrackRequest.codecs">codecs</span></code></td>
<td>
<code><span title="list">list</span>[<span title="unshackle.core.tracks.video.Video.Codec">Codec</span>]</code>
</td>
<td>
<div class="doc-md-description">
<p>Requested codecs from CLI. Empty list means no filter (accept any).</p>
</div>
</td>
</tr>
<tr class="doc-section-item">
<td><code><span title="unshackle.core.service.TrackRequest.ranges">ranges</span></code></td>
<td>
<code><span title="list">list</span>[<a class="autorefs autorefs-internal" title="&lt;code class=&quot;doc-symbol doc-symbol-heading doc-symbol-class&quot;&gt;&lt;/code&gt; &lt;span class=&quot;doc doc-object-name doc-class-name&quot;&gt;Range&lt;/span&gt; (&lt;code&gt;unshackle.core.tracks.video.Video.Range&lt;/code&gt;)" href="../tracks/#unshackle.core.tracks.Video.Range">Range</a>]</code>
</td>
<td>
<div class="doc-md-description">
<p>Requested ranges from CLI. Defaults to [SDR].</p>
</div>
</td>
</tr>
</tbody>
</table>
<div class="doc doc-children">
</div>
</div>
</div>
<div class="doc doc-object doc-class">
<h2 id="unshackle.core.service.Service" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-class"></code> <span class="doc doc-object-name doc-class-name">Service</span>
<a href="#unshackle.core.service.Service" class="headerlink" title="Permanent link">&para;</a></h2>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">Service</span><span class="p">(</span><span class="n">ctx</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>The Service Base Class.</p>
<p>A Service must define the abstract methods. The rest are optional overrides that fall back to the base
implementation when a Service does not define them. The main flow operates the HTTP session and
authentication methods first, then titles, then tracks and chapters. The license callbacks operate later
still, during track download.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-174">174</a></span>
<span class="normal"><a href="#__codelineno-0-175">175</a></span>
<span class="normal"><a href="#__codelineno-0-176">176</a></span>
<span class="normal"><a href="#__codelineno-0-177">177</a></span>
<span class="normal"><a href="#__codelineno-0-178">178</a></span>
<span class="normal"><a href="#__codelineno-0-179">179</a></span>
<span class="normal"><a href="#__codelineno-0-180">180</a></span>
<span class="normal"><a href="#__codelineno-0-181">181</a></span>
<span class="normal"><a href="#__codelineno-0-182">182</a></span>
<span class="normal"><a href="#__codelineno-0-183">183</a></span>
<span class="normal"><a href="#__codelineno-0-184">184</a></span>
<span class="normal"><a href="#__codelineno-0-185">185</a></span>
<span class="normal"><a href="#__codelineno-0-186">186</a></span>
<span class="normal"><a href="#__codelineno-0-187">187</a></span>
<span class="normal"><a href="#__codelineno-0-188">188</a></span>
<span class="normal"><a href="#__codelineno-0-189">189</a></span>
<span class="normal"><a href="#__codelineno-0-190">190</a></span>
<span class="normal"><a href="#__codelineno-0-191">191</a></span>
<span class="normal"><a href="#__codelineno-0-192">192</a></span>
<span class="normal"><a href="#__codelineno-0-193">193</a></span>
<span class="normal"><a href="#__codelineno-0-194">194</a></span>
<span class="normal"><a href="#__codelineno-0-195">195</a></span>
<span class="normal"><a href="#__codelineno-0-196">196</a></span>
<span class="normal"><a href="#__codelineno-0-197">197</a></span>
<span class="normal"><a href="#__codelineno-0-198">198</a></span>
<span class="normal"><a href="#__codelineno-0-199">199</a></span>
<span class="normal"><a href="#__codelineno-0-200">200</a></span>
<span class="normal"><a href="#__codelineno-0-201">201</a></span>
<span class="normal"><a href="#__codelineno-0-202">202</a></span>
<span class="normal"><a href="#__codelineno-0-203">203</a></span>
<span class="normal"><a href="#__codelineno-0-204">204</a></span>
<span class="normal"><a href="#__codelineno-0-205">205</a></span>
<span class="normal"><a href="#__codelineno-0-206">206</a></span>
<span class="normal"><a href="#__codelineno-0-207">207</a></span>
<span class="normal"><a href="#__codelineno-0-208">208</a></span>
<span class="normal"><a href="#__codelineno-0-209">209</a></span>
<span class="normal"><a href="#__codelineno-0-210">210</a></span>
<span class="normal"><a href="#__codelineno-0-211">211</a></span>
<span class="normal"><a href="#__codelineno-0-212">212</a></span>
<span class="normal"><a href="#__codelineno-0-213">213</a></span>
<span class="normal"><a href="#__codelineno-0-214">214</a></span>
<span class="normal"><a href="#__codelineno-0-215">215</a></span>
<span class="normal"><a href="#__codelineno-0-216">216</a></span>
<span class="normal"><a href="#__codelineno-0-217">217</a></span>
<span class="normal"><a href="#__codelineno-0-218">218</a></span>
<span class="normal"><a href="#__codelineno-0-219">219</a></span>
<span class="normal"><a href="#__codelineno-0-220">220</a></span>
<span class="normal"><a href="#__codelineno-0-221">221</a></span>
<span class="normal"><a href="#__codelineno-0-222">222</a></span>
<span class="normal"><a href="#__codelineno-0-223">223</a></span>
<span class="normal"><a href="#__codelineno-0-224">224</a></span>
<span class="normal"><a href="#__codelineno-0-225">225</a></span>
<span class="normal"><a href="#__codelineno-0-226">226</a></span>
<span class="normal"><a href="#__codelineno-0-227">227</a></span>
<span class="normal"><a href="#__codelineno-0-228">228</a></span>
<span class="normal"><a href="#__codelineno-0-229">229</a></span>
<span class="normal"><a href="#__codelineno-0-230">230</a></span>
<span class="normal"><a href="#__codelineno-0-231">231</a></span>
<span class="normal"><a href="#__codelineno-0-232">232</a></span>
<span class="normal"><a href="#__codelineno-0-233">233</a></span>
<span class="normal"><a href="#__codelineno-0-234">234</a></span>
<span class="normal"><a href="#__codelineno-0-235">235</a></span>
<span class="normal"><a href="#__codelineno-0-236">236</a></span>
<span class="normal"><a href="#__codelineno-0-237">237</a></span>
<span class="normal"><a href="#__codelineno-0-238">238</a></span>
<span class="normal"><a href="#__codelineno-0-239">239</a></span>
<span class="normal"><a href="#__codelineno-0-240">240</a></span>
<span class="normal"><a href="#__codelineno-0-241">241</a></span>
<span class="normal"><a href="#__codelineno-0-242">242</a></span>
<span class="normal"><a href="#__codelineno-0-243">243</a></span>
<span class="normal"><a href="#__codelineno-0-244">244</a></span>
<span class="normal"><a href="#__codelineno-0-245">245</a></span>
<span class="normal"><a href="#__codelineno-0-246">246</a></span>
<span class="normal"><a href="#__codelineno-0-247">247</a></span>
<span class="normal"><a href="#__codelineno-0-248">248</a></span>
<span class="normal"><a href="#__codelineno-0-249">249</a></span>
<span class="normal"><a href="#__codelineno-0-250">250</a></span>
<span class="normal"><a href="#__codelineno-0-251">251</a></span>
<span class="normal"><a href="#__codelineno-0-252">252</a></span>
<span class="normal"><a href="#__codelineno-0-253">253</a></span>
<span class="normal"><a href="#__codelineno-0-254">254</a></span>
<span class="normal"><a href="#__codelineno-0-255">255</a></span>
<span class="normal"><a href="#__codelineno-0-256">256</a></span>
<span class="normal"><a href="#__codelineno-0-257">257</a></span>
<span class="normal"><a href="#__codelineno-0-258">258</a></span>
<span class="normal"><a href="#__codelineno-0-259">259</a></span>
<span class="normal"><a href="#__codelineno-0-260">260</a></span>
<span class="normal"><a href="#__codelineno-0-261">261</a></span>
<span class="normal"><a href="#__codelineno-0-262">262</a></span>
<span class="normal"><a href="#__codelineno-0-263">263</a></span>
<span class="normal"><a href="#__codelineno-0-264">264</a></span>
<span class="normal"><a href="#__codelineno-0-265">265</a></span>
<span class="normal"><a href="#__codelineno-0-266">266</a></span>
<span class="normal"><a href="#__codelineno-0-267">267</a></span>
<span class="normal"><a href="#__codelineno-0-268">268</a></span>
<span class="normal"><a href="#__codelineno-0-269">269</a></span>
<span class="normal"><a href="#__codelineno-0-270">270</a></span>
<span class="normal"><a href="#__codelineno-0-271">271</a></span>
<span class="normal"><a href="#__codelineno-0-272">272</a></span>
<span class="normal"><a href="#__codelineno-0-273">273</a></span>
<span class="normal"><a href="#__codelineno-0-274">274</a></span>
<span class="normal"><a href="#__codelineno-0-275">275</a></span>
<span class="normal"><a href="#__codelineno-0-276">276</a></span>
<span class="normal"><a href="#__codelineno-0-277">277</a></span>
<span class="normal"><a href="#__codelineno-0-278">278</a></span>
<span class="normal"><a href="#__codelineno-0-279">279</a></span>
<span class="normal"><a href="#__codelineno-0-280">280</a></span>
<span class="normal"><a href="#__codelineno-0-281">281</a></span>
<span class="normal"><a href="#__codelineno-0-282">282</a></span>
<span class="normal"><a href="#__codelineno-0-283">283</a></span>
<span class="normal"><a href="#__codelineno-0-284">284</a></span>
<span class="normal"><a href="#__codelineno-0-285">285</a></span>
<span class="normal"><a href="#__codelineno-0-286">286</a></span>
<span class="normal"><a href="#__codelineno-0-287">287</a></span>
<span class="normal"><a href="#__codelineno-0-288">288</a></span>
<span class="normal"><a href="#__codelineno-0-289">289</a></span>
<span class="normal"><a href="#__codelineno-0-290">290</a></span>
<span class="normal"><a href="#__codelineno-0-291">291</a></span>
<span class="normal"><a href="#__codelineno-0-292">292</a></span>
<span class="normal"><a href="#__codelineno-0-293">293</a></span>
<span class="normal"><a href="#__codelineno-0-294">294</a></span>
<span class="normal"><a href="#__codelineno-0-295">295</a></span>
<span class="normal"><a href="#__codelineno-0-296">296</a></span>
<span class="normal"><a href="#__codelineno-0-297">297</a></span>
<span class="normal"><a href="#__codelineno-0-298">298</a></span>
<span class="normal"><a href="#__codelineno-0-299">299</a></span>
<span class="normal"><a href="#__codelineno-0-300">300</a></span>
<span class="normal"><a href="#__codelineno-0-301">301</a></span>
<span class="normal"><a href="#__codelineno-0-302">302</a></span>
<span class="normal"><a href="#__codelineno-0-303">303</a></span>
<span class="normal"><a href="#__codelineno-0-304">304</a></span>
<span class="normal"><a href="#__codelineno-0-305">305</a></span>
<span class="normal"><a href="#__codelineno-0-306">306</a></span>
<span class="normal"><a href="#__codelineno-0-307">307</a></span>
<span class="normal"><a href="#__codelineno-0-308">308</a></span>
<span class="normal"><a href="#__codelineno-0-309">309</a></span>
<span class="normal"><a href="#__codelineno-0-310">310</a></span>
<span class="normal"><a href="#__codelineno-0-311">311</a></span>
<span class="normal"><a href="#__codelineno-0-312">312</a></span>
<span class="normal"><a href="#__codelineno-0-313">313</a></span>
<span class="normal"><a href="#__codelineno-0-314">314</a></span>
<span class="normal"><a href="#__codelineno-0-315">315</a></span>
<span class="normal"><a href="#__codelineno-0-316">316</a></span>
<span class="normal"><a href="#__codelineno-0-317">317</a></span>
<span class="normal"><a href="#__codelineno-0-318">318</a></span>
<span class="normal"><a href="#__codelineno-0-319">319</a></span>
<span class="normal"><a href="#__codelineno-0-320">320</a></span>
<span class="normal"><a href="#__codelineno-0-321">321</a></span>
<span class="normal"><a href="#__codelineno-0-322">322</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-174"><a id="__codelineno-0-174" name="__codelineno-0-174"></a><span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ctx</span><span class="p">:</span> <span class="n">click</span><span class="o">.</span><span class="n">Context</span><span class="p">):</span>
</span><span id="__span-0-175"><a id="__codelineno-0-175" name="__codelineno-0-175"></a> <span class="n">console</span><span class="o">.</span><span class="n">print</span><span class="p">(</span><span class="n">Padding</span><span class="p">(</span><span class="n">Rule</span><span class="p">(</span><span class="sa">f</span><span class="s2">"[rule.text]Service: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2">"</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)))</span>
</span><span id="__span-0-176"><a id="__codelineno-0-176" name="__codelineno-0-176"></a>
</span><span id="__span-0-177"><a id="__codelineno-0-177" name="__codelineno-0-177"></a> <span class="bp">self</span><span class="o">.</span><span class="n">config</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="n">obj</span><span class="o">.</span><span class="n">config</span>
</span><span id="__span-0-178"><a id="__codelineno-0-178" name="__codelineno-0-178"></a>
</span><span id="__span-0-179"><a id="__codelineno-0-179" name="__codelineno-0-179"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">)</span>
</span><span id="__span-0-180"><a id="__codelineno-0-180" name="__codelineno-0-180"></a>
</span><span id="__span-0-181"><a id="__codelineno-0-181" name="__codelineno-0-181"></a> <span class="bp">self</span><span class="o">.</span><span class="n">session</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_session</span><span class="p">()</span>
</span><span id="__span-0-182"><a id="__codelineno-0-182" name="__codelineno-0-182"></a> <span class="bp">self</span><span class="o">.</span><span class="n">cache</span> <span class="o">=</span> <span class="n">Cacher</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">)</span>
</span><span id="__span-0-183"><a id="__codelineno-0-183" name="__codelineno-0-183"></a> <span class="bp">self</span><span class="o">.</span><span class="n">title_cache</span> <span class="o">=</span> <span class="n">TitleCacher</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">)</span>
</span><span id="__span-0-184"><a id="__codelineno-0-184" name="__codelineno-0-184"></a> <span class="bp">self</span><span class="o">.</span><span class="n">cache_dir</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">directories</span><span class="o">.</span><span class="n">cache</span> <span class="o">/</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span>
</span><span id="__span-0-185"><a id="__codelineno-0-185" name="__codelineno-0-185"></a>
</span><span id="__span-0-186"><a id="__codelineno-0-186" name="__codelineno-0-186"></a> <span class="bp">self</span><span class="o">.</span><span class="n">ctx</span> <span class="o">=</span> <span class="n">ctx</span>
</span><span id="__span-0-187"><a id="__codelineno-0-187" name="__codelineno-0-187"></a> <span class="bp">self</span><span class="o">.</span><span class="n">credential</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Will be set in authenticate()</span>
</span><span id="__span-0-188"><a id="__codelineno-0-188" name="__codelineno-0-188"></a> <span class="bp">self</span><span class="o">.</span><span class="n">current_region</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Will be set based on proxy/geolocation</span>
</span><span id="__span-0-189"><a id="__codelineno-0-189" name="__codelineno-0-189"></a> <span class="bp">self</span><span class="o">.</span><span class="n">_input_bridge</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">InputBridge</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
</span><span id="__span-0-190"><a id="__codelineno-0-190" name="__codelineno-0-190"></a>
</span><span id="__span-0-191"><a id="__codelineno-0-191" name="__codelineno-0-191"></a> <span class="c1"># Set track request from CLI params - services can read/override in their __init__</span>
</span><span id="__span-0-192"><a id="__codelineno-0-192" name="__codelineno-0-192"></a> <span class="n">vcodec</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"vcodec"</span><span class="p">)</span> <span class="k">if</span> <span class="n">ctx</span><span class="o">.</span><span class="n">parent</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="__span-0-193"><a id="__codelineno-0-193" name="__codelineno-0-193"></a> <span class="n">range_</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"range_"</span><span class="p">)</span> <span class="k">if</span> <span class="n">ctx</span><span class="o">.</span><span class="n">parent</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="__span-0-194"><a id="__codelineno-0-194" name="__codelineno-0-194"></a> <span class="n">best_available</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"best_available"</span><span class="p">,</span> <span class="kc">False</span><span class="p">)</span> <span class="k">if</span> <span class="n">ctx</span><span class="o">.</span><span class="n">parent</span> <span class="k">else</span> <span class="kc">False</span>
</span><span id="__span-0-195"><a id="__codelineno-0-195" name="__codelineno-0-195"></a> <span class="bp">self</span><span class="o">.</span><span class="n">track_request</span> <span class="o">=</span> <span class="n">TrackRequest</span><span class="p">(</span>
</span><span id="__span-0-196"><a id="__codelineno-0-196" name="__codelineno-0-196"></a> <span class="n">codecs</span><span class="o">=</span><span class="nb">list</span><span class="p">(</span><span class="n">vcodec</span><span class="p">)</span> <span class="k">if</span> <span class="n">vcodec</span> <span class="k">else</span> <span class="p">[],</span>
</span><span id="__span-0-197"><a id="__codelineno-0-197" name="__codelineno-0-197"></a> <span class="n">ranges</span><span class="o">=</span><span class="nb">list</span><span class="p">(</span><span class="n">range_</span><span class="p">)</span> <span class="k">if</span> <span class="n">range_</span> <span class="k">else</span> <span class="p">[</span><span class="n">Video</span><span class="o">.</span><span class="n">Range</span><span class="o">.</span><span class="n">SDR</span><span class="p">],</span>
</span><span id="__span-0-198"><a id="__codelineno-0-198" name="__codelineno-0-198"></a> <span class="n">best_available</span><span class="o">=</span><span class="nb">bool</span><span class="p">(</span><span class="n">best_available</span><span class="p">),</span>
</span><span id="__span-0-199"><a id="__codelineno-0-199" name="__codelineno-0-199"></a> <span class="p">)</span>
</span><span id="__span-0-200"><a id="__codelineno-0-200" name="__codelineno-0-200"></a>
</span><span id="__span-0-201"><a id="__codelineno-0-201" name="__codelineno-0-201"></a> <span class="n">whose</span> <span class="o">=</span> <span class="s2">"the server's"</span> <span class="k">if</span> <span class="n">ctx</span><span class="o">.</span><span class="n">parent</span> <span class="ow">and</span> <span class="n">ctx</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"served"</span><span class="p">)</span> <span class="k">else</span> <span class="s2">"your"</span>
</span><span id="__span-0-202"><a id="__codelineno-0-202" name="__codelineno-0-202"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">ctx</span><span class="o">.</span><span class="n">parent</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">ctx</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"no_proxy"</span><span class="p">):</span>
</span><span id="__span-0-203"><a id="__codelineno-0-203" name="__codelineno-0-203"></a> <span class="k">if</span> <span class="n">ctx</span><span class="o">.</span><span class="n">parent</span><span class="p">:</span>
</span><span id="__span-0-204"><a id="__codelineno-0-204" name="__codelineno-0-204"></a> <span class="n">proxy</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">params</span><span class="p">[</span><span class="s2">"proxy"</span><span class="p">]</span>
</span><span id="__span-0-205"><a id="__codelineno-0-205" name="__codelineno-0-205"></a> <span class="n">proxy_query</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"proxy_query"</span><span class="p">)</span>
</span><span id="__span-0-206"><a id="__codelineno-0-206" name="__codelineno-0-206"></a> <span class="n">proxy_provider_name</span> <span class="o">=</span> <span class="n">ctx</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"proxy_provider"</span><span class="p">)</span>
</span><span id="__span-0-207"><a id="__codelineno-0-207" name="__codelineno-0-207"></a> <span class="k">else</span><span class="p">:</span>
</span><span id="__span-0-208"><a id="__codelineno-0-208" name="__codelineno-0-208"></a> <span class="n">proxy</span> <span class="o">=</span> <span class="kc">None</span>
</span><span id="__span-0-209"><a id="__codelineno-0-209" name="__codelineno-0-209"></a> <span class="n">proxy_query</span> <span class="o">=</span> <span class="kc">None</span>
</span><span id="__span-0-210"><a id="__codelineno-0-210" name="__codelineno-0-210"></a> <span class="n">proxy_provider_name</span> <span class="o">=</span> <span class="kc">None</span>
</span><span id="__span-0-211"><a id="__codelineno-0-211" name="__codelineno-0-211"></a>
</span><span id="__span-0-212"><a id="__codelineno-0-212" name="__codelineno-0-212"></a> <span class="n">service_name</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span>
</span><span id="__span-0-213"><a id="__codelineno-0-213" name="__codelineno-0-213"></a> <span class="n">service_config_dict</span> <span class="o">=</span> <span class="n">config</span><span class="o">.</span><span class="n">services</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">service_name</span><span class="p">,</span> <span class="p">{})</span>
</span><span id="__span-0-214"><a id="__codelineno-0-214" name="__codelineno-0-214"></a> <span class="n">proxy_map</span> <span class="o">=</span> <span class="n">service_config_dict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"proxy_map"</span><span class="p">,</span> <span class="p">{})</span>
</span><span id="__span-0-215"><a id="__codelineno-0-215" name="__codelineno-0-215"></a>
</span><span id="__span-0-216"><a id="__codelineno-0-216" name="__codelineno-0-216"></a> <span class="k">if</span> <span class="n">proxy_map</span> <span class="ow">and</span> <span class="n">proxy_query</span><span class="p">:</span>
</span><span id="__span-0-217"><a id="__codelineno-0-217" name="__codelineno-0-217"></a> <span class="k">if</span> <span class="n">proxy_provider_name</span><span class="p">:</span>
</span><span id="__span-0-218"><a id="__codelineno-0-218" name="__codelineno-0-218"></a> <span class="n">full_proxy_key</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">proxy_provider_name</span><span class="si">}</span><span class="s2">:</span><span class="si">{</span><span class="n">proxy_query</span><span class="si">}</span><span class="s2">"</span>
</span><span id="__span-0-219"><a id="__codelineno-0-219" name="__codelineno-0-219"></a> <span class="k">else</span><span class="p">:</span>
</span><span id="__span-0-220"><a id="__codelineno-0-220" name="__codelineno-0-220"></a> <span class="n">full_proxy_key</span> <span class="o">=</span> <span class="n">proxy_query</span>
</span><span id="__span-0-221"><a id="__codelineno-0-221" name="__codelineno-0-221"></a>
</span><span id="__span-0-222"><a id="__codelineno-0-222" name="__codelineno-0-222"></a> <span class="n">mapped_value</span> <span class="o">=</span> <span class="n">proxy_map</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">full_proxy_key</span><span class="p">)</span>
</span><span id="__span-0-223"><a id="__codelineno-0-223" name="__codelineno-0-223"></a> <span class="k">if</span> <span class="n">mapped_value</span><span class="p">:</span>
</span><span id="__span-0-224"><a id="__codelineno-0-224" name="__codelineno-0-224"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
</span><span id="__span-0-225"><a id="__codelineno-0-225" name="__codelineno-0-225"></a> <span class="sa">f</span><span class="s2">"Found service-specific proxy mapping: </span><span class="si">{</span><span class="n">full_proxy_key</span><span class="si">}</span><span class="s2"> -&gt; </span><span class="si">{</span><span class="n">sanitize_proxy_for_log</span><span class="p">(</span><span class="n">mapped_value</span><span class="p">)</span><span class="si">}</span><span class="s2">"</span>
</span><span id="__span-0-226"><a id="__codelineno-0-226" name="__codelineno-0-226"></a> <span class="p">)</span>
</span><span id="__span-0-227"><a id="__codelineno-0-227" name="__codelineno-0-227"></a> <span class="k">if</span> <span class="n">proxy_provider_name</span><span class="p">:</span>
</span><span id="__span-0-228"><a id="__codelineno-0-228" name="__codelineno-0-228"></a> <span class="c1"># Specific provider requested</span>
</span><span id="__span-0-229"><a id="__codelineno-0-229" name="__codelineno-0-229"></a> <span class="k">try</span><span class="p">:</span>
</span><span id="__span-0-230"><a id="__codelineno-0-230" name="__codelineno-0-230"></a> <span class="n">proxy_provider</span> <span class="o">=</span> <span class="n">find_provider</span><span class="p">(</span><span class="n">ctx</span><span class="o">.</span><span class="n">obj</span><span class="o">.</span><span class="n">proxy_providers</span><span class="p">,</span> <span class="n">proxy_provider_name</span><span class="p">)</span>
</span><span id="__span-0-231"><a id="__codelineno-0-231" name="__codelineno-0-231"></a> <span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
</span><span id="__span-0-232"><a id="__codelineno-0-232" name="__codelineno-0-232"></a> <span class="n">proxy_provider</span> <span class="o">=</span> <span class="kc">None</span>
</span><span id="__span-0-233"><a id="__codelineno-0-233" name="__codelineno-0-233"></a> <span class="k">if</span> <span class="n">proxy_provider</span><span class="p">:</span>
</span><span id="__span-0-234"><a id="__codelineno-0-234" name="__codelineno-0-234"></a> <span class="n">mapped_proxy_uri</span> <span class="o">=</span> <span class="n">proxy_provider</span><span class="o">.</span><span class="n">get_proxy</span><span class="p">(</span><span class="n">mapped_value</span><span class="p">)</span>
</span><span id="__span-0-235"><a id="__codelineno-0-235" name="__codelineno-0-235"></a> <span class="k">if</span> <span class="n">mapped_proxy_uri</span><span class="p">:</span>
</span><span id="__span-0-236"><a id="__codelineno-0-236" name="__codelineno-0-236"></a> <span class="n">proxy</span> <span class="o">=</span> <span class="n">mapped_proxy_uri</span>
</span><span id="__span-0-237"><a id="__codelineno-0-237" name="__codelineno-0-237"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
</span><span id="__span-0-238"><a id="__codelineno-0-238" name="__codelineno-0-238"></a> <span class="sa">f</span><span class="s2">"Using mapped proxy from </span><span class="si">{</span><span class="n">proxy_provider</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2">: "</span>
</span><span id="__span-0-239"><a id="__codelineno-0-239" name="__codelineno-0-239"></a> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">sanitize_proxy_for_log</span><span class="p">(</span><span class="n">proxy</span><span class="p">,</span><span class="w"> </span><span class="n">mask_host</span><span class="o">=</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">proxy_provider</span><span class="p">,</span><span class="w"> </span><span class="n">Basic</span><span class="p">))</span><span class="si">}</span><span class="s2">"</span>
</span><span id="__span-0-240"><a id="__codelineno-0-240" name="__codelineno-0-240"></a> <span class="p">)</span>
</span><span id="__span-0-241"><a id="__codelineno-0-241" name="__codelineno-0-241"></a> <span class="k">else</span><span class="p">:</span>
</span><span id="__span-0-242"><a id="__codelineno-0-242" name="__codelineno-0-242"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
</span><span id="__span-0-243"><a id="__codelineno-0-243" name="__codelineno-0-243"></a> <span class="sa">f</span><span class="s2">"Failed to get proxy for mapped value '</span><span class="si">{</span><span class="n">sanitize_proxy_for_log</span><span class="p">(</span><span class="n">mapped_value</span><span class="p">)</span><span class="si">}</span><span class="s2">', using default"</span>
</span><span id="__span-0-244"><a id="__codelineno-0-244" name="__codelineno-0-244"></a> <span class="p">)</span>
</span><span id="__span-0-245"><a id="__codelineno-0-245" name="__codelineno-0-245"></a> <span class="k">else</span><span class="p">:</span>
</span><span id="__span-0-246"><a id="__codelineno-0-246" name="__codelineno-0-246"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Proxy provider '</span><span class="si">{</span><span class="n">proxy_provider_name</span><span class="si">}</span><span class="s2">' not found, using default proxy"</span><span class="p">)</span>
</span><span id="__span-0-247"><a id="__codelineno-0-247" name="__codelineno-0-247"></a> <span class="k">else</span><span class="p">:</span>
</span><span id="__span-0-248"><a id="__codelineno-0-248" name="__codelineno-0-248"></a> <span class="k">for</span> <span class="n">proxy_provider</span> <span class="ow">in</span> <span class="n">ctx</span><span class="o">.</span><span class="n">obj</span><span class="o">.</span><span class="n">proxy_providers</span><span class="p">:</span>
</span><span id="__span-0-249"><a id="__codelineno-0-249" name="__codelineno-0-249"></a> <span class="n">mapped_proxy_uri</span> <span class="o">=</span> <span class="n">proxy_provider</span><span class="o">.</span><span class="n">get_proxy</span><span class="p">(</span><span class="n">mapped_value</span><span class="p">)</span>
</span><span id="__span-0-250"><a id="__codelineno-0-250" name="__codelineno-0-250"></a> <span class="k">if</span> <span class="n">mapped_proxy_uri</span><span class="p">:</span>
</span><span id="__span-0-251"><a id="__codelineno-0-251" name="__codelineno-0-251"></a> <span class="n">proxy</span> <span class="o">=</span> <span class="n">mapped_proxy_uri</span>
</span><span id="__span-0-252"><a id="__codelineno-0-252" name="__codelineno-0-252"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
</span><span id="__span-0-253"><a id="__codelineno-0-253" name="__codelineno-0-253"></a> <span class="sa">f</span><span class="s2">"Using mapped proxy from </span><span class="si">{</span><span class="n">proxy_provider</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2">: "</span>
</span><span id="__span-0-254"><a id="__codelineno-0-254" name="__codelineno-0-254"></a> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">sanitize_proxy_for_log</span><span class="p">(</span><span class="n">proxy</span><span class="p">,</span><span class="w"> </span><span class="n">mask_host</span><span class="o">=</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">proxy_provider</span><span class="p">,</span><span class="w"> </span><span class="n">Basic</span><span class="p">))</span><span class="si">}</span><span class="s2">"</span>
</span><span id="__span-0-255"><a id="__codelineno-0-255" name="__codelineno-0-255"></a> <span class="p">)</span>
</span><span id="__span-0-256"><a id="__codelineno-0-256" name="__codelineno-0-256"></a> <span class="k">break</span>
</span><span id="__span-0-257"><a id="__codelineno-0-257" name="__codelineno-0-257"></a> <span class="k">else</span><span class="p">:</span>
</span><span id="__span-0-258"><a id="__codelineno-0-258" name="__codelineno-0-258"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
</span><span id="__span-0-259"><a id="__codelineno-0-259" name="__codelineno-0-259"></a> <span class="sa">f</span><span class="s2">"No provider could resolve mapped value '</span><span class="si">{</span><span class="n">sanitize_proxy_for_log</span><span class="p">(</span><span class="n">mapped_value</span><span class="p">)</span><span class="si">}</span><span class="s2">', using default"</span>
</span><span id="__span-0-260"><a id="__codelineno-0-260" name="__codelineno-0-260"></a> <span class="p">)</span>
</span><span id="__span-0-261"><a id="__codelineno-0-261" name="__codelineno-0-261"></a>
</span><span id="__span-0-262"><a id="__codelineno-0-262" name="__codelineno-0-262"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">proxy</span><span class="p">:</span>
</span><span id="__span-0-263"><a id="__codelineno-0-263" name="__codelineno-0-263"></a> <span class="c1"># don't override the explicit proxy set by the user, even if they may be geoblocked</span>
</span><span id="__span-0-264"><a id="__codelineno-0-264" name="__codelineno-0-264"></a> <span class="k">with</span> <span class="n">console</span><span class="o">.</span><span class="n">status</span><span class="p">(</span><span class="s2">"Checking if current region is Geoblocked..."</span><span class="p">,</span> <span class="n">spinner</span><span class="o">=</span><span class="s2">"dots"</span><span class="p">):</span>
</span><span id="__span-0-265"><a id="__codelineno-0-265" name="__codelineno-0-265"></a> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">GEOFENCE</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">GEOBLOCK</span><span class="p">:</span>
</span><span id="__span-0-266"><a id="__codelineno-0-266" name="__codelineno-0-266"></a> <span class="k">try</span><span class="p">:</span>
</span><span id="__span-0-267"><a id="__codelineno-0-267" name="__codelineno-0-267"></a> <span class="n">current_region</span> <span class="o">=</span> <span class="p">(</span><span class="n">get_ip_info</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="p">)</span> <span class="ow">or</span> <span class="p">{})</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"country"</span><span class="p">,</span> <span class="s2">""</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span><span id="__span-0-268"><a id="__codelineno-0-268" name="__codelineno-0-268"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">current_region</span><span class="p">:</span>
</span><span id="__span-0-269"><a id="__codelineno-0-269" name="__codelineno-0-269"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Could not find </span><span class="si">{</span><span class="n">whose</span><span class="si">}</span><span class="s2"> region, so the region check does not run"</span><span class="p">)</span>
</span><span id="__span-0-270"><a id="__codelineno-0-270" name="__codelineno-0-270"></a> <span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_region_allowed</span><span class="p">(</span><span class="n">current_region</span><span class="p">):</span>
</span><span id="__span-0-271"><a id="__codelineno-0-271" name="__codelineno-0-271"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">"Service is not Geoblocked in your region"</span><span class="p">)</span>
</span><span id="__span-0-272"><a id="__codelineno-0-272" name="__codelineno-0-272"></a> <span class="k">elif</span> <span class="ow">not</span> <span class="p">(</span><span class="n">fence_targets</span> <span class="o">:=</span> <span class="p">[</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">GEOFENCE</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">is_region_allowed</span><span class="p">(</span><span class="n">x</span><span class="p">)]):</span>
</span><span id="__span-0-273"><a id="__codelineno-0-273" name="__codelineno-0-273"></a> <span class="k">raise</span> <span class="n">click</span><span class="o">.</span><span class="n">ClickException</span><span class="p">(</span>
</span><span id="__span-0-274"><a id="__codelineno-0-274" name="__codelineno-0-274"></a> <span class="sa">f</span><span class="s2">"Service is not available in </span><span class="si">{</span><span class="n">whose</span><span class="si">}</span><span class="s2"> region (</span><span class="si">{</span><span class="n">current_region</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span><span class="si">}</span><span class="s2">). "</span>
</span><span id="__span-0-275"><a id="__codelineno-0-275" name="__codelineno-0-275"></a> <span class="s2">"Pass --proxy with a proxy outside the blocked regions."</span>
</span><span id="__span-0-276"><a id="__codelineno-0-276" name="__codelineno-0-276"></a> <span class="p">)</span>
</span><span id="__span-0-277"><a id="__codelineno-0-277" name="__codelineno-0-277"></a> <span class="k">else</span><span class="p">:</span>
</span><span id="__span-0-278"><a id="__codelineno-0-278" name="__codelineno-0-278"></a> <span class="n">requested_proxy</span> <span class="o">=</span> <span class="n">fence_targets</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="c1"># first is likely main region</span>
</span><span id="__span-0-279"><a id="__codelineno-0-279" name="__codelineno-0-279"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span>
</span><span id="__span-0-280"><a id="__codelineno-0-280" name="__codelineno-0-280"></a> <span class="sa">f</span><span class="s2">"Service is Geoblocked in your region, getting a Proxy to </span><span class="si">{</span><span class="n">requested_proxy</span><span class="si">}</span><span class="s2">"</span>
</span><span id="__span-0-281"><a id="__codelineno-0-281" name="__codelineno-0-281"></a> <span class="p">)</span>
</span><span id="__span-0-282"><a id="__codelineno-0-282" name="__codelineno-0-282"></a> <span class="k">for</span> <span class="n">proxy_provider</span> <span class="ow">in</span> <span class="n">ctx</span><span class="o">.</span><span class="n">obj</span><span class="o">.</span><span class="n">proxy_providers</span><span class="p">:</span>
</span><span id="__span-0-283"><a id="__codelineno-0-283" name="__codelineno-0-283"></a> <span class="n">proxy</span> <span class="o">=</span> <span class="n">proxy_provider</span><span class="o">.</span><span class="n">get_proxy</span><span class="p">(</span><span class="n">requested_proxy</span><span class="p">)</span>
</span><span id="__span-0-284"><a id="__codelineno-0-284" name="__codelineno-0-284"></a> <span class="k">if</span> <span class="n">proxy</span><span class="p">:</span>
</span><span id="__span-0-285"><a id="__codelineno-0-285" name="__codelineno-0-285"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Got Proxy from </span><span class="si">{</span><span class="n">proxy_provider</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
</span><span id="__span-0-286"><a id="__codelineno-0-286" name="__codelineno-0-286"></a> <span class="k">break</span>
</span><span id="__span-0-287"><a id="__codelineno-0-287" name="__codelineno-0-287"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">proxy</span><span class="p">:</span>
</span><span id="__span-0-288"><a id="__codelineno-0-288" name="__codelineno-0-288"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span>
</span><span id="__span-0-289"><a id="__codelineno-0-289" name="__codelineno-0-289"></a> <span class="sa">f</span><span class="s2">"No proxy available for </span><span class="si">{</span><span class="n">requested_proxy</span><span class="si">}</span><span class="s2">. "</span>
</span><span id="__span-0-290"><a id="__codelineno-0-290" name="__codelineno-0-290"></a> <span class="sa">f</span><span class="s2">"Pass --proxy with a proxy in </span><span class="si">{</span><span class="n">requested_proxy</span><span class="si">}</span><span class="s2">, or the request can fail."</span>
</span><span id="__span-0-291"><a id="__codelineno-0-291" name="__codelineno-0-291"></a> <span class="p">)</span>
</span><span id="__span-0-292"><a id="__codelineno-0-292" name="__codelineno-0-292"></a> <span class="k">except</span> <span class="n">click</span><span class="o">.</span><span class="n">ClickException</span><span class="p">:</span>
</span><span id="__span-0-293"><a id="__codelineno-0-293" name="__codelineno-0-293"></a> <span class="k">raise</span>
</span><span id="__span-0-294"><a id="__codelineno-0-294" name="__codelineno-0-294"></a> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
</span><span id="__span-0-295"><a id="__codelineno-0-295" name="__codelineno-0-295"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Failed to check geofence: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
</span><span id="__span-0-296"><a id="__codelineno-0-296" name="__codelineno-0-296"></a> <span class="k">else</span><span class="p">:</span>
</span><span id="__span-0-297"><a id="__codelineno-0-297" name="__codelineno-0-297"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">"Service has no region restrictions"</span><span class="p">)</span>
</span><span id="__span-0-298"><a id="__codelineno-0-298" name="__codelineno-0-298"></a>
</span><span id="__span-0-299"><a id="__codelineno-0-299" name="__codelineno-0-299"></a> <span class="k">if</span> <span class="n">proxy</span><span class="p">:</span>
</span><span id="__span-0-300"><a id="__codelineno-0-300" name="__codelineno-0-300"></a> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">proxies</span><span class="o">.</span><span class="n">update</span><span class="p">({</span><span class="s2">"all"</span><span class="p">:</span> <span class="n">proxy</span><span class="p">})</span>
</span><span id="__span-0-301"><a id="__codelineno-0-301" name="__codelineno-0-301"></a> <span class="c1"># Don't set Proxy-Authorization manually: both rnet (Proxy.all) and</span>
</span><span id="__span-0-302"><a id="__codelineno-0-302" name="__codelineno-0-302"></a> <span class="c1"># requests authenticate from the credentials embedded in the proxy URL.</span>
</span><span id="__span-0-303"><a id="__codelineno-0-303" name="__codelineno-0-303"></a> <span class="c1"># A manual header here was malformed (no "Basic " scheme) and broke</span>
</span><span id="__span-0-304"><a id="__codelineno-0-304" name="__codelineno-0-304"></a> <span class="c1"># plaintext-http forward-proxy requests with HTTP 407.</span>
</span><span id="__span-0-305"><a id="__codelineno-0-305" name="__codelineno-0-305"></a> <span class="c1"># Verify the proxy IP every time, because a proxy can change its exit node. A dead</span>
</span><span id="__span-0-306"><a id="__codelineno-0-306" name="__codelineno-0-306"></a> <span class="c1"># proxy fails here, not after every service request has used up its retries.</span>
</span><span id="__span-0-307"><a id="__codelineno-0-307" name="__codelineno-0-307"></a> <span class="n">exit_region</span> <span class="o">=</span> <span class="n">verify_proxy_exit</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="p">)</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"country"</span><span class="p">)</span>
</span><span id="__span-0-308"><a id="__codelineno-0-308" name="__codelineno-0-308"></a> <span class="bp">self</span><span class="o">.</span><span class="n">current_region</span> <span class="o">=</span> <span class="n">exit_region</span>
</span><span id="__span-0-309"><a id="__codelineno-0-309" name="__codelineno-0-309"></a> <span class="c1"># Only GEOBLOCK applies here: an explicit --proxy outside GEOFENCE stays the user's call.</span>
</span><span id="__span-0-310"><a id="__codelineno-0-310" name="__codelineno-0-310"></a> <span class="k">if</span> <span class="n">exit_region</span> <span class="ow">and</span> <span class="nb">any</span><span class="p">(</span><span class="n">x</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="n">exit_region</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">GEOBLOCK</span><span class="p">):</span>
</span><span id="__span-0-311"><a id="__codelineno-0-311" name="__codelineno-0-311"></a> <span class="k">raise</span> <span class="n">click</span><span class="o">.</span><span class="n">ClickException</span><span class="p">(</span>
</span><span id="__span-0-312"><a id="__codelineno-0-312" name="__codelineno-0-312"></a> <span class="sa">f</span><span class="s2">"Service is not available in </span><span class="si">{</span><span class="n">whose</span><span class="si">}</span><span class="s2"> proxy's region (</span><span class="si">{</span><span class="n">exit_region</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span><span class="si">}</span><span class="s2">). "</span>
</span><span id="__span-0-313"><a id="__codelineno-0-313" name="__codelineno-0-313"></a> <span class="s2">"Pass --proxy with a proxy outside the blocked regions."</span>
</span><span id="__span-0-314"><a id="__codelineno-0-314" name="__codelineno-0-314"></a> <span class="p">)</span>
</span><span id="__span-0-315"><a id="__codelineno-0-315" name="__codelineno-0-315"></a> <span class="k">else</span><span class="p">:</span>
</span><span id="__span-0-316"><a id="__codelineno-0-316" name="__codelineno-0-316"></a> <span class="c1"># No proxy, use cached IP info for title caching (non-critical)</span>
</span><span id="__span-0-317"><a id="__codelineno-0-317" name="__codelineno-0-317"></a> <span class="k">try</span><span class="p">:</span>
</span><span id="__span-0-318"><a id="__codelineno-0-318" name="__codelineno-0-318"></a> <span class="n">ip_info</span> <span class="o">=</span> <span class="n">get_ip_info</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="p">,</span> <span class="n">cached</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-0-319"><a id="__codelineno-0-319" name="__codelineno-0-319"></a> <span class="bp">self</span><span class="o">.</span><span class="n">current_region</span> <span class="o">=</span> <span class="n">ip_info</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"country"</span><span class="p">,</span> <span class="s2">""</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="k">if</span> <span class="n">ip_info</span> <span class="k">else</span> <span class="kc">None</span>
</span><span id="__span-0-320"><a id="__codelineno-0-320" name="__codelineno-0-320"></a> <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
</span><span id="__span-0-321"><a id="__codelineno-0-321" name="__codelineno-0-321"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Failed to get cached IP info: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
</span><span id="__span-0-322"><a id="__codelineno-0-322" name="__codelineno-0-322"></a> <span class="bp">self</span><span class="o">.</span><span class="n">current_region</span> <span class="o">=</span> <span class="kc">None</span>
</span></code></pre></div></td></tr></table></div>
</details>
<div class="doc doc-children">
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.is_region_allowed" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">is_region_allowed</span>
<span class="doc doc-labels">
<small class="doc doc-label doc-label-classmethod"><code>classmethod</code></small>
</span>
<a href="#unshackle.core.service.Service.is_region_allowed" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">is_region_allowed</span><span class="p">(</span><span class="n">region</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>True when an exit IP in <code>region</code> (two-letter region code, any case) can use the service.</p>
<p>An unknown region (None or empty) is allowed, because there is nothing to compare.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-324">324</a></span>
<span class="normal"><a href="#__codelineno-0-325">325</a></span>
<span class="normal"><a href="#__codelineno-0-326">326</a></span>
<span class="normal"><a href="#__codelineno-0-327">327</a></span>
<span class="normal"><a href="#__codelineno-0-328">328</a></span>
<span class="normal"><a href="#__codelineno-0-329">329</a></span>
<span class="normal"><a href="#__codelineno-0-330">330</a></span>
<span class="normal"><a href="#__codelineno-0-331">331</a></span>
<span class="normal"><a href="#__codelineno-0-332">332</a></span>
<span class="normal"><a href="#__codelineno-0-333">333</a></span>
<span class="normal"><a href="#__codelineno-0-334">334</a></span>
<span class="normal"><a href="#__codelineno-0-335">335</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-324"><a id="__codelineno-0-324" name="__codelineno-0-324"></a><span class="nd">@classmethod</span>
</span><span id="__span-0-325"><a id="__codelineno-0-325" name="__codelineno-0-325"></a><span class="k">def</span><span class="w"> </span><span class="nf">is_region_allowed</span><span class="p">(</span><span class="bp">cls</span><span class="p">,</span> <span class="n">region</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">])</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
</span><span id="__span-0-326"><a id="__codelineno-0-326" name="__codelineno-0-326"></a><span class="w"> </span><span class="sd">"""True when an exit IP in `region` (two-letter region code, any case) can use the service.</span>
</span><span id="__span-0-327"><a id="__codelineno-0-327" name="__codelineno-0-327"></a>
</span><span id="__span-0-328"><a id="__codelineno-0-328" name="__codelineno-0-328"></a><span class="sd"> An unknown region (None or empty) is allowed, because there is nothing to compare.</span>
</span><span id="__span-0-329"><a id="__codelineno-0-329" name="__codelineno-0-329"></a><span class="sd"> """</span>
</span><span id="__span-0-330"><a id="__codelineno-0-330" name="__codelineno-0-330"></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">region</span><span class="p">:</span>
</span><span id="__span-0-331"><a id="__codelineno-0-331" name="__codelineno-0-331"></a> <span class="k">return</span> <span class="kc">True</span>
</span><span id="__span-0-332"><a id="__codelineno-0-332" name="__codelineno-0-332"></a> <span class="n">region</span> <span class="o">=</span> <span class="n">region</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span><span id="__span-0-333"><a id="__codelineno-0-333" name="__codelineno-0-333"></a> <span class="k">if</span> <span class="nb">any</span><span class="p">(</span><span class="n">x</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="n">region</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">GEOBLOCK</span><span class="p">):</span>
</span><span id="__span-0-334"><a id="__codelineno-0-334" name="__codelineno-0-334"></a> <span class="k">return</span> <span class="kc">False</span>
</span><span id="__span-0-335"><a id="__codelineno-0-335" name="__codelineno-0-335"></a> <span class="k">return</span> <span class="ow">not</span> <span class="bp">cls</span><span class="o">.</span><span class="n">GEOFENCE</span> <span class="ow">or</span> <span class="nb">any</span><span class="p">(</span><span class="n">x</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="n">region</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="bp">cls</span><span class="o">.</span><span class="n">GEOFENCE</span><span class="p">)</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.get_tracks_for_variants" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">get_tracks_for_variants</span>
<a href="#unshackle.core.service.Service.get_tracks_for_variants" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">get_tracks_for_variants</span><span class="p">(</span><span class="n">title</span><span class="p">,</span> <span class="n">fetch_fn</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Call fetch_fn for each codec/range combo in track_request, merge results.</p>
<p>Services that need separate API calls per codec/range combo can use this
helper from their get_tracks() implementation.</p>
<p>The fetch_fn signature should be: (title, codec, range_) -&gt; Tracks</p>
<p>For HYBRID range, this helper calls fetch_fn with HDR10 and DV separately,
then merges the DV video tracks into the HDR10 result.</p>
<p><span class="doc-section-title">Parameters:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td>
<code>title</code>
</td>
<td>
<code><span title="unshackle.core.titles.Title_T">Title_T</span></code>
</td>
<td>
<div class="doc-md-description">
<p>The title to process.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>fetch_fn</code>
</td>
<td>
<code><span title="collections.abc.Callable">Callable</span>[..., <a class="autorefs autorefs-internal" title="&lt;code class=&quot;doc-symbol doc-symbol-heading doc-symbol-class&quot;&gt;&lt;/code&gt; &lt;span class=&quot;doc doc-object-name doc-class-name&quot;&gt;Tracks&lt;/span&gt; (&lt;code&gt;unshackle.core.tracks.Tracks&lt;/code&gt;)" href="../tracks/#unshackle.core.tracks.Tracks">Tracks</a>]</code>
</td>
<td>
<div class="doc-md-description">
<p>A callable that fetches tracks for a specific codec/range.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
</tbody>
</table>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-337">337</a></span>
<span class="normal"><a href="#__codelineno-0-338">338</a></span>
<span class="normal"><a href="#__codelineno-0-339">339</a></span>
<span class="normal"><a href="#__codelineno-0-340">340</a></span>
<span class="normal"><a href="#__codelineno-0-341">341</a></span>
<span class="normal"><a href="#__codelineno-0-342">342</a></span>
<span class="normal"><a href="#__codelineno-0-343">343</a></span>
<span class="normal"><a href="#__codelineno-0-344">344</a></span>
<span class="normal"><a href="#__codelineno-0-345">345</a></span>
<span class="normal"><a href="#__codelineno-0-346">346</a></span>
<span class="normal"><a href="#__codelineno-0-347">347</a></span>
<span class="normal"><a href="#__codelineno-0-348">348</a></span>
<span class="normal"><a href="#__codelineno-0-349">349</a></span>
<span class="normal"><a href="#__codelineno-0-350">350</a></span>
<span class="normal"><a href="#__codelineno-0-351">351</a></span>
<span class="normal"><a href="#__codelineno-0-352">352</a></span>
<span class="normal"><a href="#__codelineno-0-353">353</a></span>
<span class="normal"><a href="#__codelineno-0-354">354</a></span>
<span class="normal"><a href="#__codelineno-0-355">355</a></span>
<span class="normal"><a href="#__codelineno-0-356">356</a></span>
<span class="normal"><a href="#__codelineno-0-357">357</a></span>
<span class="normal"><a href="#__codelineno-0-358">358</a></span>
<span class="normal"><a href="#__codelineno-0-359">359</a></span>
<span class="normal"><a href="#__codelineno-0-360">360</a></span>
<span class="normal"><a href="#__codelineno-0-361">361</a></span>
<span class="normal"><a href="#__codelineno-0-362">362</a></span>
<span class="normal"><a href="#__codelineno-0-363">363</a></span>
<span class="normal"><a href="#__codelineno-0-364">364</a></span>
<span class="normal"><a href="#__codelineno-0-365">365</a></span>
<span class="normal"><a href="#__codelineno-0-366">366</a></span>
<span class="normal"><a href="#__codelineno-0-367">367</a></span>
<span class="normal"><a href="#__codelineno-0-368">368</a></span>
<span class="normal"><a href="#__codelineno-0-369">369</a></span>
<span class="normal"><a href="#__codelineno-0-370">370</a></span>
<span class="normal"><a href="#__codelineno-0-371">371</a></span>
<span class="normal"><a href="#__codelineno-0-372">372</a></span>
<span class="normal"><a href="#__codelineno-0-373">373</a></span>
<span class="normal"><a href="#__codelineno-0-374">374</a></span>
<span class="normal"><a href="#__codelineno-0-375">375</a></span>
<span class="normal"><a href="#__codelineno-0-376">376</a></span>
<span class="normal"><a href="#__codelineno-0-377">377</a></span>
<span class="normal"><a href="#__codelineno-0-378">378</a></span>
<span class="normal"><a href="#__codelineno-0-379">379</a></span>
<span class="normal"><a href="#__codelineno-0-380">380</a></span>
<span class="normal"><a href="#__codelineno-0-381">381</a></span>
<span class="normal"><a href="#__codelineno-0-382">382</a></span>
<span class="normal"><a href="#__codelineno-0-383">383</a></span>
<span class="normal"><a href="#__codelineno-0-384">384</a></span>
<span class="normal"><a href="#__codelineno-0-385">385</a></span>
<span class="normal"><a href="#__codelineno-0-386">386</a></span>
<span class="normal"><a href="#__codelineno-0-387">387</a></span>
<span class="normal"><a href="#__codelineno-0-388">388</a></span>
<span class="normal"><a href="#__codelineno-0-389">389</a></span>
<span class="normal"><a href="#__codelineno-0-390">390</a></span>
<span class="normal"><a href="#__codelineno-0-391">391</a></span>
<span class="normal"><a href="#__codelineno-0-392">392</a></span>
<span class="normal"><a href="#__codelineno-0-393">393</a></span>
<span class="normal"><a href="#__codelineno-0-394">394</a></span>
<span class="normal"><a href="#__codelineno-0-395">395</a></span>
<span class="normal"><a href="#__codelineno-0-396">396</a></span>
<span class="normal"><a href="#__codelineno-0-397">397</a></span>
<span class="normal"><a href="#__codelineno-0-398">398</a></span>
<span class="normal"><a href="#__codelineno-0-399">399</a></span>
<span class="normal"><a href="#__codelineno-0-400">400</a></span>
<span class="normal"><a href="#__codelineno-0-401">401</a></span>
<span class="normal"><a href="#__codelineno-0-402">402</a></span>
<span class="normal"><a href="#__codelineno-0-403">403</a></span>
<span class="normal"><a href="#__codelineno-0-404">404</a></span>
<span class="normal"><a href="#__codelineno-0-405">405</a></span>
<span class="normal"><a href="#__codelineno-0-406">406</a></span>
<span class="normal"><a href="#__codelineno-0-407">407</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-337"><a id="__codelineno-0-337" name="__codelineno-0-337"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_tracks_for_variants</span><span class="p">(</span>
</span><span id="__span-0-338"><a id="__codelineno-0-338" name="__codelineno-0-338"></a> <span class="bp">self</span><span class="p">,</span>
</span><span id="__span-0-339"><a id="__codelineno-0-339" name="__codelineno-0-339"></a> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">,</span>
</span><span id="__span-0-340"><a id="__codelineno-0-340" name="__codelineno-0-340"></a> <span class="n">fetch_fn</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">Tracks</span><span class="p">],</span>
</span><span id="__span-0-341"><a id="__codelineno-0-341" name="__codelineno-0-341"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Tracks</span><span class="p">:</span>
</span><span id="__span-0-342"><a id="__codelineno-0-342" name="__codelineno-0-342"></a><span class="w"> </span><span class="sd">"""Call fetch_fn for each codec/range combo in track_request, merge results.</span>
</span><span id="__span-0-343"><a id="__codelineno-0-343" name="__codelineno-0-343"></a>
</span><span id="__span-0-344"><a id="__codelineno-0-344" name="__codelineno-0-344"></a><span class="sd"> Services that need separate API calls per codec/range combo can use this</span>
</span><span id="__span-0-345"><a id="__codelineno-0-345" name="__codelineno-0-345"></a><span class="sd"> helper from their get_tracks() implementation.</span>
</span><span id="__span-0-346"><a id="__codelineno-0-346" name="__codelineno-0-346"></a>
</span><span id="__span-0-347"><a id="__codelineno-0-347" name="__codelineno-0-347"></a><span class="sd"> The fetch_fn signature should be: (title, codec, range_) -&gt; Tracks</span>
</span><span id="__span-0-348"><a id="__codelineno-0-348" name="__codelineno-0-348"></a>
</span><span id="__span-0-349"><a id="__codelineno-0-349" name="__codelineno-0-349"></a><span class="sd"> For HYBRID range, this helper calls fetch_fn with HDR10 and DV separately,</span>
</span><span id="__span-0-350"><a id="__codelineno-0-350" name="__codelineno-0-350"></a><span class="sd"> then merges the DV video tracks into the HDR10 result.</span>
</span><span id="__span-0-351"><a id="__codelineno-0-351" name="__codelineno-0-351"></a>
</span><span id="__span-0-352"><a id="__codelineno-0-352" name="__codelineno-0-352"></a><span class="sd"> Args:</span>
</span><span id="__span-0-353"><a id="__codelineno-0-353" name="__codelineno-0-353"></a><span class="sd"> title: The title to process.</span>
</span><span id="__span-0-354"><a id="__codelineno-0-354" name="__codelineno-0-354"></a><span class="sd"> fetch_fn: A callable that fetches tracks for a specific codec/range.</span>
</span><span id="__span-0-355"><a id="__codelineno-0-355" name="__codelineno-0-355"></a><span class="sd"> """</span>
</span><span id="__span-0-356"><a id="__codelineno-0-356" name="__codelineno-0-356"></a> <span class="n">all_tracks</span> <span class="o">=</span> <span class="n">Tracks</span><span class="p">()</span>
</span><span id="__span-0-357"><a id="__codelineno-0-357" name="__codelineno-0-357"></a> <span class="n">first</span> <span class="o">=</span> <span class="kc">True</span>
</span><span id="__span-0-358"><a id="__codelineno-0-358" name="__codelineno-0-358"></a>
</span><span id="__span-0-359"><a id="__codelineno-0-359" name="__codelineno-0-359"></a> <span class="n">codecs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">track_request</span><span class="o">.</span><span class="n">codecs</span> <span class="ow">or</span> <span class="p">[</span><span class="kc">None</span><span class="p">]</span>
</span><span id="__span-0-360"><a id="__codelineno-0-360" name="__codelineno-0-360"></a> <span class="n">ranges</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">track_request</span><span class="o">.</span><span class="n">ranges</span> <span class="ow">or</span> <span class="p">[</span><span class="n">Video</span><span class="o">.</span><span class="n">Range</span><span class="o">.</span><span class="n">SDR</span><span class="p">]</span>
</span><span id="__span-0-361"><a id="__codelineno-0-361" name="__codelineno-0-361"></a>
</span><span id="__span-0-362"><a id="__codelineno-0-362" name="__codelineno-0-362"></a> <span class="k">for</span> <span class="n">range_val</span> <span class="ow">in</span> <span class="n">ranges</span><span class="p">:</span>
</span><span id="__span-0-363"><a id="__codelineno-0-363" name="__codelineno-0-363"></a> <span class="k">if</span> <span class="n">range_val</span> <span class="o">==</span> <span class="n">Video</span><span class="o">.</span><span class="n">Range</span><span class="o">.</span><span class="n">HYBRID</span><span class="p">:</span>
</span><span id="__span-0-364"><a id="__codelineno-0-364" name="__codelineno-0-364"></a> <span class="c1"># HYBRID: fetch HDR10 first (full tracks), then DV (video only)</span>
</span><span id="__span-0-365"><a id="__codelineno-0-365" name="__codelineno-0-365"></a> <span class="k">for</span> <span class="n">codec_val</span> <span class="ow">in</span> <span class="n">codecs</span><span class="p">:</span>
</span><span id="__span-0-366"><a id="__codelineno-0-366" name="__codelineno-0-366"></a> <span class="k">try</span><span class="p">:</span>
</span><span id="__span-0-367"><a id="__codelineno-0-367" name="__codelineno-0-367"></a> <span class="n">hdr_tracks</span> <span class="o">=</span> <span class="n">fetch_fn</span><span class="p">(</span><span class="n">title</span><span class="p">,</span> <span class="n">codec</span><span class="o">=</span><span class="n">codec_val</span><span class="p">,</span> <span class="n">range_</span><span class="o">=</span><span class="n">Video</span><span class="o">.</span><span class="n">Range</span><span class="o">.</span><span class="n">HDR10</span><span class="p">)</span>
</span><span id="__span-0-368"><a id="__codelineno-0-368" name="__codelineno-0-368"></a> <span class="k">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">SystemExit</span><span class="p">)</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
</span><span id="__span-0-369"><a id="__codelineno-0-369" name="__codelineno-0-369"></a> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">track_request</span><span class="o">.</span><span class="n">best_available</span><span class="p">:</span>
</span><span id="__span-0-370"><a id="__codelineno-0-370" name="__codelineno-0-370"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">" - HDR10 not available for HYBRID, skipping (</span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">)"</span><span class="p">)</span>
</span><span id="__span-0-371"><a id="__codelineno-0-371" name="__codelineno-0-371"></a> <span class="k">continue</span>
</span><span id="__span-0-372"><a id="__codelineno-0-372" name="__codelineno-0-372"></a> <span class="k">raise</span>
</span><span id="__span-0-373"><a id="__codelineno-0-373" name="__codelineno-0-373"></a> <span class="k">if</span> <span class="n">first</span><span class="p">:</span>
</span><span id="__span-0-374"><a id="__codelineno-0-374" name="__codelineno-0-374"></a> <span class="n">all_tracks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">hdr_tracks</span><span class="p">,</span> <span class="n">warn_only</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-0-375"><a id="__codelineno-0-375" name="__codelineno-0-375"></a> <span class="k">if</span> <span class="n">hdr_tracks</span><span class="o">.</span><span class="n">manifest_url</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">all_tracks</span><span class="o">.</span><span class="n">manifest_url</span><span class="p">:</span>
</span><span id="__span-0-376"><a id="__codelineno-0-376" name="__codelineno-0-376"></a> <span class="n">all_tracks</span><span class="o">.</span><span class="n">manifest_url</span> <span class="o">=</span> <span class="n">hdr_tracks</span><span class="o">.</span><span class="n">manifest_url</span>
</span><span id="__span-0-377"><a id="__codelineno-0-377" name="__codelineno-0-377"></a> <span class="n">first</span> <span class="o">=</span> <span class="kc">False</span>
</span><span id="__span-0-378"><a id="__codelineno-0-378" name="__codelineno-0-378"></a> <span class="k">else</span><span class="p">:</span>
</span><span id="__span-0-379"><a id="__codelineno-0-379" name="__codelineno-0-379"></a> <span class="k">for</span> <span class="n">video</span> <span class="ow">in</span> <span class="n">hdr_tracks</span><span class="o">.</span><span class="n">videos</span><span class="p">:</span>
</span><span id="__span-0-380"><a id="__codelineno-0-380" name="__codelineno-0-380"></a> <span class="n">all_tracks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">video</span><span class="p">,</span> <span class="n">warn_only</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-0-381"><a id="__codelineno-0-381" name="__codelineno-0-381"></a>
</span><span id="__span-0-382"><a id="__codelineno-0-382" name="__codelineno-0-382"></a> <span class="k">try</span><span class="p">:</span>
</span><span id="__span-0-383"><a id="__codelineno-0-383" name="__codelineno-0-383"></a> <span class="n">dv_tracks</span> <span class="o">=</span> <span class="n">fetch_fn</span><span class="p">(</span><span class="n">title</span><span class="p">,</span> <span class="n">codec</span><span class="o">=</span><span class="n">codec_val</span><span class="p">,</span> <span class="n">range_</span><span class="o">=</span><span class="n">Video</span><span class="o">.</span><span class="n">Range</span><span class="o">.</span><span class="n">DV</span><span class="p">)</span>
</span><span id="__span-0-384"><a id="__codelineno-0-384" name="__codelineno-0-384"></a> <span class="k">for</span> <span class="n">video</span> <span class="ow">in</span> <span class="n">dv_tracks</span><span class="o">.</span><span class="n">videos</span><span class="p">:</span>
</span><span id="__span-0-385"><a id="__codelineno-0-385" name="__codelineno-0-385"></a> <span class="n">all_tracks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">video</span><span class="p">,</span> <span class="n">warn_only</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-0-386"><a id="__codelineno-0-386" name="__codelineno-0-386"></a> <span class="k">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">SystemExit</span><span class="p">):</span>
</span><span id="__span-0-387"><a id="__codelineno-0-387" name="__codelineno-0-387"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">" - No DolbyVision manifest available for HYBRID"</span><span class="p">)</span>
</span><span id="__span-0-388"><a id="__codelineno-0-388" name="__codelineno-0-388"></a> <span class="k">else</span><span class="p">:</span>
</span><span id="__span-0-389"><a id="__codelineno-0-389" name="__codelineno-0-389"></a> <span class="k">for</span> <span class="n">codec_val</span> <span class="ow">in</span> <span class="n">codecs</span><span class="p">:</span>
</span><span id="__span-0-390"><a id="__codelineno-0-390" name="__codelineno-0-390"></a> <span class="k">try</span><span class="p">:</span>
</span><span id="__span-0-391"><a id="__codelineno-0-391" name="__codelineno-0-391"></a> <span class="n">tracks</span> <span class="o">=</span> <span class="n">fetch_fn</span><span class="p">(</span><span class="n">title</span><span class="p">,</span> <span class="n">codec</span><span class="o">=</span><span class="n">codec_val</span><span class="p">,</span> <span class="n">range_</span><span class="o">=</span><span class="n">range_val</span><span class="p">)</span>
</span><span id="__span-0-392"><a id="__codelineno-0-392" name="__codelineno-0-392"></a> <span class="k">except</span> <span class="p">(</span><span class="ne">ValueError</span><span class="p">,</span> <span class="ne">SystemExit</span><span class="p">)</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
</span><span id="__span-0-393"><a id="__codelineno-0-393" name="__codelineno-0-393"></a> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">track_request</span><span class="o">.</span><span class="n">best_available</span><span class="p">:</span>
</span><span id="__span-0-394"><a id="__codelineno-0-394" name="__codelineno-0-394"></a> <span class="n">codec_name</span> <span class="o">=</span> <span class="n">codec_val</span><span class="o">.</span><span class="n">name</span> <span class="k">if</span> <span class="n">codec_val</span> <span class="k">else</span> <span class="s2">"default"</span>
</span><span id="__span-0-395"><a id="__codelineno-0-395" name="__codelineno-0-395"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">warning</span><span class="p">(</span><span class="sa">f</span><span class="s2">" - </span><span class="si">{</span><span class="n">range_val</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">/</span><span class="si">{</span><span class="n">codec_name</span><span class="si">}</span><span class="s2"> not available, skipping (</span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s2">)"</span><span class="p">)</span>
</span><span id="__span-0-396"><a id="__codelineno-0-396" name="__codelineno-0-396"></a> <span class="k">continue</span>
</span><span id="__span-0-397"><a id="__codelineno-0-397" name="__codelineno-0-397"></a> <span class="k">raise</span>
</span><span id="__span-0-398"><a id="__codelineno-0-398" name="__codelineno-0-398"></a> <span class="k">if</span> <span class="n">first</span><span class="p">:</span>
</span><span id="__span-0-399"><a id="__codelineno-0-399" name="__codelineno-0-399"></a> <span class="n">all_tracks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">tracks</span><span class="p">,</span> <span class="n">warn_only</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-0-400"><a id="__codelineno-0-400" name="__codelineno-0-400"></a> <span class="k">if</span> <span class="n">tracks</span><span class="o">.</span><span class="n">manifest_url</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">all_tracks</span><span class="o">.</span><span class="n">manifest_url</span><span class="p">:</span>
</span><span id="__span-0-401"><a id="__codelineno-0-401" name="__codelineno-0-401"></a> <span class="n">all_tracks</span><span class="o">.</span><span class="n">manifest_url</span> <span class="o">=</span> <span class="n">tracks</span><span class="o">.</span><span class="n">manifest_url</span>
</span><span id="__span-0-402"><a id="__codelineno-0-402" name="__codelineno-0-402"></a> <span class="n">first</span> <span class="o">=</span> <span class="kc">False</span>
</span><span id="__span-0-403"><a id="__codelineno-0-403" name="__codelineno-0-403"></a> <span class="k">else</span><span class="p">:</span>
</span><span id="__span-0-404"><a id="__codelineno-0-404" name="__codelineno-0-404"></a> <span class="k">for</span> <span class="n">video</span> <span class="ow">in</span> <span class="n">tracks</span><span class="o">.</span><span class="n">videos</span><span class="p">:</span>
</span><span id="__span-0-405"><a id="__codelineno-0-405" name="__codelineno-0-405"></a> <span class="n">all_tracks</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">video</span><span class="p">,</span> <span class="n">warn_only</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-0-406"><a id="__codelineno-0-406" name="__codelineno-0-406"></a>
</span><span id="__span-0-407"><a id="__codelineno-0-407" name="__codelineno-0-407"></a> <span class="k">return</span> <span class="n">all_tracks</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.get_session" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">get_session</span>
<span class="doc doc-labels">
<small class="doc doc-label doc-label-staticmethod"><code>staticmethod</code></small>
</span>
<a href="#unshackle.core.service.Service.get_session" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">get_session</span><span class="p">()</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Creates a Python-requests HTTP session, adds common headers
from config, cookies, retry handler, and a proxy if available.
:returns: Prepared Python-requests HTTP session</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-412">412</a></span>
<span class="normal"><a href="#__codelineno-0-413">413</a></span>
<span class="normal"><a href="#__codelineno-0-414">414</a></span>
<span class="normal"><a href="#__codelineno-0-415">415</a></span>
<span class="normal"><a href="#__codelineno-0-416">416</a></span>
<span class="normal"><a href="#__codelineno-0-417">417</a></span>
<span class="normal"><a href="#__codelineno-0-418">418</a></span>
<span class="normal"><a href="#__codelineno-0-419">419</a></span>
<span class="normal"><a href="#__codelineno-0-420">420</a></span>
<span class="normal"><a href="#__codelineno-0-421">421</a></span>
<span class="normal"><a href="#__codelineno-0-422">422</a></span>
<span class="normal"><a href="#__codelineno-0-423">423</a></span>
<span class="normal"><a href="#__codelineno-0-424">424</a></span>
<span class="normal"><a href="#__codelineno-0-425">425</a></span>
<span class="normal"><a href="#__codelineno-0-426">426</a></span>
<span class="normal"><a href="#__codelineno-0-427">427</a></span>
<span class="normal"><a href="#__codelineno-0-428">428</a></span>
<span class="normal"><a href="#__codelineno-0-429">429</a></span>
<span class="normal"><a href="#__codelineno-0-430">430</a></span>
<span class="normal"><a href="#__codelineno-0-431">431</a></span>
<span class="normal"><a href="#__codelineno-0-432">432</a></span>
<span class="normal"><a href="#__codelineno-0-433">433</a></span>
<span class="normal"><a href="#__codelineno-0-434">434</a></span>
<span class="normal"><a href="#__codelineno-0-435">435</a></span>
<span class="normal"><a href="#__codelineno-0-436">436</a></span>
<span class="normal"><a href="#__codelineno-0-437">437</a></span>
<span class="normal"><a href="#__codelineno-0-438">438</a></span>
<span class="normal"><a href="#__codelineno-0-439">439</a></span>
<span class="normal"><a href="#__codelineno-0-440">440</a></span>
<span class="normal"><a href="#__codelineno-0-441">441</a></span>
<span class="normal"><a href="#__codelineno-0-442">442</a></span>
<span class="normal"><a href="#__codelineno-0-443">443</a></span>
<span class="normal"><a href="#__codelineno-0-444">444</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-412"><a id="__codelineno-0-412" name="__codelineno-0-412"></a><span class="nd">@staticmethod</span>
</span><span id="__span-0-413"><a id="__codelineno-0-413" name="__codelineno-0-413"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_session</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">requests</span><span class="o">.</span><span class="n">Session</span><span class="p">:</span>
</span><span id="__span-0-414"><a id="__codelineno-0-414" name="__codelineno-0-414"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-415"><a id="__codelineno-0-415" name="__codelineno-0-415"></a><span class="sd"> Creates a Python-requests HTTP session, adds common headers</span>
</span><span id="__span-0-416"><a id="__codelineno-0-416" name="__codelineno-0-416"></a><span class="sd"> from config, cookies, retry handler, and a proxy if available.</span>
</span><span id="__span-0-417"><a id="__codelineno-0-417" name="__codelineno-0-417"></a><span class="sd"> :returns: Prepared Python-requests HTTP session</span>
</span><span id="__span-0-418"><a id="__codelineno-0-418" name="__codelineno-0-418"></a><span class="sd"> """</span>
</span><span id="__span-0-419"><a id="__codelineno-0-419" name="__codelineno-0-419"></a> <span class="n">session</span> <span class="o">=</span> <span class="n">TimeoutSession</span><span class="p">()</span>
</span><span id="__span-0-420"><a id="__codelineno-0-420" name="__codelineno-0-420"></a> <span class="n">session</span><span class="o">.</span><span class="n">headers</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">config</span><span class="o">.</span><span class="n">headers</span><span class="p">)</span>
</span><span id="__span-0-421"><a id="__codelineno-0-421" name="__codelineno-0-421"></a> <span class="c1"># Retry / pool policy mirrors RnetSession via the shared constants in session.py:</span>
</span><span id="__span-0-422"><a id="__codelineno-0-422" name="__codelineno-0-422"></a> <span class="c1"># same total, forcelist, backoff cap, allowed_methods (incl. POST, so license</span>
</span><span id="__span-0-423"><a id="__codelineno-0-423" name="__codelineno-0-423"></a> <span class="c1"># requests retry on both paths), and pool size. Accepted divergence: urllib3's</span>
</span><span id="__span-0-424"><a id="__codelineno-0-424" name="__codelineno-0-424"></a> <span class="c1"># backoff_jitter adds an absolute 0..N seconds whereas rnet jitters ±10% of the</span>
</span><span id="__span-0-425"><a id="__codelineno-0-425" name="__codelineno-0-425"></a> <span class="c1"># backoff, the only intentional difference, not worth hand-rolling a retry loop.</span>
</span><span id="__span-0-426"><a id="__codelineno-0-426" name="__codelineno-0-426"></a> <span class="n">session</span><span class="o">.</span><span class="n">mount</span><span class="p">(</span>
</span><span id="__span-0-427"><a id="__codelineno-0-427" name="__codelineno-0-427"></a> <span class="s2">"https://"</span><span class="p">,</span>
</span><span id="__span-0-428"><a id="__codelineno-0-428" name="__codelineno-0-428"></a> <span class="n">TimeoutHTTPAdapter</span><span class="p">(</span>
</span><span id="__span-0-429"><a id="__codelineno-0-429" name="__codelineno-0-429"></a> <span class="n">max_retries</span><span class="o">=</span><span class="n">Retry</span><span class="p">(</span>
</span><span id="__span-0-430"><a id="__codelineno-0-430" name="__codelineno-0-430"></a> <span class="n">total</span><span class="o">=</span><span class="n">MAX_RETRIES</span><span class="p">,</span>
</span><span id="__span-0-431"><a id="__codelineno-0-431" name="__codelineno-0-431"></a> <span class="n">backoff_factor</span><span class="o">=</span><span class="n">BACKOFF_FACTOR</span><span class="p">,</span>
</span><span id="__span-0-432"><a id="__codelineno-0-432" name="__codelineno-0-432"></a> <span class="n">backoff_max</span><span class="o">=</span><span class="n">MAX_BACKOFF</span><span class="p">,</span>
</span><span id="__span-0-433"><a id="__codelineno-0-433" name="__codelineno-0-433"></a> <span class="n">backoff_jitter</span><span class="o">=</span><span class="mf">0.2</span><span class="p">,</span>
</span><span id="__span-0-434"><a id="__codelineno-0-434" name="__codelineno-0-434"></a> <span class="n">status_forcelist</span><span class="o">=</span><span class="n">STATUS_FORCELIST</span><span class="p">,</span>
</span><span id="__span-0-435"><a id="__codelineno-0-435" name="__codelineno-0-435"></a> <span class="n">allowed_methods</span><span class="o">=</span><span class="n">RETRY_METHODS</span><span class="p">,</span>
</span><span id="__span-0-436"><a id="__codelineno-0-436" name="__codelineno-0-436"></a> <span class="n">respect_retry_after_header</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
</span><span id="__span-0-437"><a id="__codelineno-0-437" name="__codelineno-0-437"></a> <span class="p">),</span>
</span><span id="__span-0-438"><a id="__codelineno-0-438" name="__codelineno-0-438"></a> <span class="n">pool_connections</span><span class="o">=</span><span class="n">POOL_MAX_SIZE</span><span class="p">,</span>
</span><span id="__span-0-439"><a id="__codelineno-0-439" name="__codelineno-0-439"></a> <span class="n">pool_maxsize</span><span class="o">=</span><span class="n">POOL_MAX_SIZE</span><span class="p">,</span>
</span><span id="__span-0-440"><a id="__codelineno-0-440" name="__codelineno-0-440"></a> <span class="n">pool_block</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
</span><span id="__span-0-441"><a id="__codelineno-0-441" name="__codelineno-0-441"></a> <span class="p">),</span>
</span><span id="__span-0-442"><a id="__codelineno-0-442" name="__codelineno-0-442"></a> <span class="p">)</span>
</span><span id="__span-0-443"><a id="__codelineno-0-443" name="__codelineno-0-443"></a> <span class="n">session</span><span class="o">.</span><span class="n">mount</span><span class="p">(</span><span class="s2">"http://"</span><span class="p">,</span> <span class="n">session</span><span class="o">.</span><span class="n">adapters</span><span class="p">[</span><span class="s2">"https://"</span><span class="p">])</span>
</span><span id="__span-0-444"><a id="__codelineno-0-444" name="__codelineno-0-444"></a> <span class="k">return</span> <span class="n">session</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.get_binaries" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">get_binaries</span>
<span class="doc doc-labels">
<small class="doc doc-label doc-label-staticmethod"><code>staticmethod</code></small>
</span>
<a href="#unshackle.core.service.Service.get_binaries" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">get_binaries</span><span class="p">()</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Declare custom binary dependencies required by this service.
:returns: List of dicts, each with a <code>name</code> and optional <code>candidates</code> and <code>desc</code>.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-446">446</a></span>
<span class="normal"><a href="#__codelineno-0-447">447</a></span>
<span class="normal"><a href="#__codelineno-0-448">448</a></span>
<span class="normal"><a href="#__codelineno-0-449">449</a></span>
<span class="normal"><a href="#__codelineno-0-450">450</a></span>
<span class="normal"><a href="#__codelineno-0-451">451</a></span>
<span class="normal"><a href="#__codelineno-0-452">452</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-446"><a id="__codelineno-0-446" name="__codelineno-0-446"></a><span class="nd">@staticmethod</span>
</span><span id="__span-0-447"><a id="__codelineno-0-447" name="__codelineno-0-447"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_binaries</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">[</span><span class="nb">dict</span><span class="p">]:</span>
</span><span id="__span-0-448"><a id="__codelineno-0-448" name="__codelineno-0-448"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-449"><a id="__codelineno-0-449" name="__codelineno-0-449"></a><span class="sd"> Declare custom binary dependencies required by this service.</span>
</span><span id="__span-0-450"><a id="__codelineno-0-450" name="__codelineno-0-450"></a><span class="sd"> :returns: List of dicts, each with a ``name`` and optional ``candidates`` and ``desc``.</span>
</span><span id="__span-0-451"><a id="__codelineno-0-451" name="__codelineno-0-451"></a><span class="sd"> """</span>
</span><span id="__span-0-452"><a id="__codelineno-0-452" name="__codelineno-0-452"></a> <span class="k">return</span> <span class="p">[]</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.authenticate" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">authenticate</span>
<a href="#unshackle.core.service.Service.authenticate" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">authenticate</span><span class="p">(</span><span class="n">cookies</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">credential</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Authenticate the Service with Cookies and/or Credentials (Email/Username and Password).</p>
<p>This is effectively a login() function. Any API calls or object initializations
needing to be made, should be made here. unshackle operates this method before
any of the following abstract functions. The one exception is a search on a
Service that sets <code>ANONYMOUS_SEARCH</code>, which does not operate this method.</p>
<p>You should avoid storing or using the Credential outside this function.
Make any calls you need for any Cookies, Tokens, or such, then use those.</p>
<p>Do not store the cookies outside this function either. However, you can load
the cookies into the service HTTP session.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-454">454</a></span>
<span class="normal"><a href="#__codelineno-0-455">455</a></span>
<span class="normal"><a href="#__codelineno-0-456">456</a></span>
<span class="normal"><a href="#__codelineno-0-457">457</a></span>
<span class="normal"><a href="#__codelineno-0-458">458</a></span>
<span class="normal"><a href="#__codelineno-0-459">459</a></span>
<span class="normal"><a href="#__codelineno-0-460">460</a></span>
<span class="normal"><a href="#__codelineno-0-461">461</a></span>
<span class="normal"><a href="#__codelineno-0-462">462</a></span>
<span class="normal"><a href="#__codelineno-0-463">463</a></span>
<span class="normal"><a href="#__codelineno-0-464">464</a></span>
<span class="normal"><a href="#__codelineno-0-465">465</a></span>
<span class="normal"><a href="#__codelineno-0-466">466</a></span>
<span class="normal"><a href="#__codelineno-0-467">467</a></span>
<span class="normal"><a href="#__codelineno-0-468">468</a></span>
<span class="normal"><a href="#__codelineno-0-469">469</a></span>
<span class="normal"><a href="#__codelineno-0-470">470</a></span>
<span class="normal"><a href="#__codelineno-0-471">471</a></span>
<span class="normal"><a href="#__codelineno-0-472">472</a></span>
<span class="normal"><a href="#__codelineno-0-473">473</a></span>
<span class="normal"><a href="#__codelineno-0-474">474</a></span>
<span class="normal"><a href="#__codelineno-0-475">475</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-454"><a id="__codelineno-0-454" name="__codelineno-0-454"></a><span class="k">def</span><span class="w"> </span><span class="nf">authenticate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cookies</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">CookieJar</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="n">credential</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Credential</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="__span-0-455"><a id="__codelineno-0-455" name="__codelineno-0-455"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-456"><a id="__codelineno-0-456" name="__codelineno-0-456"></a><span class="sd"> Authenticate the Service with Cookies and/or Credentials (Email/Username and Password).</span>
</span><span id="__span-0-457"><a id="__codelineno-0-457" name="__codelineno-0-457"></a>
</span><span id="__span-0-458"><a id="__codelineno-0-458" name="__codelineno-0-458"></a><span class="sd"> This is effectively a login() function. Any API calls or object initializations</span>
</span><span id="__span-0-459"><a id="__codelineno-0-459" name="__codelineno-0-459"></a><span class="sd"> needing to be made, should be made here. unshackle operates this method before</span>
</span><span id="__span-0-460"><a id="__codelineno-0-460" name="__codelineno-0-460"></a><span class="sd"> any of the following abstract functions. The one exception is a search on a</span>
</span><span id="__span-0-461"><a id="__codelineno-0-461" name="__codelineno-0-461"></a><span class="sd"> Service that sets ``ANONYMOUS_SEARCH``, which does not operate this method.</span>
</span><span id="__span-0-462"><a id="__codelineno-0-462" name="__codelineno-0-462"></a>
</span><span id="__span-0-463"><a id="__codelineno-0-463" name="__codelineno-0-463"></a><span class="sd"> You should avoid storing or using the Credential outside this function.</span>
</span><span id="__span-0-464"><a id="__codelineno-0-464" name="__codelineno-0-464"></a><span class="sd"> Make any calls you need for any Cookies, Tokens, or such, then use those.</span>
</span><span id="__span-0-465"><a id="__codelineno-0-465" name="__codelineno-0-465"></a>
</span><span id="__span-0-466"><a id="__codelineno-0-466" name="__codelineno-0-466"></a><span class="sd"> Do not store the cookies outside this function either. However, you can load</span>
</span><span id="__span-0-467"><a id="__codelineno-0-467" name="__codelineno-0-467"></a><span class="sd"> the cookies into the service HTTP session.</span>
</span><span id="__span-0-468"><a id="__codelineno-0-468" name="__codelineno-0-468"></a><span class="sd"> """</span>
</span><span id="__span-0-469"><a id="__codelineno-0-469" name="__codelineno-0-469"></a> <span class="k">if</span> <span class="n">cookies</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="__span-0-470"><a id="__codelineno-0-470" name="__codelineno-0-470"></a> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">cookies</span><span class="p">,</span> <span class="n">CookieJar</span><span class="p">):</span>
</span><span id="__span-0-471"><a id="__codelineno-0-471" name="__codelineno-0-471"></a> <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Expected cookies to be a </span><span class="si">{</span><span class="n">CookieJar</span><span class="si">}</span><span class="s2">, not </span><span class="si">{</span><span class="n">cookies</span><span class="si">!r}</span><span class="s2">."</span><span class="p">)</span>
</span><span id="__span-0-472"><a id="__codelineno-0-472" name="__codelineno-0-472"></a> <span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="o">.</span><span class="n">cookies</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">cookies</span><span class="p">)</span>
</span><span id="__span-0-473"><a id="__codelineno-0-473" name="__codelineno-0-473"></a>
</span><span id="__span-0-474"><a id="__codelineno-0-474" name="__codelineno-0-474"></a> <span class="c1"># Store credential for cache key generation</span>
</span><span id="__span-0-475"><a id="__codelineno-0-475" name="__codelineno-0-475"></a> <span class="bp">self</span><span class="o">.</span><span class="n">credential</span> <span class="o">=</span> <span class="n">credential</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.request_input" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">request_input</span>
<a href="#unshackle.core.service.Service.request_input" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">request_input</span><span class="p">(</span><span class="n">prompt</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Request interactive input from the user.</p>
<p>Locally, prompts through the shared rich console so the prompt renders alongside
Live progress. A remote-dl session relays it through its :class:<code>InputBridge</code>, and a
REST download job relays it through <code>prompt_user</code> to the job's <code>input_prompt</code>.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-477">477</a></span>
<span class="normal"><a href="#__codelineno-0-478">478</a></span>
<span class="normal"><a href="#__codelineno-0-479">479</a></span>
<span class="normal"><a href="#__codelineno-0-480">480</a></span>
<span class="normal"><a href="#__codelineno-0-481">481</a></span>
<span class="normal"><a href="#__codelineno-0-482">482</a></span>
<span class="normal"><a href="#__codelineno-0-483">483</a></span>
<span class="normal"><a href="#__codelineno-0-484">484</a></span>
<span class="normal"><a href="#__codelineno-0-485">485</a></span>
<span class="normal"><a href="#__codelineno-0-486">486</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-477"><a id="__codelineno-0-477" name="__codelineno-0-477"></a><span class="k">def</span><span class="w"> </span><span class="nf">request_input</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">prompt</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span><span id="__span-0-478"><a id="__codelineno-0-478" name="__codelineno-0-478"></a><span class="w"> </span><span class="sd">"""Request interactive input from the user.</span>
</span><span id="__span-0-479"><a id="__codelineno-0-479" name="__codelineno-0-479"></a>
</span><span id="__span-0-480"><a id="__codelineno-0-480" name="__codelineno-0-480"></a><span class="sd"> Locally, prompts through the shared rich console so the prompt renders alongside</span>
</span><span id="__span-0-481"><a id="__codelineno-0-481" name="__codelineno-0-481"></a><span class="sd"> Live progress. A remote-dl session relays it through its :class:`InputBridge`, and a</span>
</span><span id="__span-0-482"><a id="__codelineno-0-482" name="__codelineno-0-482"></a><span class="sd"> REST download job relays it through ``prompt_user`` to the job's ``input_prompt``.</span>
</span><span id="__span-0-483"><a id="__codelineno-0-483" name="__codelineno-0-483"></a><span class="sd"> """</span>
</span><span id="__span-0-484"><a id="__codelineno-0-484" name="__codelineno-0-484"></a> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_input_bridge</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="__span-0-485"><a id="__codelineno-0-485" name="__codelineno-0-485"></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_input_bridge</span><span class="o">.</span><span class="n">request_input</span><span class="p">(</span><span class="n">prompt</span><span class="p">)</span>
</span><span id="__span-0-486"><a id="__codelineno-0-486" name="__codelineno-0-486"></a> <span class="k">return</span> <span class="n">prompt_user</span><span class="p">(</span><span class="n">prompt</span><span class="p">)</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.wait_for_approval" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">wait_for_approval</span>
<a href="#unshackle.core.service.Service.wait_for_approval" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">wait_for_approval</span><span class="p">(</span><span class="n">message</span><span class="p">,</span> <span class="n">check</span><span class="p">,</span> <span class="n">timeout</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mf">3.0</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Show <code>message</code>, then call <code>check</code> until it returns a value.</p>
<p>Use it for a login that the user approves on another device, such as a pair code.
<code>check</code> returns None while the approval is pending, and must return within a few
seconds. Raises TimeoutError after <code>timeout</code> seconds, and RuntimeError when the
remote session no longer exists. A REST download job shows <code>message</code> as its <code>notice</code>.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-488">488</a></span>
<span class="normal"><a href="#__codelineno-0-489">489</a></span>
<span class="normal"><a href="#__codelineno-0-490">490</a></span>
<span class="normal"><a href="#__codelineno-0-491">491</a></span>
<span class="normal"><a href="#__codelineno-0-492">492</a></span>
<span class="normal"><a href="#__codelineno-0-493">493</a></span>
<span class="normal"><a href="#__codelineno-0-494">494</a></span>
<span class="normal"><a href="#__codelineno-0-495">495</a></span>
<span class="normal"><a href="#__codelineno-0-496">496</a></span>
<span class="normal"><a href="#__codelineno-0-497">497</a></span>
<span class="normal"><a href="#__codelineno-0-498">498</a></span>
<span class="normal"><a href="#__codelineno-0-499">499</a></span>
<span class="normal"><a href="#__codelineno-0-500">500</a></span>
<span class="normal"><a href="#__codelineno-0-501">501</a></span>
<span class="normal"><a href="#__codelineno-0-502">502</a></span>
<span class="normal"><a href="#__codelineno-0-503">503</a></span>
<span class="normal"><a href="#__codelineno-0-504">504</a></span>
<span class="normal"><a href="#__codelineno-0-505">505</a></span>
<span class="normal"><a href="#__codelineno-0-506">506</a></span>
<span class="normal"><a href="#__codelineno-0-507">507</a></span>
<span class="normal"><a href="#__codelineno-0-508">508</a></span>
<span class="normal"><a href="#__codelineno-0-509">509</a></span>
<span class="normal"><a href="#__codelineno-0-510">510</a></span>
<span class="normal"><a href="#__codelineno-0-511">511</a></span>
<span class="normal"><a href="#__codelineno-0-512">512</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-488"><a id="__codelineno-0-488" name="__codelineno-0-488"></a><span class="k">def</span><span class="w"> </span><span class="nf">wait_for_approval</span><span class="p">(</span>
</span><span id="__span-0-489"><a id="__codelineno-0-489" name="__codelineno-0-489"></a> <span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">check</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[[],</span> <span class="n">Optional</span><span class="p">[</span><span class="n">T</span><span class="p">]],</span> <span class="n">timeout</span><span class="p">:</span> <span class="nb">float</span><span class="p">,</span> <span class="n">interval</span><span class="p">:</span> <span class="nb">float</span> <span class="o">=</span> <span class="mf">3.0</span>
</span><span id="__span-0-490"><a id="__codelineno-0-490" name="__codelineno-0-490"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">T</span><span class="p">:</span>
</span><span id="__span-0-491"><a id="__codelineno-0-491" name="__codelineno-0-491"></a><span class="w"> </span><span class="sd">"""Show ``message``, then call ``check`` until it returns a value.</span>
</span><span id="__span-0-492"><a id="__codelineno-0-492" name="__codelineno-0-492"></a>
</span><span id="__span-0-493"><a id="__codelineno-0-493" name="__codelineno-0-493"></a><span class="sd"> Use it for a login that the user approves on another device, such as a pair code.</span>
</span><span id="__span-0-494"><a id="__codelineno-0-494" name="__codelineno-0-494"></a><span class="sd"> ``check`` returns None while the approval is pending, and must return within a few</span>
</span><span id="__span-0-495"><a id="__codelineno-0-495" name="__codelineno-0-495"></a><span class="sd"> seconds. Raises TimeoutError after ``timeout`` seconds, and RuntimeError when the</span>
</span><span id="__span-0-496"><a id="__codelineno-0-496" name="__codelineno-0-496"></a><span class="sd"> remote session no longer exists. A REST download job shows ``message`` as its ``notice``.</span>
</span><span id="__span-0-497"><a id="__codelineno-0-497" name="__codelineno-0-497"></a><span class="sd"> """</span>
</span><span id="__span-0-498"><a id="__codelineno-0-498" name="__codelineno-0-498"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
</span><span id="__span-0-499"><a id="__codelineno-0-499" name="__codelineno-0-499"></a> <span class="n">show_notice</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
</span><span id="__span-0-500"><a id="__codelineno-0-500" name="__codelineno-0-500"></a> <span class="n">deadline</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">monotonic</span><span class="p">()</span> <span class="o">+</span> <span class="n">timeout</span>
</span><span id="__span-0-501"><a id="__codelineno-0-501" name="__codelineno-0-501"></a> <span class="k">try</span><span class="p">:</span>
</span><span id="__span-0-502"><a id="__codelineno-0-502" name="__codelineno-0-502"></a> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span><span id="__span-0-503"><a id="__codelineno-0-503" name="__codelineno-0-503"></a> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_input_bridge</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="__span-0-504"><a id="__codelineno-0-504" name="__codelineno-0-504"></a> <span class="bp">self</span><span class="o">.</span><span class="n">_input_bridge</span><span class="o">.</span><span class="n">ensure_active</span><span class="p">()</span>
</span><span id="__span-0-505"><a id="__codelineno-0-505" name="__codelineno-0-505"></a> <span class="n">result</span> <span class="o">=</span> <span class="n">check</span><span class="p">()</span>
</span><span id="__span-0-506"><a id="__codelineno-0-506" name="__codelineno-0-506"></a> <span class="k">if</span> <span class="n">result</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="__span-0-507"><a id="__codelineno-0-507" name="__codelineno-0-507"></a> <span class="k">return</span> <span class="n">result</span>
</span><span id="__span-0-508"><a id="__codelineno-0-508" name="__codelineno-0-508"></a> <span class="k">if</span> <span class="n">time</span><span class="o">.</span><span class="n">monotonic</span><span class="p">()</span> <span class="o">+</span> <span class="n">interval</span> <span class="o">&gt;=</span> <span class="n">deadline</span><span class="p">:</span>
</span><span id="__span-0-509"><a id="__codelineno-0-509" name="__codelineno-0-509"></a> <span class="k">raise</span> <span class="ne">TimeoutError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"No approval within </span><span class="si">{</span><span class="n">timeout</span><span class="si">:</span><span class="s2">.0f</span><span class="si">}</span><span class="s2">s"</span><span class="p">)</span>
</span><span id="__span-0-510"><a id="__codelineno-0-510" name="__codelineno-0-510"></a> <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">interval</span><span class="p">)</span>
</span><span id="__span-0-511"><a id="__codelineno-0-511" name="__codelineno-0-511"></a> <span class="k">finally</span><span class="p">:</span>
</span><span id="__span-0-512"><a id="__codelineno-0-512" name="__codelineno-0-512"></a> <span class="n">show_notice</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.search" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">search</span>
<a href="#unshackle.core.service.Service.search" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">search</span><span class="p">()</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Find titles from the Service by query.</p>
<p>The Service class must take the query as a CLI argument.
Ideally re-use the title ID argument (that is, self.title).</p>
<p>unshackle displays the search results in the order yielded.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-514">514</a></span>
<span class="normal"><a href="#__codelineno-0-515">515</a></span>
<span class="normal"><a href="#__codelineno-0-516">516</a></span>
<span class="normal"><a href="#__codelineno-0-517">517</a></span>
<span class="normal"><a href="#__codelineno-0-518">518</a></span>
<span class="normal"><a href="#__codelineno-0-519">519</a></span>
<span class="normal"><a href="#__codelineno-0-520">520</a></span>
<span class="normal"><a href="#__codelineno-0-521">521</a></span>
<span class="normal"><a href="#__codelineno-0-522">522</a></span>
<span class="normal"><a href="#__codelineno-0-523">523</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-514"><a id="__codelineno-0-514" name="__codelineno-0-514"></a><span class="k">def</span><span class="w"> </span><span class="nf">search</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Generator</span><span class="p">[</span><span class="n">SearchResult</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">]:</span>
</span><span id="__span-0-515"><a id="__codelineno-0-515" name="__codelineno-0-515"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-516"><a id="__codelineno-0-516" name="__codelineno-0-516"></a><span class="sd"> Find titles from the Service by query.</span>
</span><span id="__span-0-517"><a id="__codelineno-0-517" name="__codelineno-0-517"></a>
</span><span id="__span-0-518"><a id="__codelineno-0-518" name="__codelineno-0-518"></a><span class="sd"> The Service class must take the query as a CLI argument.</span>
</span><span id="__span-0-519"><a id="__codelineno-0-519" name="__codelineno-0-519"></a><span class="sd"> Ideally re-use the title ID argument (that is, self.title).</span>
</span><span id="__span-0-520"><a id="__codelineno-0-520" name="__codelineno-0-520"></a>
</span><span id="__span-0-521"><a id="__codelineno-0-521" name="__codelineno-0-521"></a><span class="sd"> unshackle displays the search results in the order yielded.</span>
</span><span id="__span-0-522"><a id="__codelineno-0-522" name="__codelineno-0-522"></a><span class="sd"> """</span>
</span><span id="__span-0-523"><a id="__codelineno-0-523" name="__codelineno-0-523"></a> <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Search functionality has not been implemented by </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.get_widevine_service_certificate" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">get_widevine_service_certificate</span>
<a href="#unshackle.core.service.Service.get_widevine_service_certificate" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">get_widevine_service_certificate</span><span class="p">(</span>
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a> <span class="o">*</span><span class="p">,</span> <span class="n">challenge</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">track</span>
</span><span id="__span-0-3"><a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Get the Widevine Service Certificate used for Privacy Mode.</p>
<p>:param challenge: The service challenge, providing this to a License endpoint should return the
privacy certificate that the service uses.
:param title: The current <code>Title</code> from get_titles that unshackle processes now. unshackle
gives this in case it holds data you need, for example for an HTTP request.
:param track: The current <code>Track</code> needing decryption. Provided for same reason as <code>title</code>.
:return: The Service Privacy Certificate as Bytes or a Base64 string. Do not Base64 Encode or
Decode the data, return as is to reduce unnecessary computations.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-525">525</a></span>
<span class="normal"><a href="#__codelineno-0-526">526</a></span>
<span class="normal"><a href="#__codelineno-0-527">527</a></span>
<span class="normal"><a href="#__codelineno-0-528">528</a></span>
<span class="normal"><a href="#__codelineno-0-529">529</a></span>
<span class="normal"><a href="#__codelineno-0-530">530</a></span>
<span class="normal"><a href="#__codelineno-0-531">531</a></span>
<span class="normal"><a href="#__codelineno-0-532">532</a></span>
<span class="normal"><a href="#__codelineno-0-533">533</a></span>
<span class="normal"><a href="#__codelineno-0-534">534</a></span>
<span class="normal"><a href="#__codelineno-0-535">535</a></span>
<span class="normal"><a href="#__codelineno-0-536">536</a></span>
<span class="normal"><a href="#__codelineno-0-537">537</a></span>
<span class="normal"><a href="#__codelineno-0-538">538</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-525"><a id="__codelineno-0-525" name="__codelineno-0-525"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_widevine_service_certificate</span><span class="p">(</span>
</span><span id="__span-0-526"><a id="__codelineno-0-526" name="__codelineno-0-526"></a> <span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">challenge</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">,</span> <span class="n">track</span><span class="p">:</span> <span class="n">AnyTrack</span>
</span><span id="__span-0-527"><a id="__codelineno-0-527" name="__codelineno-0-527"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Union</span><span class="p">[</span><span class="nb">bytes</span><span class="p">,</span> <span class="nb">str</span><span class="p">]:</span>
</span><span id="__span-0-528"><a id="__codelineno-0-528" name="__codelineno-0-528"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-529"><a id="__codelineno-0-529" name="__codelineno-0-529"></a><span class="sd"> Get the Widevine Service Certificate used for Privacy Mode.</span>
</span><span id="__span-0-530"><a id="__codelineno-0-530" name="__codelineno-0-530"></a>
</span><span id="__span-0-531"><a id="__codelineno-0-531" name="__codelineno-0-531"></a><span class="sd"> :param challenge: The service challenge, providing this to a License endpoint should return the</span>
</span><span id="__span-0-532"><a id="__codelineno-0-532" name="__codelineno-0-532"></a><span class="sd"> privacy certificate that the service uses.</span>
</span><span id="__span-0-533"><a id="__codelineno-0-533" name="__codelineno-0-533"></a><span class="sd"> :param title: The current `Title` from get_titles that unshackle processes now. unshackle</span>
</span><span id="__span-0-534"><a id="__codelineno-0-534" name="__codelineno-0-534"></a><span class="sd"> gives this in case it holds data you need, for example for an HTTP request.</span>
</span><span id="__span-0-535"><a id="__codelineno-0-535" name="__codelineno-0-535"></a><span class="sd"> :param track: The current `Track` needing decryption. Provided for same reason as `title`.</span>
</span><span id="__span-0-536"><a id="__codelineno-0-536" name="__codelineno-0-536"></a><span class="sd"> :return: The Service Privacy Certificate as Bytes or a Base64 string. Do not Base64 Encode or</span>
</span><span id="__span-0-537"><a id="__codelineno-0-537" name="__codelineno-0-537"></a><span class="sd"> Decode the data, return as is to reduce unnecessary computations.</span>
</span><span id="__span-0-538"><a id="__codelineno-0-538" name="__codelineno-0-538"></a><span class="sd"> """</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.get_widevine_license" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">get_widevine_license</span>
<a href="#unshackle.core.service.Service.get_widevine_license" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">get_widevine_license</span><span class="p">(</span><span class="o">*</span><span class="p">,</span> <span class="n">challenge</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">track</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Get a Widevine License message by sending a License Request (challenge).</p>
<p>This License message contains the encrypted content keys and will be
read by the Cdm and decrypted.</p>
<p>This is a very important request to get correct. A bad, unexpected, or missing
value in the request can cause the service to detect your CDM device.
The service can then ban, revoke, disable, or downgrade that device.</p>
<p>:param challenge: The license challenge from the Widevine CDM.
:param title: The current <code>Title</code> from get_titles that unshackle processes now. unshackle
gives this in case it holds data you need, for example for an HTTP request.
:param track: The current <code>Track</code> needing decryption. Provided for same reason as <code>title</code>.
:return: The License response as Bytes or a Base64 string. Do not Base64 Encode or
Decode the data, return as is to reduce unnecessary computations.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-540">540</a></span>
<span class="normal"><a href="#__codelineno-0-541">541</a></span>
<span class="normal"><a href="#__codelineno-0-542">542</a></span>
<span class="normal"><a href="#__codelineno-0-543">543</a></span>
<span class="normal"><a href="#__codelineno-0-544">544</a></span>
<span class="normal"><a href="#__codelineno-0-545">545</a></span>
<span class="normal"><a href="#__codelineno-0-546">546</a></span>
<span class="normal"><a href="#__codelineno-0-547">547</a></span>
<span class="normal"><a href="#__codelineno-0-548">548</a></span>
<span class="normal"><a href="#__codelineno-0-549">549</a></span>
<span class="normal"><a href="#__codelineno-0-550">550</a></span>
<span class="normal"><a href="#__codelineno-0-551">551</a></span>
<span class="normal"><a href="#__codelineno-0-552">552</a></span>
<span class="normal"><a href="#__codelineno-0-553">553</a></span>
<span class="normal"><a href="#__codelineno-0-554">554</a></span>
<span class="normal"><a href="#__codelineno-0-555">555</a></span>
<span class="normal"><a href="#__codelineno-0-556">556</a></span>
<span class="normal"><a href="#__codelineno-0-557">557</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-540"><a id="__codelineno-0-540" name="__codelineno-0-540"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_widevine_license</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">challenge</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">,</span> <span class="n">track</span><span class="p">:</span> <span class="n">AnyTrack</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="nb">bytes</span><span class="p">,</span> <span class="nb">str</span><span class="p">]]:</span>
</span><span id="__span-0-541"><a id="__codelineno-0-541" name="__codelineno-0-541"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-542"><a id="__codelineno-0-542" name="__codelineno-0-542"></a><span class="sd"> Get a Widevine License message by sending a License Request (challenge).</span>
</span><span id="__span-0-543"><a id="__codelineno-0-543" name="__codelineno-0-543"></a>
</span><span id="__span-0-544"><a id="__codelineno-0-544" name="__codelineno-0-544"></a><span class="sd"> This License message contains the encrypted content keys and will be</span>
</span><span id="__span-0-545"><a id="__codelineno-0-545" name="__codelineno-0-545"></a><span class="sd"> read by the Cdm and decrypted.</span>
</span><span id="__span-0-546"><a id="__codelineno-0-546" name="__codelineno-0-546"></a>
</span><span id="__span-0-547"><a id="__codelineno-0-547" name="__codelineno-0-547"></a><span class="sd"> This is a very important request to get correct. A bad, unexpected, or missing</span>
</span><span id="__span-0-548"><a id="__codelineno-0-548" name="__codelineno-0-548"></a><span class="sd"> value in the request can cause the service to detect your CDM device.</span>
</span><span id="__span-0-549"><a id="__codelineno-0-549" name="__codelineno-0-549"></a><span class="sd"> The service can then ban, revoke, disable, or downgrade that device.</span>
</span><span id="__span-0-550"><a id="__codelineno-0-550" name="__codelineno-0-550"></a>
</span><span id="__span-0-551"><a id="__codelineno-0-551" name="__codelineno-0-551"></a><span class="sd"> :param challenge: The license challenge from the Widevine CDM.</span>
</span><span id="__span-0-552"><a id="__codelineno-0-552" name="__codelineno-0-552"></a><span class="sd"> :param title: The current `Title` from get_titles that unshackle processes now. unshackle</span>
</span><span id="__span-0-553"><a id="__codelineno-0-553" name="__codelineno-0-553"></a><span class="sd"> gives this in case it holds data you need, for example for an HTTP request.</span>
</span><span id="__span-0-554"><a id="__codelineno-0-554" name="__codelineno-0-554"></a><span class="sd"> :param track: The current `Track` needing decryption. Provided for same reason as `title`.</span>
</span><span id="__span-0-555"><a id="__codelineno-0-555" name="__codelineno-0-555"></a><span class="sd"> :return: The License response as Bytes or a Base64 string. Do not Base64 Encode or</span>
</span><span id="__span-0-556"><a id="__codelineno-0-556" name="__codelineno-0-556"></a><span class="sd"> Decode the data, return as is to reduce unnecessary computations.</span>
</span><span id="__span-0-557"><a id="__codelineno-0-557" name="__codelineno-0-557"></a><span class="sd"> """</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.get_playready_license" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">get_playready_license</span>
<a href="#unshackle.core.service.Service.get_playready_license" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">get_playready_license</span><span class="p">(</span><span class="o">*</span><span class="p">,</span> <span class="n">challenge</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">track</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Get a PlayReady License message by sending a License Request (challenge).</p>
<p>This License message contains the encrypted content keys and will be
read by the CDM and decrypted.</p>
<p>This is a very important request to get correct. A bad, unexpected, or missing
value in the request can cause the service to detect your CDM device.
The service can then ban, revoke, disable, or downgrade that device.</p>
<p>:param challenge: The license challenge from the PlayReady CDM.
:param title: The current <code>Title</code> from get_titles that unshackle processes now. unshackle
gives this in case it holds data you need, for example for an HTTP request.
:param track: The current <code>Track</code> needing decryption. Provided for same reason as <code>title</code>.
:return: The License response as Bytes or a Base64 string. Do not Base64 Encode or
Decode the data, return as is to reduce unnecessary computations.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-559">559</a></span>
<span class="normal"><a href="#__codelineno-0-560">560</a></span>
<span class="normal"><a href="#__codelineno-0-561">561</a></span>
<span class="normal"><a href="#__codelineno-0-562">562</a></span>
<span class="normal"><a href="#__codelineno-0-563">563</a></span>
<span class="normal"><a href="#__codelineno-0-564">564</a></span>
<span class="normal"><a href="#__codelineno-0-565">565</a></span>
<span class="normal"><a href="#__codelineno-0-566">566</a></span>
<span class="normal"><a href="#__codelineno-0-567">567</a></span>
<span class="normal"><a href="#__codelineno-0-568">568</a></span>
<span class="normal"><a href="#__codelineno-0-569">569</a></span>
<span class="normal"><a href="#__codelineno-0-570">570</a></span>
<span class="normal"><a href="#__codelineno-0-571">571</a></span>
<span class="normal"><a href="#__codelineno-0-572">572</a></span>
<span class="normal"><a href="#__codelineno-0-573">573</a></span>
<span class="normal"><a href="#__codelineno-0-574">574</a></span>
<span class="normal"><a href="#__codelineno-0-575">575</a></span>
<span class="normal"><a href="#__codelineno-0-576">576</a></span>
<span class="normal"><a href="#__codelineno-0-577">577</a></span>
<span class="normal"><a href="#__codelineno-0-578">578</a></span>
<span class="normal"><a href="#__codelineno-0-579">579</a></span>
<span class="normal"><a href="#__codelineno-0-580">580</a></span>
<span class="normal"><a href="#__codelineno-0-581">581</a></span>
<span class="normal"><a href="#__codelineno-0-582">582</a></span>
<span class="normal"><a href="#__codelineno-0-583">583</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-559"><a id="__codelineno-0-559" name="__codelineno-0-559"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_playready_license</span><span class="p">(</span>
</span><span id="__span-0-560"><a id="__codelineno-0-560" name="__codelineno-0-560"></a> <span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">challenge</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">,</span> <span class="n">track</span><span class="p">:</span> <span class="n">AnyTrack</span>
</span><span id="__span-0-561"><a id="__codelineno-0-561" name="__codelineno-0-561"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="nb">bytes</span><span class="p">,</span> <span class="nb">str</span><span class="p">]]:</span>
</span><span id="__span-0-562"><a id="__codelineno-0-562" name="__codelineno-0-562"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-563"><a id="__codelineno-0-563" name="__codelineno-0-563"></a><span class="sd"> Get a PlayReady License message by sending a License Request (challenge).</span>
</span><span id="__span-0-564"><a id="__codelineno-0-564" name="__codelineno-0-564"></a>
</span><span id="__span-0-565"><a id="__codelineno-0-565" name="__codelineno-0-565"></a><span class="sd"> This License message contains the encrypted content keys and will be</span>
</span><span id="__span-0-566"><a id="__codelineno-0-566" name="__codelineno-0-566"></a><span class="sd"> read by the CDM and decrypted.</span>
</span><span id="__span-0-567"><a id="__codelineno-0-567" name="__codelineno-0-567"></a>
</span><span id="__span-0-568"><a id="__codelineno-0-568" name="__codelineno-0-568"></a><span class="sd"> This is a very important request to get correct. A bad, unexpected, or missing</span>
</span><span id="__span-0-569"><a id="__codelineno-0-569" name="__codelineno-0-569"></a><span class="sd"> value in the request can cause the service to detect your CDM device.</span>
</span><span id="__span-0-570"><a id="__codelineno-0-570" name="__codelineno-0-570"></a><span class="sd"> The service can then ban, revoke, disable, or downgrade that device.</span>
</span><span id="__span-0-571"><a id="__codelineno-0-571" name="__codelineno-0-571"></a>
</span><span id="__span-0-572"><a id="__codelineno-0-572" name="__codelineno-0-572"></a><span class="sd"> :param challenge: The license challenge from the PlayReady CDM.</span>
</span><span id="__span-0-573"><a id="__codelineno-0-573" name="__codelineno-0-573"></a><span class="sd"> :param title: The current `Title` from get_titles that unshackle processes now. unshackle</span>
</span><span id="__span-0-574"><a id="__codelineno-0-574" name="__codelineno-0-574"></a><span class="sd"> gives this in case it holds data you need, for example for an HTTP request.</span>
</span><span id="__span-0-575"><a id="__codelineno-0-575" name="__codelineno-0-575"></a><span class="sd"> :param track: The current `Track` needing decryption. Provided for same reason as `title`.</span>
</span><span id="__span-0-576"><a id="__codelineno-0-576" name="__codelineno-0-576"></a><span class="sd"> :return: The License response as Bytes or a Base64 string. Do not Base64 Encode or</span>
</span><span id="__span-0-577"><a id="__codelineno-0-577" name="__codelineno-0-577"></a><span class="sd"> Decode the data, return as is to reduce unnecessary computations.</span>
</span><span id="__span-0-578"><a id="__codelineno-0-578" name="__codelineno-0-578"></a><span class="sd"> """</span>
</span><span id="__span-0-579"><a id="__codelineno-0-579" name="__codelineno-0-579"></a> <span class="c1"># A service that implements Widevine licensing only still gets PlayReady, with the</span>
</span><span id="__span-0-580"><a id="__codelineno-0-580" name="__codelineno-0-580"></a> <span class="c1"># arguments its own signature declares.</span>
</span><span id="__span-0-581"><a id="__codelineno-0-581" name="__codelineno-0-581"></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_widevine_license</span><span class="p">(</span>
</span><span id="__span-0-582"><a id="__codelineno-0-582" name="__codelineno-0-582"></a> <span class="o">**</span><span class="n">declared_kwargs</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">get_widevine_license</span><span class="p">,</span> <span class="p">{</span><span class="s2">"challenge"</span><span class="p">:</span> <span class="n">challenge</span><span class="p">,</span> <span class="s2">"title"</span><span class="p">:</span> <span class="n">title</span><span class="p">,</span> <span class="s2">"track"</span><span class="p">:</span> <span class="n">track</span><span class="p">})</span>
</span><span id="__span-0-583"><a id="__codelineno-0-583" name="__codelineno-0-583"></a> <span class="p">)</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.get_clearkey_license" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">get_clearkey_license</span>
<a href="#unshackle.core.service.Service.get_clearkey_license" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">get_clearkey_license</span><span class="p">(</span><span class="o">*</span><span class="p">,</span> <span class="n">challenge</span><span class="p">,</span> <span class="n">title</span><span class="p">,</span> <span class="n">track</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Get a W3C ClearKey License (JWK Set) by sending a License Request (challenge).</p>
<p>Used for DASH <code>org.w3.clearkey</code> tracks. unshackle uses no CDM here: the challenge is
the W3C EME JSON license request, e.g. <code>{"kids": ["&lt;base64url&gt;"], "type": "temporary"}</code>,
and the license is a JWK Set, e.g. <code>{"keys": [{"kty": "oct", "k": "...", "kid": "..."}]}</code>.</p>
<p>:param challenge: The JSON license request bytes to POST to the license server.
:param title: The current <code>Title</code> from get_titles that unshackle processes now. unshackle
gives this in case it holds data you need, for example for an HTTP request.
:param track: The current <code>Track</code> needing decryption. Provided for same reason as <code>title</code>.
:return: The JWK Set license as a dict, JSON str, or raw bytes. Return None (the default)
to let the framework POST the challenge to the manifest-provided Laurl, if any.
Services with no license server can instead pre-populate the DRM object's
<code>content_keys</code> in get_tracks.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-585">585</a></span>
<span class="normal"><a href="#__codelineno-0-586">586</a></span>
<span class="normal"><a href="#__codelineno-0-587">587</a></span>
<span class="normal"><a href="#__codelineno-0-588">588</a></span>
<span class="normal"><a href="#__codelineno-0-589">589</a></span>
<span class="normal"><a href="#__codelineno-0-590">590</a></span>
<span class="normal"><a href="#__codelineno-0-591">591</a></span>
<span class="normal"><a href="#__codelineno-0-592">592</a></span>
<span class="normal"><a href="#__codelineno-0-593">593</a></span>
<span class="normal"><a href="#__codelineno-0-594">594</a></span>
<span class="normal"><a href="#__codelineno-0-595">595</a></span>
<span class="normal"><a href="#__codelineno-0-596">596</a></span>
<span class="normal"><a href="#__codelineno-0-597">597</a></span>
<span class="normal"><a href="#__codelineno-0-598">598</a></span>
<span class="normal"><a href="#__codelineno-0-599">599</a></span>
<span class="normal"><a href="#__codelineno-0-600">600</a></span>
<span class="normal"><a href="#__codelineno-0-601">601</a></span>
<span class="normal"><a href="#__codelineno-0-602">602</a></span>
<span class="normal"><a href="#__codelineno-0-603">603</a></span>
<span class="normal"><a href="#__codelineno-0-604">604</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-585"><a id="__codelineno-0-585" name="__codelineno-0-585"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_clearkey_license</span><span class="p">(</span>
</span><span id="__span-0-586"><a id="__codelineno-0-586" name="__codelineno-0-586"></a> <span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">challenge</span><span class="p">:</span> <span class="nb">bytes</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">,</span> <span class="n">track</span><span class="p">:</span> <span class="n">AnyTrack</span>
</span><span id="__span-0-587"><a id="__codelineno-0-587" name="__codelineno-0-587"></a><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Optional</span><span class="p">[</span><span class="n">Union</span><span class="p">[</span><span class="nb">bytes</span><span class="p">,</span> <span class="nb">str</span><span class="p">,</span> <span class="nb">dict</span><span class="p">]]:</span>
</span><span id="__span-0-588"><a id="__codelineno-0-588" name="__codelineno-0-588"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-589"><a id="__codelineno-0-589" name="__codelineno-0-589"></a><span class="sd"> Get a W3C ClearKey License (JWK Set) by sending a License Request (challenge).</span>
</span><span id="__span-0-590"><a id="__codelineno-0-590" name="__codelineno-0-590"></a>
</span><span id="__span-0-591"><a id="__codelineno-0-591" name="__codelineno-0-591"></a><span class="sd"> Used for DASH `org.w3.clearkey` tracks. unshackle uses no CDM here: the challenge is</span>
</span><span id="__span-0-592"><a id="__codelineno-0-592" name="__codelineno-0-592"></a><span class="sd"> the W3C EME JSON license request, e.g. ``{"kids": ["&lt;base64url&gt;"], "type": "temporary"}``,</span>
</span><span id="__span-0-593"><a id="__codelineno-0-593" name="__codelineno-0-593"></a><span class="sd"> and the license is a JWK Set, e.g. ``{"keys": [{"kty": "oct", "k": "...", "kid": "..."}]}``.</span>
</span><span id="__span-0-594"><a id="__codelineno-0-594" name="__codelineno-0-594"></a>
</span><span id="__span-0-595"><a id="__codelineno-0-595" name="__codelineno-0-595"></a><span class="sd"> :param challenge: The JSON license request bytes to POST to the license server.</span>
</span><span id="__span-0-596"><a id="__codelineno-0-596" name="__codelineno-0-596"></a><span class="sd"> :param title: The current `Title` from get_titles that unshackle processes now. unshackle</span>
</span><span id="__span-0-597"><a id="__codelineno-0-597" name="__codelineno-0-597"></a><span class="sd"> gives this in case it holds data you need, for example for an HTTP request.</span>
</span><span id="__span-0-598"><a id="__codelineno-0-598" name="__codelineno-0-598"></a><span class="sd"> :param track: The current `Track` needing decryption. Provided for same reason as `title`.</span>
</span><span id="__span-0-599"><a id="__codelineno-0-599" name="__codelineno-0-599"></a><span class="sd"> :return: The JWK Set license as a dict, JSON str, or raw bytes. Return None (the default)</span>
</span><span id="__span-0-600"><a id="__codelineno-0-600" name="__codelineno-0-600"></a><span class="sd"> to let the framework POST the challenge to the manifest-provided Laurl, if any.</span>
</span><span id="__span-0-601"><a id="__codelineno-0-601" name="__codelineno-0-601"></a><span class="sd"> Services with no license server can instead pre-populate the DRM object's</span>
</span><span id="__span-0-602"><a id="__codelineno-0-602" name="__codelineno-0-602"></a><span class="sd"> `content_keys` in get_tracks.</span>
</span><span id="__span-0-603"><a id="__codelineno-0-603" name="__codelineno-0-603"></a><span class="sd"> """</span>
</span><span id="__span-0-604"><a id="__codelineno-0-604" name="__codelineno-0-604"></a> <span class="k">return</span> <span class="kc">None</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.get_titles" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">get_titles</span>
<span class="doc doc-labels">
<small class="doc doc-label doc-label-abstractmethod"><code>abstractmethod</code></small>
</span>
<a href="#unshackle.core.service.Service.get_titles" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">get_titles</span><span class="p">()</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Get Titles for the provided title ID.</p>
<p>Return a Movies, Series, or Album objects containing Movie, Episode, or Song title objects respectively.
The returned data must be for the given title ID, or a spawn of the title ID.</p>
<p>You must return at least one object. If you do not, unshackle presumes an invalid
Title ID.</p>
<p>You can use the <code>data</code> dictionary class instance attribute of each Title to store data you may need later on.
This can be useful to store information on each title that you need later, like any sub-asset IDs, or such.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-606">606</a></span>
<span class="normal"><a href="#__codelineno-0-607">607</a></span>
<span class="normal"><a href="#__codelineno-0-608">608</a></span>
<span class="normal"><a href="#__codelineno-0-609">609</a></span>
<span class="normal"><a href="#__codelineno-0-610">610</a></span>
<span class="normal"><a href="#__codelineno-0-611">611</a></span>
<span class="normal"><a href="#__codelineno-0-612">612</a></span>
<span class="normal"><a href="#__codelineno-0-613">613</a></span>
<span class="normal"><a href="#__codelineno-0-614">614</a></span>
<span class="normal"><a href="#__codelineno-0-615">615</a></span>
<span class="normal"><a href="#__codelineno-0-616">616</a></span>
<span class="normal"><a href="#__codelineno-0-617">617</a></span>
<span class="normal"><a href="#__codelineno-0-618">618</a></span>
<span class="normal"><a href="#__codelineno-0-619">619</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-606"><a id="__codelineno-0-606" name="__codelineno-0-606"></a><span class="nd">@abstractmethod</span>
</span><span id="__span-0-607"><a id="__codelineno-0-607" name="__codelineno-0-607"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_titles</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Titles_T</span><span class="p">:</span>
</span><span id="__span-0-608"><a id="__codelineno-0-608" name="__codelineno-0-608"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-609"><a id="__codelineno-0-609" name="__codelineno-0-609"></a><span class="sd"> Get Titles for the provided title ID.</span>
</span><span id="__span-0-610"><a id="__codelineno-0-610" name="__codelineno-0-610"></a>
</span><span id="__span-0-611"><a id="__codelineno-0-611" name="__codelineno-0-611"></a><span class="sd"> Return a Movies, Series, or Album objects containing Movie, Episode, or Song title objects respectively.</span>
</span><span id="__span-0-612"><a id="__codelineno-0-612" name="__codelineno-0-612"></a><span class="sd"> The returned data must be for the given title ID, or a spawn of the title ID.</span>
</span><span id="__span-0-613"><a id="__codelineno-0-613" name="__codelineno-0-613"></a>
</span><span id="__span-0-614"><a id="__codelineno-0-614" name="__codelineno-0-614"></a><span class="sd"> You must return at least one object. If you do not, unshackle presumes an invalid</span>
</span><span id="__span-0-615"><a id="__codelineno-0-615" name="__codelineno-0-615"></a><span class="sd"> Title ID.</span>
</span><span id="__span-0-616"><a id="__codelineno-0-616" name="__codelineno-0-616"></a>
</span><span id="__span-0-617"><a id="__codelineno-0-617" name="__codelineno-0-617"></a><span class="sd"> You can use the `data` dictionary class instance attribute of each Title to store data you may need later on.</span>
</span><span id="__span-0-618"><a id="__codelineno-0-618" name="__codelineno-0-618"></a><span class="sd"> This can be useful to store information on each title that you need later, like any sub-asset IDs, or such.</span>
</span><span id="__span-0-619"><a id="__codelineno-0-619" name="__codelineno-0-619"></a><span class="sd"> """</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.get_titles_cached" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">get_titles_cached</span>
<a href="#unshackle.core.service.Service.get_titles_cached" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">get_titles_cached</span><span class="p">(</span><span class="n">title_id</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Cached wrapper around get_titles() to reduce redundant API calls.</p>
<p>This method checks the cache before calling get_titles() and handles
fallback to cached data when API calls fail.</p>
<p><span class="doc-section-title">Parameters:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td>
<code>title_id</code>
</td>
<td>
<code><span title="str">str</span></code>
</td>
<td>
<div class="doc-md-description">
<p>Optional title ID for cache key generation.
If not provided, will try to extract from service instance.</p>
</div>
</td>
<td>
<code>None</code>
</td>
</tr>
</tbody>
</table>
<p><span class="doc-section-title">Returns:</span></p>
<table>
<thead>
<tr>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td>
<code><span title="unshackle.core.titles.Titles_T">Titles_T</span></code>
</td>
<td>
<div class="doc-md-description">
<p>Titles object (Movies, Series, or Album)</p>
</div>
</td>
</tr>
</tbody>
</table>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-621">621</a></span>
<span class="normal"><a href="#__codelineno-0-622">622</a></span>
<span class="normal"><a href="#__codelineno-0-623">623</a></span>
<span class="normal"><a href="#__codelineno-0-624">624</a></span>
<span class="normal"><a href="#__codelineno-0-625">625</a></span>
<span class="normal"><a href="#__codelineno-0-626">626</a></span>
<span class="normal"><a href="#__codelineno-0-627">627</a></span>
<span class="normal"><a href="#__codelineno-0-628">628</a></span>
<span class="normal"><a href="#__codelineno-0-629">629</a></span>
<span class="normal"><a href="#__codelineno-0-630">630</a></span>
<span class="normal"><a href="#__codelineno-0-631">631</a></span>
<span class="normal"><a href="#__codelineno-0-632">632</a></span>
<span class="normal"><a href="#__codelineno-0-633">633</a></span>
<span class="normal"><a href="#__codelineno-0-634">634</a></span>
<span class="normal"><a href="#__codelineno-0-635">635</a></span>
<span class="normal"><a href="#__codelineno-0-636">636</a></span>
<span class="normal"><a href="#__codelineno-0-637">637</a></span>
<span class="normal"><a href="#__codelineno-0-638">638</a></span>
<span class="normal"><a href="#__codelineno-0-639">639</a></span>
<span class="normal"><a href="#__codelineno-0-640">640</a></span>
<span class="normal"><a href="#__codelineno-0-641">641</a></span>
<span class="normal"><a href="#__codelineno-0-642">642</a></span>
<span class="normal"><a href="#__codelineno-0-643">643</a></span>
<span class="normal"><a href="#__codelineno-0-644">644</a></span>
<span class="normal"><a href="#__codelineno-0-645">645</a></span>
<span class="normal"><a href="#__codelineno-0-646">646</a></span>
<span class="normal"><a href="#__codelineno-0-647">647</a></span>
<span class="normal"><a href="#__codelineno-0-648">648</a></span>
<span class="normal"><a href="#__codelineno-0-649">649</a></span>
<span class="normal"><a href="#__codelineno-0-650">650</a></span>
<span class="normal"><a href="#__codelineno-0-651">651</a></span>
<span class="normal"><a href="#__codelineno-0-652">652</a></span>
<span class="normal"><a href="#__codelineno-0-653">653</a></span>
<span class="normal"><a href="#__codelineno-0-654">654</a></span>
<span class="normal"><a href="#__codelineno-0-655">655</a></span>
<span class="normal"><a href="#__codelineno-0-656">656</a></span>
<span class="normal"><a href="#__codelineno-0-657">657</a></span>
<span class="normal"><a href="#__codelineno-0-658">658</a></span>
<span class="normal"><a href="#__codelineno-0-659">659</a></span>
<span class="normal"><a href="#__codelineno-0-660">660</a></span>
<span class="normal"><a href="#__codelineno-0-661">661</a></span>
<span class="normal"><a href="#__codelineno-0-662">662</a></span>
<span class="normal"><a href="#__codelineno-0-663">663</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-621"><a id="__codelineno-0-621" name="__codelineno-0-621"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_titles_cached</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title_id</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Titles_T</span><span class="p">:</span>
</span><span id="__span-0-622"><a id="__codelineno-0-622" name="__codelineno-0-622"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-623"><a id="__codelineno-0-623" name="__codelineno-0-623"></a><span class="sd"> Cached wrapper around get_titles() to reduce redundant API calls.</span>
</span><span id="__span-0-624"><a id="__codelineno-0-624" name="__codelineno-0-624"></a>
</span><span id="__span-0-625"><a id="__codelineno-0-625" name="__codelineno-0-625"></a><span class="sd"> This method checks the cache before calling get_titles() and handles</span>
</span><span id="__span-0-626"><a id="__codelineno-0-626" name="__codelineno-0-626"></a><span class="sd"> fallback to cached data when API calls fail.</span>
</span><span id="__span-0-627"><a id="__codelineno-0-627" name="__codelineno-0-627"></a>
</span><span id="__span-0-628"><a id="__codelineno-0-628" name="__codelineno-0-628"></a><span class="sd"> Args:</span>
</span><span id="__span-0-629"><a id="__codelineno-0-629" name="__codelineno-0-629"></a><span class="sd"> title_id: Optional title ID for cache key generation.</span>
</span><span id="__span-0-630"><a id="__codelineno-0-630" name="__codelineno-0-630"></a><span class="sd"> If not provided, will try to extract from service instance.</span>
</span><span id="__span-0-631"><a id="__codelineno-0-631" name="__codelineno-0-631"></a>
</span><span id="__span-0-632"><a id="__codelineno-0-632" name="__codelineno-0-632"></a><span class="sd"> Returns:</span>
</span><span id="__span-0-633"><a id="__codelineno-0-633" name="__codelineno-0-633"></a><span class="sd"> Titles object (Movies, Series, or Album)</span>
</span><span id="__span-0-634"><a id="__codelineno-0-634" name="__codelineno-0-634"></a><span class="sd"> """</span>
</span><span id="__span-0-635"><a id="__codelineno-0-635" name="__codelineno-0-635"></a> <span class="k">if</span> <span class="n">title_id</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="__span-0-636"><a id="__codelineno-0-636" name="__codelineno-0-636"></a> <span class="c1"># Different services store the title ID in different attributes</span>
</span><span id="__span-0-637"><a id="__codelineno-0-637" name="__codelineno-0-637"></a> <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"title"</span><span class="p">):</span>
</span><span id="__span-0-638"><a id="__codelineno-0-638" name="__codelineno-0-638"></a> <span class="n">title_id</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span>
</span><span id="__span-0-639"><a id="__codelineno-0-639" name="__codelineno-0-639"></a> <span class="k">elif</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"title_id"</span><span class="p">):</span>
</span><span id="__span-0-640"><a id="__codelineno-0-640" name="__codelineno-0-640"></a> <span class="n">title_id</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">title_id</span>
</span><span id="__span-0-641"><a id="__codelineno-0-641" name="__codelineno-0-641"></a> <span class="k">else</span><span class="p">:</span>
</span><span id="__span-0-642"><a id="__codelineno-0-642" name="__codelineno-0-642"></a> <span class="c1"># If we can't determine title_id, just call get_titles directly</span>
</span><span id="__span-0-643"><a id="__codelineno-0-643" name="__codelineno-0-643"></a> <span class="bp">self</span><span class="o">.</span><span class="n">log</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s2">"Cannot determine title_id for caching, bypassing cache"</span><span class="p">)</span>
</span><span id="__span-0-644"><a id="__codelineno-0-644" name="__codelineno-0-644"></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">apply_title_map</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">get_titles</span><span class="p">())</span>
</span><span id="__span-0-645"><a id="__codelineno-0-645" name="__codelineno-0-645"></a>
</span><span id="__span-0-646"><a id="__codelineno-0-646" name="__codelineno-0-646"></a> <span class="n">no_cache</span> <span class="o">=</span> <span class="kc">False</span>
</span><span id="__span-0-647"><a id="__codelineno-0-647" name="__codelineno-0-647"></a> <span class="n">reset_cache</span> <span class="o">=</span> <span class="kc">False</span>
</span><span id="__span-0-648"><a id="__codelineno-0-648" name="__codelineno-0-648"></a> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">ctx</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">ctx</span><span class="o">.</span><span class="n">parent</span><span class="p">:</span>
</span><span id="__span-0-649"><a id="__codelineno-0-649" name="__codelineno-0-649"></a> <span class="n">no_cache</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">ctx</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"no_cache"</span><span class="p">,</span> <span class="kc">False</span><span class="p">)</span>
</span><span id="__span-0-650"><a id="__codelineno-0-650" name="__codelineno-0-650"></a> <span class="n">reset_cache</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">ctx</span><span class="o">.</span><span class="n">parent</span><span class="o">.</span><span class="n">params</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"reset_cache"</span><span class="p">,</span> <span class="kc">False</span><span class="p">)</span>
</span><span id="__span-0-651"><a id="__codelineno-0-651" name="__codelineno-0-651"></a>
</span><span id="__span-0-652"><a id="__codelineno-0-652" name="__codelineno-0-652"></a> <span class="c1"># Get account hash for cache key</span>
</span><span id="__span-0-653"><a id="__codelineno-0-653" name="__codelineno-0-653"></a> <span class="n">account_hash</span> <span class="o">=</span> <span class="n">get_account_hash</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">credential</span><span class="p">)</span>
</span><span id="__span-0-654"><a id="__codelineno-0-654" name="__codelineno-0-654"></a>
</span><span id="__span-0-655"><a id="__codelineno-0-655" name="__codelineno-0-655"></a> <span class="n">titles</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">title_cache</span><span class="o">.</span><span class="n">get_cached_titles</span><span class="p">(</span>
</span><span id="__span-0-656"><a id="__codelineno-0-656" name="__codelineno-0-656"></a> <span class="n">title_id</span><span class="o">=</span><span class="nb">str</span><span class="p">(</span><span class="n">title_id</span><span class="p">),</span>
</span><span id="__span-0-657"><a id="__codelineno-0-657" name="__codelineno-0-657"></a> <span class="n">fetch_function</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">get_titles</span><span class="p">,</span>
</span><span id="__span-0-658"><a id="__codelineno-0-658" name="__codelineno-0-658"></a> <span class="n">region</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">current_region</span><span class="p">,</span>
</span><span id="__span-0-659"><a id="__codelineno-0-659" name="__codelineno-0-659"></a> <span class="n">account_hash</span><span class="o">=</span><span class="n">account_hash</span><span class="p">,</span>
</span><span id="__span-0-660"><a id="__codelineno-0-660" name="__codelineno-0-660"></a> <span class="n">no_cache</span><span class="o">=</span><span class="n">no_cache</span><span class="p">,</span>
</span><span id="__span-0-661"><a id="__codelineno-0-661" name="__codelineno-0-661"></a> <span class="n">reset_cache</span><span class="o">=</span><span class="n">reset_cache</span><span class="p">,</span>
</span><span id="__span-0-662"><a id="__codelineno-0-662" name="__codelineno-0-662"></a> <span class="p">)</span>
</span><span id="__span-0-663"><a id="__codelineno-0-663" name="__codelineno-0-663"></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">apply_title_map</span><span class="p">(</span><span class="n">titles</span><span class="p">)</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.apply_title_map" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">apply_title_map</span>
<a href="#unshackle.core.service.Service.apply_title_map" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">apply_title_map</span><span class="p">(</span><span class="n">titles</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Rewrite service-provided titles using the per-service <code>title_map</code> config.</p>
<p><code>title_map</code> lives under <code>services.&lt;TAG&gt;</code> in unshackle.yaml. Applied after the
title cache so config edits take effect without a cache reset, and before any
<code>--enrich</code> override so enrich wins. See <code>remap_titles</code> for the match rules.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-665">665</a></span>
<span class="normal"><a href="#__codelineno-0-666">666</a></span>
<span class="normal"><a href="#__codelineno-0-667">667</a></span>
<span class="normal"><a href="#__codelineno-0-668">668</a></span>
<span class="normal"><a href="#__codelineno-0-669">669</a></span>
<span class="normal"><a href="#__codelineno-0-670">670</a></span>
<span class="normal"><a href="#__codelineno-0-671">671</a></span>
<span class="normal"><a href="#__codelineno-0-672">672</a></span>
<span class="normal"><a href="#__codelineno-0-673">673</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-665"><a id="__codelineno-0-665" name="__codelineno-0-665"></a><span class="k">def</span><span class="w"> </span><span class="nf">apply_title_map</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">titles</span><span class="p">:</span> <span class="n">Titles_T</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Titles_T</span><span class="p">:</span>
</span><span id="__span-0-666"><a id="__codelineno-0-666" name="__codelineno-0-666"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-667"><a id="__codelineno-0-667" name="__codelineno-0-667"></a><span class="sd"> Rewrite service-provided titles using the per-service ``title_map`` config.</span>
</span><span id="__span-0-668"><a id="__codelineno-0-668" name="__codelineno-0-668"></a>
</span><span id="__span-0-669"><a id="__codelineno-0-669" name="__codelineno-0-669"></a><span class="sd"> ``title_map`` lives under ``services.&lt;TAG&gt;`` in unshackle.yaml. Applied after the</span>
</span><span id="__span-0-670"><a id="__codelineno-0-670" name="__codelineno-0-670"></a><span class="sd"> title cache so config edits take effect without a cache reset, and before any</span>
</span><span id="__span-0-671"><a id="__codelineno-0-671" name="__codelineno-0-671"></a><span class="sd"> ``--enrich`` override so enrich wins. See ``remap_titles`` for the match rules.</span>
</span><span id="__span-0-672"><a id="__codelineno-0-672" name="__codelineno-0-672"></a><span class="sd"> """</span>
</span><span id="__span-0-673"><a id="__codelineno-0-673" name="__codelineno-0-673"></a> <span class="k">return</span> <span class="n">remap_titles</span><span class="p">(</span><span class="n">titles</span><span class="p">,</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">config</span> <span class="ow">or</span> <span class="p">{})</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"title_map"</span><span class="p">)</span> <span class="ow">or</span> <span class="p">{})</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.get_tracks" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">get_tracks</span>
<span class="doc doc-labels">
<small class="doc doc-label doc-label-abstractmethod"><code>abstractmethod</code></small>
</span>
<a href="#unshackle.core.service.Service.get_tracks" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">get_tracks</span><span class="p">(</span><span class="n">title</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Get Track objects of the Title.</p>
<p>Return a Tracks object, which itself can contain Video, Audio, Subtitle or even Chapters.
Tracks.videos, Tracks.audio, Tracks.subtitles, and Track.chapters should be a List of Track objects.</p>
<p>Each Track in the Tracks should represent a Video/Audio track, Representation, or
Adaptation, or a Subtitle file.</p>
<p>While one Track should only hold information for one downloadable track, try to get as many
unique Track objects per track type so track selection by the root code can give you more
options in terms of Resolution, Bitrate, Codecs, Language, and such.</p>
<p>No decision making or filtering of which Tracks get returned should happen here. It can be
considered an error to filter for e.g. resolution, codec, and such. All filtering based on
arguments will be done by the root code automatically when needed.</p>
<p>Make sure you correctly mark which Tracks have encryption, and which DRM System they
use, with the <code>drm</code> property.</p>
<p>If you can get the Track's KID (Key ID) as a 32 char (16 bit) HEX string, give it to the
Track's <code>kid</code> variable, as it will speed up the decryption process later on. The service
decides whether it is necessary. Generally if you can give it, without downloading any of
the Track's media data, then do.</p>
<p>:param title: The current <code>Title</code> from get_titles that unshackle processes now.
:return: Tracks object containing Video, Audio, Subtitles, and Chapters, if available.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-675">675</a></span>
<span class="normal"><a href="#__codelineno-0-676">676</a></span>
<span class="normal"><a href="#__codelineno-0-677">677</a></span>
<span class="normal"><a href="#__codelineno-0-678">678</a></span>
<span class="normal"><a href="#__codelineno-0-679">679</a></span>
<span class="normal"><a href="#__codelineno-0-680">680</a></span>
<span class="normal"><a href="#__codelineno-0-681">681</a></span>
<span class="normal"><a href="#__codelineno-0-682">682</a></span>
<span class="normal"><a href="#__codelineno-0-683">683</a></span>
<span class="normal"><a href="#__codelineno-0-684">684</a></span>
<span class="normal"><a href="#__codelineno-0-685">685</a></span>
<span class="normal"><a href="#__codelineno-0-686">686</a></span>
<span class="normal"><a href="#__codelineno-0-687">687</a></span>
<span class="normal"><a href="#__codelineno-0-688">688</a></span>
<span class="normal"><a href="#__codelineno-0-689">689</a></span>
<span class="normal"><a href="#__codelineno-0-690">690</a></span>
<span class="normal"><a href="#__codelineno-0-691">691</a></span>
<span class="normal"><a href="#__codelineno-0-692">692</a></span>
<span class="normal"><a href="#__codelineno-0-693">693</a></span>
<span class="normal"><a href="#__codelineno-0-694">694</a></span>
<span class="normal"><a href="#__codelineno-0-695">695</a></span>
<span class="normal"><a href="#__codelineno-0-696">696</a></span>
<span class="normal"><a href="#__codelineno-0-697">697</a></span>
<span class="normal"><a href="#__codelineno-0-698">698</a></span>
<span class="normal"><a href="#__codelineno-0-699">699</a></span>
<span class="normal"><a href="#__codelineno-0-700">700</a></span>
<span class="normal"><a href="#__codelineno-0-701">701</a></span>
<span class="normal"><a href="#__codelineno-0-702">702</a></span>
<span class="normal"><a href="#__codelineno-0-703">703</a></span>
<span class="normal"><a href="#__codelineno-0-704">704</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-675"><a id="__codelineno-0-675" name="__codelineno-0-675"></a><span class="nd">@abstractmethod</span>
</span><span id="__span-0-676"><a id="__codelineno-0-676" name="__codelineno-0-676"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_tracks</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Tracks</span><span class="p">:</span>
</span><span id="__span-0-677"><a id="__codelineno-0-677" name="__codelineno-0-677"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-678"><a id="__codelineno-0-678" name="__codelineno-0-678"></a><span class="sd"> Get Track objects of the Title.</span>
</span><span id="__span-0-679"><a id="__codelineno-0-679" name="__codelineno-0-679"></a>
</span><span id="__span-0-680"><a id="__codelineno-0-680" name="__codelineno-0-680"></a><span class="sd"> Return a Tracks object, which itself can contain Video, Audio, Subtitle or even Chapters.</span>
</span><span id="__span-0-681"><a id="__codelineno-0-681" name="__codelineno-0-681"></a><span class="sd"> Tracks.videos, Tracks.audio, Tracks.subtitles, and Track.chapters should be a List of Track objects.</span>
</span><span id="__span-0-682"><a id="__codelineno-0-682" name="__codelineno-0-682"></a>
</span><span id="__span-0-683"><a id="__codelineno-0-683" name="__codelineno-0-683"></a><span class="sd"> Each Track in the Tracks should represent a Video/Audio track, Representation, or</span>
</span><span id="__span-0-684"><a id="__codelineno-0-684" name="__codelineno-0-684"></a><span class="sd"> Adaptation, or a Subtitle file.</span>
</span><span id="__span-0-685"><a id="__codelineno-0-685" name="__codelineno-0-685"></a>
</span><span id="__span-0-686"><a id="__codelineno-0-686" name="__codelineno-0-686"></a><span class="sd"> While one Track should only hold information for one downloadable track, try to get as many</span>
</span><span id="__span-0-687"><a id="__codelineno-0-687" name="__codelineno-0-687"></a><span class="sd"> unique Track objects per track type so track selection by the root code can give you more</span>
</span><span id="__span-0-688"><a id="__codelineno-0-688" name="__codelineno-0-688"></a><span class="sd"> options in terms of Resolution, Bitrate, Codecs, Language, and such.</span>
</span><span id="__span-0-689"><a id="__codelineno-0-689" name="__codelineno-0-689"></a>
</span><span id="__span-0-690"><a id="__codelineno-0-690" name="__codelineno-0-690"></a><span class="sd"> No decision making or filtering of which Tracks get returned should happen here. It can be</span>
</span><span id="__span-0-691"><a id="__codelineno-0-691" name="__codelineno-0-691"></a><span class="sd"> considered an error to filter for e.g. resolution, codec, and such. All filtering based on</span>
</span><span id="__span-0-692"><a id="__codelineno-0-692" name="__codelineno-0-692"></a><span class="sd"> arguments will be done by the root code automatically when needed.</span>
</span><span id="__span-0-693"><a id="__codelineno-0-693" name="__codelineno-0-693"></a>
</span><span id="__span-0-694"><a id="__codelineno-0-694" name="__codelineno-0-694"></a><span class="sd"> Make sure you correctly mark which Tracks have encryption, and which DRM System they</span>
</span><span id="__span-0-695"><a id="__codelineno-0-695" name="__codelineno-0-695"></a><span class="sd"> use, with the `drm` property.</span>
</span><span id="__span-0-696"><a id="__codelineno-0-696" name="__codelineno-0-696"></a>
</span><span id="__span-0-697"><a id="__codelineno-0-697" name="__codelineno-0-697"></a><span class="sd"> If you can get the Track's KID (Key ID) as a 32 char (16 bit) HEX string, give it to the</span>
</span><span id="__span-0-698"><a id="__codelineno-0-698" name="__codelineno-0-698"></a><span class="sd"> Track's `kid` variable, as it will speed up the decryption process later on. The service</span>
</span><span id="__span-0-699"><a id="__codelineno-0-699" name="__codelineno-0-699"></a><span class="sd"> decides whether it is necessary. Generally if you can give it, without downloading any of</span>
</span><span id="__span-0-700"><a id="__codelineno-0-700" name="__codelineno-0-700"></a><span class="sd"> the Track's media data, then do.</span>
</span><span id="__span-0-701"><a id="__codelineno-0-701" name="__codelineno-0-701"></a>
</span><span id="__span-0-702"><a id="__codelineno-0-702" name="__codelineno-0-702"></a><span class="sd"> :param title: The current `Title` from get_titles that unshackle processes now.</span>
</span><span id="__span-0-703"><a id="__codelineno-0-703" name="__codelineno-0-703"></a><span class="sd"> :return: Tracks object containing Video, Audio, Subtitles, and Chapters, if available.</span>
</span><span id="__span-0-704"><a id="__codelineno-0-704" name="__codelineno-0-704"></a><span class="sd"> """</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.get_chapters" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">get_chapters</span>
<span class="doc doc-labels">
<small class="doc doc-label doc-label-abstractmethod"><code>abstractmethod</code></small>
</span>
<a href="#unshackle.core.service.Service.get_chapters" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">get_chapters</span><span class="p">(</span><span class="n">title</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Get Chapters for the Title.</p>
<p><span class="doc-section-title">Parameters:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td>
<code>title</code>
</td>
<td>
<code><span title="unshackle.core.titles.Title_T">Title_T</span></code>
</td>
<td>
<div class="doc-md-description">
<p>The current Title from <code>get_titles</code> that unshackle processes now.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
</tbody>
</table>
<p>You must return a Chapters object containing 0 or more Chapter objects.</p>
<p>You do not need to set a Chapter number or sort/order the chapters in any way as
the Chapters class automatically handles all of that for you. If there is no
descriptive name for a Chapter then do not set a name at all.</p>
<p>You must not set Chapter names to "Chapter {n}" or such. If you (or the user)
wants "Chapter {n}" style Chapter names (or similar) then they can use the config
option <code>chapter_fallback_name</code>. For example, <code>"Chapter {i:02}"</code> for "Chapter 01".</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-706">706</a></span>
<span class="normal"><a href="#__codelineno-0-707">707</a></span>
<span class="normal"><a href="#__codelineno-0-708">708</a></span>
<span class="normal"><a href="#__codelineno-0-709">709</a></span>
<span class="normal"><a href="#__codelineno-0-710">710</a></span>
<span class="normal"><a href="#__codelineno-0-711">711</a></span>
<span class="normal"><a href="#__codelineno-0-712">712</a></span>
<span class="normal"><a href="#__codelineno-0-713">713</a></span>
<span class="normal"><a href="#__codelineno-0-714">714</a></span>
<span class="normal"><a href="#__codelineno-0-715">715</a></span>
<span class="normal"><a href="#__codelineno-0-716">716</a></span>
<span class="normal"><a href="#__codelineno-0-717">717</a></span>
<span class="normal"><a href="#__codelineno-0-718">718</a></span>
<span class="normal"><a href="#__codelineno-0-719">719</a></span>
<span class="normal"><a href="#__codelineno-0-720">720</a></span>
<span class="normal"><a href="#__codelineno-0-721">721</a></span>
<span class="normal"><a href="#__codelineno-0-722">722</a></span>
<span class="normal"><a href="#__codelineno-0-723">723</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-706"><a id="__codelineno-0-706" name="__codelineno-0-706"></a><span class="nd">@abstractmethod</span>
</span><span id="__span-0-707"><a id="__codelineno-0-707" name="__codelineno-0-707"></a><span class="k">def</span><span class="w"> </span><span class="nf">get_chapters</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="p">:</span> <span class="n">Title_T</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Chapters</span><span class="p">:</span>
</span><span id="__span-0-708"><a id="__codelineno-0-708" name="__codelineno-0-708"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-709"><a id="__codelineno-0-709" name="__codelineno-0-709"></a><span class="sd"> Get Chapters for the Title.</span>
</span><span id="__span-0-710"><a id="__codelineno-0-710" name="__codelineno-0-710"></a>
</span><span id="__span-0-711"><a id="__codelineno-0-711" name="__codelineno-0-711"></a><span class="sd"> Parameters:</span>
</span><span id="__span-0-712"><a id="__codelineno-0-712" name="__codelineno-0-712"></a><span class="sd"> title: The current Title from `get_titles` that unshackle processes now.</span>
</span><span id="__span-0-713"><a id="__codelineno-0-713" name="__codelineno-0-713"></a>
</span><span id="__span-0-714"><a id="__codelineno-0-714" name="__codelineno-0-714"></a><span class="sd"> You must return a Chapters object containing 0 or more Chapter objects.</span>
</span><span id="__span-0-715"><a id="__codelineno-0-715" name="__codelineno-0-715"></a>
</span><span id="__span-0-716"><a id="__codelineno-0-716" name="__codelineno-0-716"></a><span class="sd"> You do not need to set a Chapter number or sort/order the chapters in any way as</span>
</span><span id="__span-0-717"><a id="__codelineno-0-717" name="__codelineno-0-717"></a><span class="sd"> the Chapters class automatically handles all of that for you. If there is no</span>
</span><span id="__span-0-718"><a id="__codelineno-0-718" name="__codelineno-0-718"></a><span class="sd"> descriptive name for a Chapter then do not set a name at all.</span>
</span><span id="__span-0-719"><a id="__codelineno-0-719" name="__codelineno-0-719"></a>
</span><span id="__span-0-720"><a id="__codelineno-0-720" name="__codelineno-0-720"></a><span class="sd"> You must not set Chapter names to "Chapter {n}" or such. If you (or the user)</span>
</span><span id="__span-0-721"><a id="__codelineno-0-721" name="__codelineno-0-721"></a><span class="sd"> wants "Chapter {n}" style Chapter names (or similar) then they can use the config</span>
</span><span id="__span-0-722"><a id="__codelineno-0-722" name="__codelineno-0-722"></a><span class="sd"> option `chapter_fallback_name`. For example, `"Chapter {i:02}"` for "Chapter 01".</span>
</span><span id="__span-0-723"><a id="__codelineno-0-723" name="__codelineno-0-723"></a><span class="sd"> """</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.on_segment_downloaded" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">on_segment_downloaded</span>
<a href="#unshackle.core.service.Service.on_segment_downloaded" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">on_segment_downloaded</span><span class="p">(</span><span class="n">track</span><span class="p">,</span> <span class="n">segment</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Called when one of a Track's Segments has finished downloading.</p>
<p><span class="doc-section-title">Parameters:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td>
<code>track</code>
</td>
<td>
<code><span title="unshackle.core.constants.AnyTrack">AnyTrack</span></code>
</td>
<td>
<div class="doc-md-description">
<p>The Track object that had a Segment downloaded.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>segment</code>
</td>
<td>
<code><span title="pathlib.Path">Path</span></code>
</td>
<td>
<div class="doc-md-description">
<p>The Path to the downloaded Segment.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
</tbody>
</table>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-727">727</a></span>
<span class="normal"><a href="#__codelineno-0-728">728</a></span>
<span class="normal"><a href="#__codelineno-0-729">729</a></span>
<span class="normal"><a href="#__codelineno-0-730">730</a></span>
<span class="normal"><a href="#__codelineno-0-731">731</a></span>
<span class="normal"><a href="#__codelineno-0-732">732</a></span>
<span class="normal"><a href="#__codelineno-0-733">733</a></span>
<span class="normal"><a href="#__codelineno-0-734">734</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-727"><a id="__codelineno-0-727" name="__codelineno-0-727"></a><span class="k">def</span><span class="w"> </span><span class="nf">on_segment_downloaded</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">track</span><span class="p">:</span> <span class="n">AnyTrack</span><span class="p">,</span> <span class="n">segment</span><span class="p">:</span> <span class="n">Path</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="__span-0-728"><a id="__codelineno-0-728" name="__codelineno-0-728"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-729"><a id="__codelineno-0-729" name="__codelineno-0-729"></a><span class="sd"> Called when one of a Track's Segments has finished downloading.</span>
</span><span id="__span-0-730"><a id="__codelineno-0-730" name="__codelineno-0-730"></a>
</span><span id="__span-0-731"><a id="__codelineno-0-731" name="__codelineno-0-731"></a><span class="sd"> Parameters:</span>
</span><span id="__span-0-732"><a id="__codelineno-0-732" name="__codelineno-0-732"></a><span class="sd"> track: The Track object that had a Segment downloaded.</span>
</span><span id="__span-0-733"><a id="__codelineno-0-733" name="__codelineno-0-733"></a><span class="sd"> segment: The Path to the downloaded Segment.</span>
</span><span id="__span-0-734"><a id="__codelineno-0-734" name="__codelineno-0-734"></a><span class="sd"> """</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.on_track_downloaded" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">on_track_downloaded</span>
<a href="#unshackle.core.service.Service.on_track_downloaded" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">on_track_downloaded</span><span class="p">(</span><span class="n">track</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Called when a Track has finished downloading.</p>
<p><span class="doc-section-title">Parameters:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td>
<code>track</code>
</td>
<td>
<code><span title="unshackle.core.constants.AnyTrack">AnyTrack</span></code>
</td>
<td>
<div class="doc-md-description">
<p>The downloaded Track object.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
</tbody>
</table>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-736">736</a></span>
<span class="normal"><a href="#__codelineno-0-737">737</a></span>
<span class="normal"><a href="#__codelineno-0-738">738</a></span>
<span class="normal"><a href="#__codelineno-0-739">739</a></span>
<span class="normal"><a href="#__codelineno-0-740">740</a></span>
<span class="normal"><a href="#__codelineno-0-741">741</a></span>
<span class="normal"><a href="#__codelineno-0-742">742</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-736"><a id="__codelineno-0-736" name="__codelineno-0-736"></a><span class="k">def</span><span class="w"> </span><span class="nf">on_track_downloaded</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">track</span><span class="p">:</span> <span class="n">AnyTrack</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="__span-0-737"><a id="__codelineno-0-737" name="__codelineno-0-737"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-738"><a id="__codelineno-0-738" name="__codelineno-0-738"></a><span class="sd"> Called when a Track has finished downloading.</span>
</span><span id="__span-0-739"><a id="__codelineno-0-739" name="__codelineno-0-739"></a>
</span><span id="__span-0-740"><a id="__codelineno-0-740" name="__codelineno-0-740"></a><span class="sd"> Parameters:</span>
</span><span id="__span-0-741"><a id="__codelineno-0-741" name="__codelineno-0-741"></a><span class="sd"> track: The downloaded Track object.</span>
</span><span id="__span-0-742"><a id="__codelineno-0-742" name="__codelineno-0-742"></a><span class="sd"> """</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.on_track_decrypted" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">on_track_decrypted</span>
<a href="#unshackle.core.service.Service.on_track_decrypted" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">on_track_decrypted</span><span class="p">(</span><span class="n">track</span><span class="p">,</span> <span class="n">drm</span><span class="p">,</span> <span class="n">segment</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Called when a Track has finished decrypting.</p>
<p><span class="doc-section-title">Parameters:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td>
<code>track</code>
</td>
<td>
<code><span title="unshackle.core.constants.AnyTrack">AnyTrack</span></code>
</td>
<td>
<div class="doc-md-description">
<p>The decrypted Track object.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>drm</code>
</td>
<td>
<code><span title="unshackle.core.drm.DRM_T">DRM_T</span></code>
</td>
<td>
<div class="doc-md-description">
<p>The DRM object it decrypted with.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
<tr class="doc-section-item">
<td>
<code>segment</code>
</td>
<td>
<code><span title="typing.Optional">Optional</span>[<span title="m3u8.Segment">Segment</span>]</code>
</td>
<td>
<div class="doc-md-description">
<p>The decrypted HLS segment information. None for DASH and ISM tracks and
for an HLS track that merged during the download (merge_segments).</p>
</div>
</td>
<td>
<code>None</code>
</td>
</tr>
</tbody>
</table>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-744">744</a></span>
<span class="normal"><a href="#__codelineno-0-745">745</a></span>
<span class="normal"><a href="#__codelineno-0-746">746</a></span>
<span class="normal"><a href="#__codelineno-0-747">747</a></span>
<span class="normal"><a href="#__codelineno-0-748">748</a></span>
<span class="normal"><a href="#__codelineno-0-749">749</a></span>
<span class="normal"><a href="#__codelineno-0-750">750</a></span>
<span class="normal"><a href="#__codelineno-0-751">751</a></span>
<span class="normal"><a href="#__codelineno-0-752">752</a></span>
<span class="normal"><a href="#__codelineno-0-753">753</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-744"><a id="__codelineno-0-744" name="__codelineno-0-744"></a><span class="k">def</span><span class="w"> </span><span class="nf">on_track_decrypted</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">track</span><span class="p">:</span> <span class="n">AnyTrack</span><span class="p">,</span> <span class="n">drm</span><span class="p">:</span> <span class="n">DRM_T</span><span class="p">,</span> <span class="n">segment</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">m3u8</span><span class="o">.</span><span class="n">Segment</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="__span-0-745"><a id="__codelineno-0-745" name="__codelineno-0-745"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-746"><a id="__codelineno-0-746" name="__codelineno-0-746"></a><span class="sd"> Called when a Track has finished decrypting.</span>
</span><span id="__span-0-747"><a id="__codelineno-0-747" name="__codelineno-0-747"></a>
</span><span id="__span-0-748"><a id="__codelineno-0-748" name="__codelineno-0-748"></a><span class="sd"> Parameters:</span>
</span><span id="__span-0-749"><a id="__codelineno-0-749" name="__codelineno-0-749"></a><span class="sd"> track: The decrypted Track object.</span>
</span><span id="__span-0-750"><a id="__codelineno-0-750" name="__codelineno-0-750"></a><span class="sd"> drm: The DRM object it decrypted with.</span>
</span><span id="__span-0-751"><a id="__codelineno-0-751" name="__codelineno-0-751"></a><span class="sd"> segment: The decrypted HLS segment information. None for DASH and ISM tracks and</span>
</span><span id="__span-0-752"><a id="__codelineno-0-752" name="__codelineno-0-752"></a><span class="sd"> for an HLS track that merged during the download (merge_segments).</span>
</span><span id="__span-0-753"><a id="__codelineno-0-753" name="__codelineno-0-753"></a><span class="sd"> """</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.on_track_repacked" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">on_track_repacked</span>
<a href="#unshackle.core.service.Service.on_track_repacked" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">on_track_repacked</span><span class="p">(</span><span class="n">track</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Called when a Track has finished repacking.</p>
<p><span class="doc-section-title">Parameters:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td>
<code>track</code>
</td>
<td>
<code><span title="unshackle.core.constants.AnyTrack">AnyTrack</span></code>
</td>
<td>
<div class="doc-md-description">
<p>The repacked Track object.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
</tbody>
</table>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-755">755</a></span>
<span class="normal"><a href="#__codelineno-0-756">756</a></span>
<span class="normal"><a href="#__codelineno-0-757">757</a></span>
<span class="normal"><a href="#__codelineno-0-758">758</a></span>
<span class="normal"><a href="#__codelineno-0-759">759</a></span>
<span class="normal"><a href="#__codelineno-0-760">760</a></span>
<span class="normal"><a href="#__codelineno-0-761">761</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-755"><a id="__codelineno-0-755" name="__codelineno-0-755"></a><span class="k">def</span><span class="w"> </span><span class="nf">on_track_repacked</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">track</span><span class="p">:</span> <span class="n">AnyTrack</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="__span-0-756"><a id="__codelineno-0-756" name="__codelineno-0-756"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-757"><a id="__codelineno-0-757" name="__codelineno-0-757"></a><span class="sd"> Called when a Track has finished repacking.</span>
</span><span id="__span-0-758"><a id="__codelineno-0-758" name="__codelineno-0-758"></a>
</span><span id="__span-0-759"><a id="__codelineno-0-759" name="__codelineno-0-759"></a><span class="sd"> Parameters:</span>
</span><span id="__span-0-760"><a id="__codelineno-0-760" name="__codelineno-0-760"></a><span class="sd"> track: The repacked Track object.</span>
</span><span id="__span-0-761"><a id="__codelineno-0-761" name="__codelineno-0-761"></a><span class="sd"> """</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h3 id="unshackle.core.service.Service.on_track_multiplex" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-method"></code> <span class="doc doc-object-name doc-function-name">on_track_multiplex</span>
<a href="#unshackle.core.service.Service.on_track_multiplex" class="headerlink" title="Permanent link">&para;</a></h3>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">on_track_multiplex</span><span class="p">(</span><span class="n">track</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Called immediately before unshackle multiplexes a Track into a Container.</p>
<p>Note: Right now unshackle multiplexes only MKV containers. In the future
unshackle can also call this when it multiplexes to other containers like
MP4 with FFmpeg/mp4box.</p>
<p><span class="doc-section-title">Parameters:</span></p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</thead>
<tbody>
<tr class="doc-section-item">
<td>
<code>track</code>
</td>
<td>
<code><span title="unshackle.core.constants.AnyTrack">AnyTrack</span></code>
</td>
<td>
<div class="doc-md-description">
<p>The repacked Track object.</p>
</div>
</td>
<td>
<em>required</em>
</td>
</tr>
</tbody>
</table>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-763">763</a></span>
<span class="normal"><a href="#__codelineno-0-764">764</a></span>
<span class="normal"><a href="#__codelineno-0-765">765</a></span>
<span class="normal"><a href="#__codelineno-0-766">766</a></span>
<span class="normal"><a href="#__codelineno-0-767">767</a></span>
<span class="normal"><a href="#__codelineno-0-768">768</a></span>
<span class="normal"><a href="#__codelineno-0-769">769</a></span>
<span class="normal"><a href="#__codelineno-0-770">770</a></span>
<span class="normal"><a href="#__codelineno-0-771">771</a></span>
<span class="normal"><a href="#__codelineno-0-772">772</a></span>
<span class="normal"><a href="#__codelineno-0-773">773</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-763"><a id="__codelineno-0-763" name="__codelineno-0-763"></a><span class="k">def</span><span class="w"> </span><span class="nf">on_track_multiplex</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">track</span><span class="p">:</span> <span class="n">AnyTrack</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="__span-0-764"><a id="__codelineno-0-764" name="__codelineno-0-764"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-765"><a id="__codelineno-0-765" name="__codelineno-0-765"></a><span class="sd"> Called immediately before unshackle multiplexes a Track into a Container.</span>
</span><span id="__span-0-766"><a id="__codelineno-0-766" name="__codelineno-0-766"></a>
</span><span id="__span-0-767"><a id="__codelineno-0-767" name="__codelineno-0-767"></a><span class="sd"> Note: Right now unshackle multiplexes only MKV containers. In the future</span>
</span><span id="__span-0-768"><a id="__codelineno-0-768" name="__codelineno-0-768"></a><span class="sd"> unshackle can also call this when it multiplexes to other containers like</span>
</span><span id="__span-0-769"><a id="__codelineno-0-769" name="__codelineno-0-769"></a><span class="sd"> MP4 with FFmpeg/mp4box.</span>
</span><span id="__span-0-770"><a id="__codelineno-0-770" name="__codelineno-0-770"></a>
</span><span id="__span-0-771"><a id="__codelineno-0-771" name="__codelineno-0-771"></a><span class="sd"> Parameters:</span>
</span><span id="__span-0-772"><a id="__codelineno-0-772" name="__codelineno-0-772"></a><span class="sd"> track: The repacked Track object.</span>
</span><span id="__span-0-773"><a id="__codelineno-0-773" name="__codelineno-0-773"></a><span class="sd"> """</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
</div>
</div>
</div>
<div class="doc doc-object doc-function">
<h2 id="unshackle.core.service.grow_session_pool" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-function"></code> <span class="doc doc-object-name doc-function-name">grow_session_pool</span>
<a href="#unshackle.core.service.grow_session_pool" class="headerlink" title="Permanent link">&para;</a></h2>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">grow_session_pool</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">size</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Grow a shared requests session's connection pool to <code>size</code> before track downloads start.</p>
<p>The worker threads of every track draw on this one pool, because the downloader never
remounts an HTTP session the caller passes in (see downloaders/requests.py). The pool must hold
<code>downloads * workers</code> connections, or threads queue for a slot instead of reading.
Call this before any download thread exists: the rebuild races with other threads that call
<code>get_adapter</code>. RnetSession does not block on its idle-pool cap, so this function skips it.</p>
<p>Every mounted adapter grows in place, through its own <code>init_poolmanager</code>. A service can
mount an :class:<code>HTTPAdapter</code> subclass, such as <code>SSLCiphers</code>, on any prefix. Mounting a new
adapter over it would drop that subclass state, and its TLS context with it.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-91"> 91</a></span>
<span class="normal"><a href="#__codelineno-0-92"> 92</a></span>
<span class="normal"><a href="#__codelineno-0-93"> 93</a></span>
<span class="normal"><a href="#__codelineno-0-94"> 94</a></span>
<span class="normal"><a href="#__codelineno-0-95"> 95</a></span>
<span class="normal"><a href="#__codelineno-0-96"> 96</a></span>
<span class="normal"><a href="#__codelineno-0-97"> 97</a></span>
<span class="normal"><a href="#__codelineno-0-98"> 98</a></span>
<span class="normal"><a href="#__codelineno-0-99"> 99</a></span>
<span class="normal"><a href="#__codelineno-0-100">100</a></span>
<span class="normal"><a href="#__codelineno-0-101">101</a></span>
<span class="normal"><a href="#__codelineno-0-102">102</a></span>
<span class="normal"><a href="#__codelineno-0-103">103</a></span>
<span class="normal"><a href="#__codelineno-0-104">104</a></span>
<span class="normal"><a href="#__codelineno-0-105">105</a></span>
<span class="normal"><a href="#__codelineno-0-106">106</a></span>
<span class="normal"><a href="#__codelineno-0-107">107</a></span>
<span class="normal"><a href="#__codelineno-0-108">108</a></span>
<span class="normal"><a href="#__codelineno-0-109">109</a></span>
<span class="normal"><a href="#__codelineno-0-110">110</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-91"><a id="__codelineno-0-91" name="__codelineno-0-91"></a><span class="k">def</span><span class="w"> </span><span class="nf">grow_session_pool</span><span class="p">(</span><span class="n">session</span><span class="p">:</span> <span class="n">Any</span><span class="p">,</span> <span class="n">size</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="__span-0-92"><a id="__codelineno-0-92" name="__codelineno-0-92"></a><span class="w"> </span><span class="sd">"""Grow a shared requests session's connection pool to ``size`` before track downloads start.</span>
</span><span id="__span-0-93"><a id="__codelineno-0-93" name="__codelineno-0-93"></a>
</span><span id="__span-0-94"><a id="__codelineno-0-94" name="__codelineno-0-94"></a><span class="sd"> The worker threads of every track draw on this one pool, because the downloader never</span>
</span><span id="__span-0-95"><a id="__codelineno-0-95" name="__codelineno-0-95"></a><span class="sd"> remounts an HTTP session the caller passes in (see downloaders/requests.py). The pool must hold</span>
</span><span id="__span-0-96"><a id="__codelineno-0-96" name="__codelineno-0-96"></a><span class="sd"> ``downloads * workers`` connections, or threads queue for a slot instead of reading.</span>
</span><span id="__span-0-97"><a id="__codelineno-0-97" name="__codelineno-0-97"></a><span class="sd"> Call this before any download thread exists: the rebuild races with other threads that call</span>
</span><span id="__span-0-98"><a id="__codelineno-0-98" name="__codelineno-0-98"></a><span class="sd"> ``get_adapter``. RnetSession does not block on its idle-pool cap, so this function skips it.</span>
</span><span id="__span-0-99"><a id="__codelineno-0-99" name="__codelineno-0-99"></a>
</span><span id="__span-0-100"><a id="__codelineno-0-100" name="__codelineno-0-100"></a><span class="sd"> Every mounted adapter grows in place, through its own ``init_poolmanager``. A service can</span>
</span><span id="__span-0-101"><a id="__codelineno-0-101" name="__codelineno-0-101"></a><span class="sd"> mount an :class:`HTTPAdapter` subclass, such as ``SSLCiphers``, on any prefix. Mounting a new</span>
</span><span id="__span-0-102"><a id="__codelineno-0-102" name="__codelineno-0-102"></a><span class="sd"> adapter over it would drop that subclass state, and its TLS context with it.</span>
</span><span id="__span-0-103"><a id="__codelineno-0-103" name="__codelineno-0-103"></a><span class="sd"> """</span>
</span><span id="__span-0-104"><a id="__codelineno-0-104" name="__codelineno-0-104"></a> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">requests</span><span class="o">.</span><span class="n">Session</span><span class="p">):</span>
</span><span id="__span-0-105"><a id="__codelineno-0-105" name="__codelineno-0-105"></a> <span class="k">return</span>
</span><span id="__span-0-106"><a id="__codelineno-0-106" name="__codelineno-0-106"></a> <span class="k">for</span> <span class="n">adapter</span> <span class="ow">in</span> <span class="p">{</span><span class="nb">id</span><span class="p">(</span><span class="n">a</span><span class="p">):</span> <span class="n">a</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">session</span><span class="o">.</span><span class="n">adapters</span><span class="o">.</span><span class="n">values</span><span class="p">()}</span><span class="o">.</span><span class="n">values</span><span class="p">():</span>
</span><span id="__span-0-107"><a id="__codelineno-0-107" name="__codelineno-0-107"></a> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">adapter</span><span class="p">,</span> <span class="n">HTTPAdapter</span><span class="p">)</span> <span class="ow">or</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">adapter</span><span class="p">,</span> <span class="s2">"_pool_maxsize"</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="n">size</span><span class="p">:</span>
</span><span id="__span-0-108"><a id="__codelineno-0-108" name="__codelineno-0-108"></a> <span class="k">continue</span>
</span><span id="__span-0-109"><a id="__codelineno-0-109" name="__codelineno-0-109"></a> <span class="n">adapter</span><span class="o">.</span><span class="n">init_poolmanager</span><span class="p">(</span><span class="n">size</span><span class="p">,</span> <span class="n">size</span><span class="p">,</span> <span class="n">block</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
</span><span id="__span-0-110"><a id="__codelineno-0-110" name="__codelineno-0-110"></a> <span class="n">adapter</span><span class="o">.</span><span class="n">proxy_manager</span><span class="o">.</span><span class="n">clear</span><span class="p">()</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
<div class="doc doc-object doc-function">
<h2 id="unshackle.core.service.sanitize_proxy_for_log" class="doc doc-heading">
<code class="doc-symbol doc-symbol-heading doc-symbol-function"></code> <span class="doc doc-object-name doc-function-name">sanitize_proxy_for_log</span>
<a href="#unshackle.core.service.sanitize_proxy_for_log" class="headerlink" title="Permanent link">&para;</a></h2>
<div class="language-python doc-signature highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a><span class="nf">sanitize_proxy_for_log</span><span class="p">(</span><span class="n">uri</span><span class="p">,</span> <span class="n">mask_host</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</span></code></pre></div>
<div class="doc doc-contents ">
<p>Sanitise a proxy URI for logs by masking any embedded userinfo (username/password).</p>
<p><code>serve</code> sends these log lines to the client of a remote session, so the mask is
unconditional and debug mode never lifts it. <code>mask_host</code> hides the hostname as
well, for a proxy that came from the user-supplied <code>Basic</code> proxy provider.</p>
<details class="mkdocstrings-source">
<summary>Source code in <code>unshackle/core/service.py</code></summary>
<div class="language-python highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-129">129</a></span>
<span class="normal"><a href="#__codelineno-0-130">130</a></span>
<span class="normal"><a href="#__codelineno-0-131">131</a></span>
<span class="normal"><a href="#__codelineno-0-132">132</a></span>
<span class="normal"><a href="#__codelineno-0-133">133</a></span>
<span class="normal"><a href="#__codelineno-0-134">134</a></span>
<span class="normal"><a href="#__codelineno-0-135">135</a></span>
<span class="normal"><a href="#__codelineno-0-136">136</a></span>
<span class="normal"><a href="#__codelineno-0-137">137</a></span>
<span class="normal"><a href="#__codelineno-0-138">138</a></span>
<span class="normal"><a href="#__codelineno-0-139">139</a></span>
<span class="normal"><a href="#__codelineno-0-140">140</a></span>
<span class="normal"><a href="#__codelineno-0-141">141</a></span></pre></div></td><td class="code"><div><pre><span></span><code><span id="__span-0-129"><a id="__codelineno-0-129" name="__codelineno-0-129"></a><span class="k">def</span><span class="w"> </span><span class="nf">sanitize_proxy_for_log</span><span class="p">(</span><span class="n">uri</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">],</span> <span class="n">mask_host</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="kc">False</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
</span><span id="__span-0-130"><a id="__codelineno-0-130" name="__codelineno-0-130"></a><span class="w"> </span><span class="sd">"""</span>
</span><span id="__span-0-131"><a id="__codelineno-0-131" name="__codelineno-0-131"></a><span class="sd"> Sanitise a proxy URI for logs by masking any embedded userinfo (username/password).</span>
</span><span id="__span-0-132"><a id="__codelineno-0-132" name="__codelineno-0-132"></a>
</span><span id="__span-0-133"><a id="__codelineno-0-133" name="__codelineno-0-133"></a><span class="sd"> ``serve`` sends these log lines to the client of a remote session, so the mask is</span>
</span><span id="__span-0-134"><a id="__codelineno-0-134" name="__codelineno-0-134"></a><span class="sd"> unconditional and debug mode never lifts it. ``mask_host`` hides the hostname as</span>
</span><span id="__span-0-135"><a id="__codelineno-0-135" name="__codelineno-0-135"></a><span class="sd"> well, for a proxy that came from the user-supplied ``Basic`` proxy provider.</span>
</span><span id="__span-0-136"><a id="__codelineno-0-136" name="__codelineno-0-136"></a><span class="sd"> """</span>
</span><span id="__span-0-137"><a id="__codelineno-0-137" name="__codelineno-0-137"></a> <span class="k">if</span> <span class="n">uri</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="__span-0-138"><a id="__codelineno-0-138" name="__codelineno-0-138"></a> <span class="k">return</span> <span class="kc">None</span>
</span><span id="__span-0-139"><a id="__codelineno-0-139" name="__codelineno-0-139"></a> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">uri</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
</span><span id="__span-0-140"><a id="__codelineno-0-140" name="__codelineno-0-140"></a> <span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">uri</span><span class="p">)</span>
</span><span id="__span-0-141"><a id="__codelineno-0-141" name="__codelineno-0-141"></a> <span class="k">return</span> <span class="n">mask_proxy</span><span class="p">(</span><span class="n">uri</span><span class="p">,</span> <span class="n">mask_host</span><span class="o">=</span><span class="n">mask_host</span><span class="p">,</span> <span class="n">allow_debug</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
</span></code></pre></div></td></tr></table></div>
</details>
</div>
</div>
</div>
</div>
</div>
</article>
</div>
<script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script>
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
</div>
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg>
Back to top
</button>
</main>
<footer class="md-footer">
<nav class="md-footer__inner md-grid" aria-label="Footer" >
<a href="../../../dev/rest-api/errors/" class="md-footer__link md-footer__link--prev" aria-label="Previous: Error Responses">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg>
</div>
<div class="md-footer__title">
<span class="md-footer__direction">
Previous
</span>
<div class="md-ellipsis">
Error Responses
</div>
</div>
</a>
<a href="../config/" class="md-footer__link md-footer__link--next" aria-label="Next: Config">
<div class="md-footer__title">
<span class="md-footer__direction">
Next
</span>
<div class="md-ellipsis">
Config
</div>
</div>
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg>
</div>
</a>
</nav>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"annotate": null, "base": "../../..", "features": ["content.code.annotate", "content.code.copy", "content.tabs.link", "content.tooltips", "navigation.footer", "navigation.indexes", "navigation.sections", "navigation.tabs", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../../assets/javascripts/workers/search.2c215733.min.js", "tags": null, "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": null}</script>
<script src="../../../assets/javascripts/bundle.d7400e89.min.js"></script>
</body>
</html>