A loose federation of distributed, typed datasets
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 1891 lines 75 kB view raw
1<!DOCTYPE html> 2<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"><head> 3 4<meta charset="utf-8"> 5<meta name="generator" content="quarto-1.7.34"> 6 7<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"> 8 9 10<title>atmosphereclient – atdata</title> 11<style> 12code{white-space: pre-wrap;} 13span.smallcaps{font-variant: small-caps;} 14div.columns{display: flex; gap: min(4vw, 1.5em);} 15div.column{flex: auto; overflow-x: auto;} 16div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;} 17ul.task-list{list-style: none;} 18ul.task-list li input[type="checkbox"] { 19 width: 0.8em; 20 margin: 0 0.8em 0.2em -1em; /* quarto-specific, see https://github.com/quarto-dev/quarto-cli/issues/4556 */ 21 vertical-align: middle; 22} 23/* CSS for syntax highlighting */ 24html { -webkit-text-size-adjust: 100%; } 25pre > code.sourceCode { white-space: pre; position: relative; } 26pre > code.sourceCode > span { display: inline-block; line-height: 1.25; } 27pre > code.sourceCode > span:empty { height: 1.2em; } 28.sourceCode { overflow: visible; } 29code.sourceCode > span { color: inherit; text-decoration: inherit; } 30div.sourceCode { margin: 1em 0; } 31pre.sourceCode { margin: 0; } 32@media screen { 33div.sourceCode { overflow: auto; } 34} 35@media print { 36pre > code.sourceCode { white-space: pre-wrap; } 37pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; } 38} 39pre.numberSource code 40 { counter-reset: source-line 0; } 41pre.numberSource code > span 42 { position: relative; left: -4em; counter-increment: source-line; } 43pre.numberSource code > span > a:first-child::before 44 { content: counter(source-line); 45 position: relative; left: -1em; text-align: right; vertical-align: baseline; 46 border: none; display: inline-block; 47 -webkit-touch-callout: none; -webkit-user-select: none; 48 -khtml-user-select: none; -moz-user-select: none; 49 -ms-user-select: none; user-select: none; 50 padding: 0 4px; width: 4em; 51 } 52pre.numberSource { margin-left: 3em; padding-left: 4px; } 53div.sourceCode 54 { } 55@media screen { 56pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; } 57} 58</style> 59 60 61<script src="../site_libs/quarto-nav/quarto-nav.js"></script> 62<script src="../site_libs/quarto-nav/headroom.min.js"></script> 63<script src="../site_libs/clipboard/clipboard.min.js"></script> 64<script src="../site_libs/quarto-search/autocomplete.umd.js"></script> 65<script src="../site_libs/quarto-search/fuse.min.js"></script> 66<script src="../site_libs/quarto-search/quarto-search.js"></script> 67<meta name="quarto:offset" content="../"> 68<script src="../site_libs/quarto-html/quarto.js" type="module"></script> 69<script src="../site_libs/quarto-html/tabsets/tabsets.js" type="module"></script> 70<script src="../site_libs/quarto-html/popper.min.js"></script> 71<script src="../site_libs/quarto-html/tippy.umd.min.js"></script> 72<script src="../site_libs/quarto-html/anchor.min.js"></script> 73<link href="../site_libs/quarto-html/tippy.css" rel="stylesheet"> 74<link href="../site_libs/quarto-html/quarto-syntax-highlighting-9582434199d49cc9e91654cdeeb4866b.css" rel="stylesheet" class="quarto-color-scheme" id="quarto-text-highlighting-styles"> 75<link href="../site_libs/quarto-html/quarto-syntax-highlighting-dark-8dcd8563ea6803ab7cbb3d71ca5772e1.css" rel="stylesheet" class="quarto-color-scheme quarto-color-alternate" id="quarto-text-highlighting-styles"> 76<link href="../site_libs/quarto-html/quarto-syntax-highlighting-9582434199d49cc9e91654cdeeb4866b.css" rel="stylesheet" class="quarto-color-scheme-extra" id="quarto-text-highlighting-styles"> 77<script src="../site_libs/bootstrap/bootstrap.min.js"></script> 78<link href="../site_libs/bootstrap/bootstrap-icons.css" rel="stylesheet"> 79<link href="../site_libs/bootstrap/bootstrap-62bce24ca844314e7bb1a34dbdfe05cc.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme" id="quarto-bootstrap" data-mode="light"> 80<link href="../site_libs/bootstrap/bootstrap-dark-7964ffd8887b0991fe8d71c6c8bc75d6.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme quarto-color-alternate" id="quarto-bootstrap" data-mode="dark"> 81<link href="../site_libs/bootstrap/bootstrap-62bce24ca844314e7bb1a34dbdfe05cc.min.css" rel="stylesheet" append-hash="true" class="quarto-color-scheme-extra" id="quarto-bootstrap" data-mode="light"> 82<script id="quarto-search-options" type="application/json">{ 83 "location": "navbar", 84 "copy-button": false, 85 "collapse-after": 3, 86 "panel-placement": "end", 87 "type": "overlay", 88 "limit": 50, 89 "keyboard-shortcut": [ 90 "f", 91 "/", 92 "s" 93 ], 94 "show-item-context": false, 95 "language": { 96 "search-no-results-text": "No results", 97 "search-matching-documents-text": "matching documents", 98 "search-copy-link-title": "Copy link to search", 99 "search-hide-matches-text": "Hide additional matches", 100 "search-more-match-text": "more match in this document", 101 "search-more-matches-text": "more matches in this document", 102 "search-clear-button-title": "Clear", 103 "search-text-placeholder": "", 104 "search-detached-cancel-button-title": "Cancel", 105 "search-submit-button-title": "Submit", 106 "search-label": "Search" 107 } 108}</script> 109 110 111<link rel="stylesheet" href="../assets/styles.css"> 112</head> 113 114<body class="nav-fixed quarto-light"><script id="quarto-html-before-body" type="application/javascript"> 115 const toggleBodyColorMode = (bsSheetEl) => { 116 const mode = bsSheetEl.getAttribute("data-mode"); 117 const bodyEl = window.document.querySelector("body"); 118 if (mode === "dark") { 119 bodyEl.classList.add("quarto-dark"); 120 bodyEl.classList.remove("quarto-light"); 121 } else { 122 bodyEl.classList.add("quarto-light"); 123 bodyEl.classList.remove("quarto-dark"); 124 } 125 } 126 const toggleBodyColorPrimary = () => { 127 const bsSheetEl = window.document.querySelector("link#quarto-bootstrap:not([rel=disabled-stylesheet])"); 128 if (bsSheetEl) { 129 toggleBodyColorMode(bsSheetEl); 130 } 131 } 132 const setColorSchemeToggle = (alternate) => { 133 const toggles = window.document.querySelectorAll('.quarto-color-scheme-toggle'); 134 for (let i=0; i < toggles.length; i++) { 135 const toggle = toggles[i]; 136 if (toggle) { 137 if (alternate) { 138 toggle.classList.add("alternate"); 139 } else { 140 toggle.classList.remove("alternate"); 141 } 142 } 143 } 144 }; 145 const toggleColorMode = (alternate) => { 146 // Switch the stylesheets 147 const primaryStylesheets = window.document.querySelectorAll('link.quarto-color-scheme:not(.quarto-color-alternate)'); 148 const alternateStylesheets = window.document.querySelectorAll('link.quarto-color-scheme.quarto-color-alternate'); 149 manageTransitions('#quarto-margin-sidebar .nav-link', false); 150 if (alternate) { 151 // note: dark is layered on light, we don't disable primary! 152 enableStylesheet(alternateStylesheets); 153 for (const sheetNode of alternateStylesheets) { 154 if (sheetNode.id === "quarto-bootstrap") { 155 toggleBodyColorMode(sheetNode); 156 } 157 } 158 } else { 159 disableStylesheet(alternateStylesheets); 160 enableStylesheet(primaryStylesheets) 161 toggleBodyColorPrimary(); 162 } 163 manageTransitions('#quarto-margin-sidebar .nav-link', true); 164 // Switch the toggles 165 setColorSchemeToggle(alternate) 166 // Hack to workaround the fact that safari doesn't 167 // properly recolor the scrollbar when toggling (#1455) 168 if (navigator.userAgent.indexOf('Safari') > 0 && navigator.userAgent.indexOf('Chrome') == -1) { 169 manageTransitions("body", false); 170 window.scrollTo(0, 1); 171 setTimeout(() => { 172 window.scrollTo(0, 0); 173 manageTransitions("body", true); 174 }, 40); 175 } 176 } 177 const disableStylesheet = (stylesheets) => { 178 for (let i=0; i < stylesheets.length; i++) { 179 const stylesheet = stylesheets[i]; 180 stylesheet.rel = 'disabled-stylesheet'; 181 } 182 } 183 const enableStylesheet = (stylesheets) => { 184 for (let i=0; i < stylesheets.length; i++) { 185 const stylesheet = stylesheets[i]; 186 if(stylesheet.rel !== 'stylesheet') { // for Chrome, which will still FOUC without this check 187 stylesheet.rel = 'stylesheet'; 188 } 189 } 190 } 191 const manageTransitions = (selector, allowTransitions) => { 192 const els = window.document.querySelectorAll(selector); 193 for (let i=0; i < els.length; i++) { 194 const el = els[i]; 195 if (allowTransitions) { 196 el.classList.remove('notransition'); 197 } else { 198 el.classList.add('notransition'); 199 } 200 } 201 } 202 const isFileUrl = () => { 203 return window.location.protocol === 'file:'; 204 } 205 const hasAlternateSentinel = () => { 206 let styleSentinel = getColorSchemeSentinel(); 207 if (styleSentinel !== null) { 208 return styleSentinel === "alternate"; 209 } else { 210 return false; 211 } 212 } 213 const setStyleSentinel = (alternate) => { 214 const value = alternate ? "alternate" : "default"; 215 if (!isFileUrl()) { 216 window.localStorage.setItem("quarto-color-scheme", value); 217 } else { 218 localAlternateSentinel = value; 219 } 220 } 221 const getColorSchemeSentinel = () => { 222 if (!isFileUrl()) { 223 const storageValue = window.localStorage.getItem("quarto-color-scheme"); 224 return storageValue != null ? storageValue : localAlternateSentinel; 225 } else { 226 return localAlternateSentinel; 227 } 228 } 229 const toggleGiscusIfUsed = (isAlternate, darkModeDefault) => { 230 const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light'; 231 const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark'; 232 let newTheme = ''; 233 if(authorPrefersDark) { 234 newTheme = isAlternate ? baseTheme : alternateTheme; 235 } else { 236 newTheme = isAlternate ? alternateTheme : baseTheme; 237 } 238 const changeGiscusTheme = () => { 239 // From: https://github.com/giscus/giscus/issues/336 240 const sendMessage = (message) => { 241 const iframe = document.querySelector('iframe.giscus-frame'); 242 if (!iframe) return; 243 iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app'); 244 } 245 sendMessage({ 246 setConfig: { 247 theme: newTheme 248 } 249 }); 250 } 251 const isGiscussLoaded = window.document.querySelector('iframe.giscus-frame') !== null; 252 if (isGiscussLoaded) { 253 changeGiscusTheme(); 254 } 255 }; 256 const authorPrefersDark = false; 257 const darkModeDefault = authorPrefersDark; 258 document.querySelector('link#quarto-text-highlighting-styles.quarto-color-scheme-extra').rel = 'disabled-stylesheet'; 259 document.querySelector('link#quarto-bootstrap.quarto-color-scheme-extra').rel = 'disabled-stylesheet'; 260 let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default'; 261 // Dark / light mode switch 262 window.quartoToggleColorScheme = () => { 263 // Read the current dark / light value 264 let toAlternate = !hasAlternateSentinel(); 265 toggleColorMode(toAlternate); 266 setStyleSentinel(toAlternate); 267 toggleGiscusIfUsed(toAlternate, darkModeDefault); 268 window.dispatchEvent(new Event('resize')); 269 }; 270 // Switch to dark mode if need be 271 if (hasAlternateSentinel()) { 272 toggleColorMode(true); 273 } else { 274 toggleColorMode(false); 275 } 276 </script> 277 278<div id="quarto-search-results"></div> 279 <header id="quarto-header" class="headroom fixed-top"> 280 <nav class="navbar navbar-expand-lg " data-bs-theme="dark"> 281 <div class="navbar-container container-fluid"> 282 <div class="navbar-brand-container mx-auto"> 283 <a class="navbar-brand" href="../index.html"> 284 <span class="navbar-title">atdata</span> 285 </a> 286 </div> 287 <div id="quarto-search" class="" title="Search"></div> 288 <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" role="menu" aria-expanded="false" aria-label="Toggle navigation" onclick="if (window.quartoToggleHeadroom) { window.quartoToggleHeadroom(); }"> 289 <span class="navbar-toggler-icon"></span> 290</button> 291 <div class="collapse navbar-collapse" id="navbarCollapse"> 292 <ul class="navbar-nav navbar-nav-scroll me-auto"> 293 <li class="nav-item"> 294 <a class="nav-link" href="../index.html"> 295<span class="menu-text">Guide</span></a> 296 </li> 297 <li class="nav-item dropdown "> 298 <a class="nav-link dropdown-toggle" href="#" id="nav-menu-tutorials" role="link" data-bs-toggle="dropdown" aria-expanded="false"> 299 <span class="menu-text">Tutorials</span> 300 </a> 301 <ul class="dropdown-menu" aria-labelledby="nav-menu-tutorials"> 302 <li> 303 <a class="dropdown-item" href="../tutorials/quickstart.html"> 304 <span class="dropdown-text">Quick Start</span></a> 305 </li> 306 <li> 307 <a class="dropdown-item" href="../tutorials/local-workflow.html"> 308 <span class="dropdown-text">Local Workflow</span></a> 309 </li> 310 <li> 311 <a class="dropdown-item" href="../tutorials/atmosphere.html"> 312 <span class="dropdown-text">Atmosphere Publishing</span></a> 313 </li> 314 <li> 315 <a class="dropdown-item" href="../tutorials/promotion.html"> 316 <span class="dropdown-text">Promotion Workflow</span></a> 317 </li> 318 </ul> 319 </li> 320 <li class="nav-item dropdown "> 321 <a class="nav-link dropdown-toggle" href="#" id="nav-menu-reference" role="link" data-bs-toggle="dropdown" aria-expanded="false"> 322 <span class="menu-text">Reference</span> 323 </a> 324 <ul class="dropdown-menu" aria-labelledby="nav-menu-reference"> 325 <li> 326 <a class="dropdown-item" href="../reference/architecture.html"> 327 <span class="dropdown-text">Architecture Overview</span></a> 328 </li> 329 <li> 330 <a class="dropdown-item" href="../reference/packable-samples.html"> 331 <span class="dropdown-text">Packable Samples</span></a> 332 </li> 333 <li> 334 <a class="dropdown-item" href="../reference/datasets.html"> 335 <span class="dropdown-text">Datasets</span></a> 336 </li> 337 <li> 338 <a class="dropdown-item" href="../reference/lenses.html"> 339 <span class="dropdown-text">Lenses</span></a> 340 </li> 341 <li> 342 <a class="dropdown-item" href="../reference/local-storage.html"> 343 <span class="dropdown-text">Local Storage</span></a> 344 </li> 345 <li> 346 <a class="dropdown-item" href="../reference/atmosphere.html"> 347 <span class="dropdown-text">Atmosphere</span></a> 348 </li> 349 <li> 350 <a class="dropdown-item" href="../reference/promotion.html"> 351 <span class="dropdown-text">Promotion</span></a> 352 </li> 353 <li> 354 <a class="dropdown-item" href="../reference/load-dataset.html"> 355 <span class="dropdown-text">load_dataset API</span></a> 356 </li> 357 <li> 358 <a class="dropdown-item" href="../reference/protocols.html"> 359 <span class="dropdown-text">Protocols</span></a> 360 </li> 361 <li> 362 <a class="dropdown-item" href="../reference/uri-spec.html"> 363 <span class="dropdown-text">URI Specification</span></a> 364 </li> 365 <li> 366 <a class="dropdown-item" href="../reference/troubleshooting.html"> 367 <span class="dropdown-text">Troubleshooting &amp; FAQ</span></a> 368 </li> 369 <li> 370 <a class="dropdown-item" href="../reference/deployment.html"> 371 <span class="dropdown-text">Deployment Guide</span></a> 372 </li> 373 </ul> 374 </li> 375 <li class="nav-item"> 376 <a class="nav-link" href="../api/index.html"> 377<span class="menu-text">API</span></a> 378 </li> 379</ul> 380 <ul class="navbar-nav navbar-nav-scroll ms-auto"> 381 <li class="nav-item compact"> 382 <a class="nav-link" href="https://github.com/your-org/atdata"> <i class="bi bi-github" role="img"> 383</i> 384<span class="menu-text"></span></a> 385 </li> 386</ul> 387 </div> <!-- /navcollapse --> 388 <div class="quarto-navbar-tools"> 389 <a href="" class="quarto-color-scheme-toggle quarto-navigation-tool px-1" onclick="window.quartoToggleColorScheme(); return false;" title="Toggle dark mode"><i class="bi"></i></a> 390</div> 391 </div> <!-- /container-fluid --> 392 </nav> 393</header> 394<!-- content --> 395<div id="quarto-content" class="quarto-container page-columns page-rows-contents page-layout-article page-navbar"> 396<!-- sidebar --> 397<!-- margin-sidebar --> 398 <div id="quarto-margin-sidebar" class="sidebar margin-sidebar"> 399 <nav id="TOC" role="doc-toc" class="toc-active"> 400 <h2 id="toc-title">On this page</h2> 401 402 <ul> 403 <li><a href="#atdata.atmosphere.AtmosphereClient" id="toc-atdata.atmosphere.AtmosphereClient" class="nav-link active" data-scroll-target="#atdata.atmosphere.AtmosphereClient">AtmosphereClient</a> 404 <ul class="collapse"> 405 <li><a href="#examples" id="toc-examples" class="nav-link" data-scroll-target="#examples">Examples</a></li> 406 <li><a href="#note" id="toc-note" class="nav-link" data-scroll-target="#note">Note</a></li> 407 <li><a href="#attributes" id="toc-attributes" class="nav-link" data-scroll-target="#attributes">Attributes</a></li> 408 <li><a href="#methods" id="toc-methods" class="nav-link" data-scroll-target="#methods">Methods</a> 409 <ul class="collapse"> 410 <li><a href="#atdata.atmosphere.AtmosphereClient.create_record" id="toc-atdata.atmosphere.AtmosphereClient.create_record" class="nav-link" data-scroll-target="#atdata.atmosphere.AtmosphereClient.create_record">create_record</a></li> 411 <li><a href="#atdata.atmosphere.AtmosphereClient.delete_record" id="toc-atdata.atmosphere.AtmosphereClient.delete_record" class="nav-link" data-scroll-target="#atdata.atmosphere.AtmosphereClient.delete_record">delete_record</a></li> 412 <li><a href="#atdata.atmosphere.AtmosphereClient.export_session" id="toc-atdata.atmosphere.AtmosphereClient.export_session" class="nav-link" data-scroll-target="#atdata.atmosphere.AtmosphereClient.export_session">export_session</a></li> 413 <li><a href="#atdata.atmosphere.AtmosphereClient.get_blob" id="toc-atdata.atmosphere.AtmosphereClient.get_blob" class="nav-link" data-scroll-target="#atdata.atmosphere.AtmosphereClient.get_blob">get_blob</a></li> 414 <li><a href="#atdata.atmosphere.AtmosphereClient.get_blob_url" id="toc-atdata.atmosphere.AtmosphereClient.get_blob_url" class="nav-link" data-scroll-target="#atdata.atmosphere.AtmosphereClient.get_blob_url">get_blob_url</a></li> 415 <li><a href="#atdata.atmosphere.AtmosphereClient.get_record" id="toc-atdata.atmosphere.AtmosphereClient.get_record" class="nav-link" data-scroll-target="#atdata.atmosphere.AtmosphereClient.get_record">get_record</a></li> 416 <li><a href="#atdata.atmosphere.AtmosphereClient.list_datasets" id="toc-atdata.atmosphere.AtmosphereClient.list_datasets" class="nav-link" data-scroll-target="#atdata.atmosphere.AtmosphereClient.list_datasets">list_datasets</a></li> 417 <li><a href="#atdata.atmosphere.AtmosphereClient.list_lenses" id="toc-atdata.atmosphere.AtmosphereClient.list_lenses" class="nav-link" data-scroll-target="#atdata.atmosphere.AtmosphereClient.list_lenses">list_lenses</a></li> 418 <li><a href="#atdata.atmosphere.AtmosphereClient.list_records" id="toc-atdata.atmosphere.AtmosphereClient.list_records" class="nav-link" data-scroll-target="#atdata.atmosphere.AtmosphereClient.list_records">list_records</a></li> 419 <li><a href="#atdata.atmosphere.AtmosphereClient.list_schemas" id="toc-atdata.atmosphere.AtmosphereClient.list_schemas" class="nav-link" data-scroll-target="#atdata.atmosphere.AtmosphereClient.list_schemas">list_schemas</a></li> 420 <li><a href="#atdata.atmosphere.AtmosphereClient.login" id="toc-atdata.atmosphere.AtmosphereClient.login" class="nav-link" data-scroll-target="#atdata.atmosphere.AtmosphereClient.login">login</a></li> 421 <li><a href="#atdata.atmosphere.AtmosphereClient.login_with_session" id="toc-atdata.atmosphere.AtmosphereClient.login_with_session" class="nav-link" data-scroll-target="#atdata.atmosphere.AtmosphereClient.login_with_session">login_with_session</a></li> 422 <li><a href="#atdata.atmosphere.AtmosphereClient.put_record" id="toc-atdata.atmosphere.AtmosphereClient.put_record" class="nav-link" data-scroll-target="#atdata.atmosphere.AtmosphereClient.put_record">put_record</a></li> 423 <li><a href="#atdata.atmosphere.AtmosphereClient.upload_blob" id="toc-atdata.atmosphere.AtmosphereClient.upload_blob" class="nav-link" data-scroll-target="#atdata.atmosphere.AtmosphereClient.upload_blob">upload_blob</a></li> 424 </ul></li> 425 </ul></li> 426 </ul> 427<div class="toc-actions"><ul><li><a href="https://github.com/your-org/atdata/edit/main/api/AtmosphereClient.qmd" class="toc-action"><i class="bi bi-github"></i>Edit this page</a></li><li><a href="https://github.com/your-org/atdata/issues/new" class="toc-action"><i class="bi empty"></i>Report an issue</a></li></ul></div></nav> 428 </div> 429<!-- main --> 430<main class="content" id="quarto-document-content"><header id="title-block-header" class="quarto-title-block"></header> 431 432 433 434 435 436<section id="atdata.atmosphere.AtmosphereClient" class="level1"> 437<h1>AtmosphereClient</h1> 438<div class="sourceCode" id="cb1"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>atmosphere.AtmosphereClient(base_url<span class="op">=</span><span class="va">None</span>, <span class="op">*</span>, _client<span class="op">=</span><span class="va">None</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 439<p>ATProto client wrapper for atdata operations.</p> 440<p>This class wraps the atproto SDK client and provides higher-level methods for working with atdata records (schemas, datasets, lenses).</p> 441<section id="examples" class="level2 doc-section doc-section-examples"> 442<h2 class="doc-section doc-section-examples anchored" data-anchor-id="examples">Examples</h2> 443<div class="sourceCode" id="cb2"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;&gt;&gt;</span> client <span class="op">=</span> AtmosphereClient()</span> 444<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;&gt;&gt;</span> client.login(<span class="st">"alice.bsky.social"</span>, <span class="st">"app-password"</span>)</span> 445<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;&gt;&gt;</span> <span class="bu">print</span>(client.did)</span> 446<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="co">'did:plc:...'</span></span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 447</section> 448<section id="note" class="level2 doc-section doc-section-note"> 449<h2 class="doc-section doc-section-note anchored" data-anchor-id="note">Note</h2> 450<p>The password should be an app-specific password, not your main account password. Create app passwords in your Bluesky account settings.</p> 451</section> 452<section id="attributes" class="level2"> 453<h2 class="anchored" data-anchor-id="attributes">Attributes</h2> 454<table class="caption-top table"> 455<thead> 456<tr class="header"> 457<th>Name</th> 458<th>Description</th> 459</tr> 460</thead> 461<tbody> 462<tr class="odd"> 463<td><a href="#atdata.atmosphere.AtmosphereClient.did">did</a></td> 464<td>Get the DID of the authenticated user.</td> 465</tr> 466<tr class="even"> 467<td><a href="#atdata.atmosphere.AtmosphereClient.handle">handle</a></td> 468<td>Get the handle of the authenticated user.</td> 469</tr> 470<tr class="odd"> 471<td><a href="#atdata.atmosphere.AtmosphereClient.is_authenticated">is_authenticated</a></td> 472<td>Check if the client has a valid session.</td> 473</tr> 474</tbody> 475</table> 476</section> 477<section id="methods" class="level2"> 478<h2 class="anchored" data-anchor-id="methods">Methods</h2> 479<table class="caption-top table"> 480<thead> 481<tr class="header"> 482<th>Name</th> 483<th>Description</th> 484</tr> 485</thead> 486<tbody> 487<tr class="odd"> 488<td><a href="#atdata.atmosphere.AtmosphereClient.create_record">create_record</a></td> 489<td>Create a record in the user’s repository.</td> 490</tr> 491<tr class="even"> 492<td><a href="#atdata.atmosphere.AtmosphereClient.delete_record">delete_record</a></td> 493<td>Delete a record.</td> 494</tr> 495<tr class="odd"> 496<td><a href="#atdata.atmosphere.AtmosphereClient.export_session">export_session</a></td> 497<td>Export the current session for later reuse.</td> 498</tr> 499<tr class="even"> 500<td><a href="#atdata.atmosphere.AtmosphereClient.get_blob">get_blob</a></td> 501<td>Download a blob from a PDS.</td> 502</tr> 503<tr class="odd"> 504<td><a href="#atdata.atmosphere.AtmosphereClient.get_blob_url">get_blob_url</a></td> 505<td>Get the direct URL for fetching a blob.</td> 506</tr> 507<tr class="even"> 508<td><a href="#atdata.atmosphere.AtmosphereClient.get_record">get_record</a></td> 509<td>Fetch a record by AT URI.</td> 510</tr> 511<tr class="odd"> 512<td><a href="#atdata.atmosphere.AtmosphereClient.list_datasets">list_datasets</a></td> 513<td>List dataset records.</td> 514</tr> 515<tr class="even"> 516<td><a href="#atdata.atmosphere.AtmosphereClient.list_lenses">list_lenses</a></td> 517<td>List lens records.</td> 518</tr> 519<tr class="odd"> 520<td><a href="#atdata.atmosphere.AtmosphereClient.list_records">list_records</a></td> 521<td>List records in a collection.</td> 522</tr> 523<tr class="even"> 524<td><a href="#atdata.atmosphere.AtmosphereClient.list_schemas">list_schemas</a></td> 525<td>List schema records.</td> 526</tr> 527<tr class="odd"> 528<td><a href="#atdata.atmosphere.AtmosphereClient.login">login</a></td> 529<td>Authenticate with the ATProto PDS.</td> 530</tr> 531<tr class="even"> 532<td><a href="#atdata.atmosphere.AtmosphereClient.login_with_session">login_with_session</a></td> 533<td>Authenticate using an exported session string.</td> 534</tr> 535<tr class="odd"> 536<td><a href="#atdata.atmosphere.AtmosphereClient.put_record">put_record</a></td> 537<td>Create or update a record at a specific key.</td> 538</tr> 539<tr class="even"> 540<td><a href="#atdata.atmosphere.AtmosphereClient.upload_blob">upload_blob</a></td> 541<td>Upload binary data as a blob to the PDS.</td> 542</tr> 543</tbody> 544</table> 545<section id="atdata.atmosphere.AtmosphereClient.create_record" class="level3"> 546<h3 class="anchored" data-anchor-id="atdata.atmosphere.AtmosphereClient.create_record">create_record</h3> 547<div class="sourceCode" id="cb3"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>atmosphere.AtmosphereClient.create_record(</span> 548<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a> collection,</span> 549<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> record,</span> 550<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> <span class="op">*</span>,</span> 551<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a> rkey<span class="op">=</span><span class="va">None</span>,</span> 552<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> validate<span class="op">=</span><span class="va">False</span>,</span> 553<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 554<p>Create a record in the user’s repository.</p> 555<section id="parameters" class="level4 doc-section doc-section-parameters"> 556<h4 class="doc-section doc-section-parameters anchored" data-anchor-id="parameters">Parameters</h4> 557<table class="caption-top table"> 558<thead> 559<tr class="header"> 560<th>Name</th> 561<th>Type</th> 562<th>Description</th> 563<th>Default</th> 564</tr> 565</thead> 566<tbody> 567<tr class="odd"> 568<td>collection</td> 569<td><a href="`str`">str</a></td> 570<td>The NSID of the record collection (e.g., ‘ac.foundation.dataset.sampleSchema’).</td> 571<td><em>required</em></td> 572</tr> 573<tr class="even"> 574<td>record</td> 575<td><a href="`dict`">dict</a></td> 576<td>The record data. Must include a ‘$type’ field.</td> 577<td><em>required</em></td> 578</tr> 579<tr class="odd"> 580<td>rkey</td> 581<td><a href="`typing.Optional`">Optional</a>[<a href="`str`">str</a>]</td> 582<td>Optional explicit record key. If not provided, a TID is generated.</td> 583<td><code>None</code></td> 584</tr> 585<tr class="even"> 586<td>validate</td> 587<td><a href="`bool`">bool</a></td> 588<td>Whether to validate against the Lexicon schema. Set to False for custom lexicons that the PDS doesn’t know about.</td> 589<td><code>False</code></td> 590</tr> 591</tbody> 592</table> 593</section> 594<section id="returns" class="level4 doc-section doc-section-returns"> 595<h4 class="doc-section doc-section-returns anchored" data-anchor-id="returns">Returns</h4> 596<table class="caption-top table"> 597<thead> 598<tr class="header"> 599<th>Name</th> 600<th>Type</th> 601<th>Description</th> 602</tr> 603</thead> 604<tbody> 605<tr class="odd"> 606<td></td> 607<td><a href="`atdata.atmosphere._types.AtUri`">AtUri</a></td> 608<td>The AT URI of the created record.</td> 609</tr> 610</tbody> 611</table> 612</section> 613<section id="raises" class="level4 doc-section doc-section-raises"> 614<h4 class="doc-section doc-section-raises anchored" data-anchor-id="raises">Raises</h4> 615<table class="caption-top table"> 616<thead> 617<tr class="header"> 618<th>Name</th> 619<th>Type</th> 620<th>Description</th> 621</tr> 622</thead> 623<tbody> 624<tr class="odd"> 625<td></td> 626<td><a href="`ValueError`">ValueError</a></td> 627<td>If not authenticated.</td> 628</tr> 629<tr class="even"> 630<td></td> 631<td><a href="`atproto`">atproto</a>.<a href="`atproto.exceptions`">exceptions</a>.<a href="`atproto.exceptions.AtProtocolError`">AtProtocolError</a></td> 632<td>If record creation fails.</td> 633</tr> 634</tbody> 635</table> 636</section> 637</section> 638<section id="atdata.atmosphere.AtmosphereClient.delete_record" class="level3"> 639<h3 class="anchored" data-anchor-id="atdata.atmosphere.AtmosphereClient.delete_record">delete_record</h3> 640<div class="sourceCode" id="cb4"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>atmosphere.AtmosphereClient.delete_record(uri, <span class="op">*</span>, swap_commit<span class="op">=</span><span class="va">None</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 641<p>Delete a record.</p> 642<section id="parameters-1" class="level4 doc-section doc-section-parameters"> 643<h4 class="doc-section doc-section-parameters anchored" data-anchor-id="parameters-1">Parameters</h4> 644<table class="caption-top table"> 645<thead> 646<tr class="header"> 647<th>Name</th> 648<th>Type</th> 649<th>Description</th> 650<th>Default</th> 651</tr> 652</thead> 653<tbody> 654<tr class="odd"> 655<td>uri</td> 656<td><a href="`str`">str</a> | <a href="`atdata.atmosphere._types.AtUri`">AtUri</a></td> 657<td>The AT URI of the record to delete.</td> 658<td><em>required</em></td> 659</tr> 660<tr class="even"> 661<td>swap_commit</td> 662<td><a href="`typing.Optional`">Optional</a>[<a href="`str`">str</a>]</td> 663<td>Optional CID for compare-and-swap delete.</td> 664<td><code>None</code></td> 665</tr> 666</tbody> 667</table> 668</section> 669<section id="raises-1" class="level4 doc-section doc-section-raises"> 670<h4 class="doc-section doc-section-raises anchored" data-anchor-id="raises-1">Raises</h4> 671<table class="caption-top table"> 672<thead> 673<tr class="header"> 674<th>Name</th> 675<th>Type</th> 676<th>Description</th> 677</tr> 678</thead> 679<tbody> 680<tr class="odd"> 681<td></td> 682<td><a href="`ValueError`">ValueError</a></td> 683<td>If not authenticated.</td> 684</tr> 685<tr class="even"> 686<td></td> 687<td><a href="`atproto`">atproto</a>.<a href="`atproto.exceptions`">exceptions</a>.<a href="`atproto.exceptions.AtProtocolError`">AtProtocolError</a></td> 688<td>If deletion fails.</td> 689</tr> 690</tbody> 691</table> 692</section> 693</section> 694<section id="atdata.atmosphere.AtmosphereClient.export_session" class="level3"> 695<h3 class="anchored" data-anchor-id="atdata.atmosphere.AtmosphereClient.export_session">export_session</h3> 696<div class="sourceCode" id="cb5"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>atmosphere.AtmosphereClient.export_session()</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 697<p>Export the current session for later reuse.</p> 698<section id="returns-1" class="level4 doc-section doc-section-returns"> 699<h4 class="doc-section doc-section-returns anchored" data-anchor-id="returns-1">Returns</h4> 700<table class="caption-top table"> 701<thead> 702<tr class="header"> 703<th>Name</th> 704<th>Type</th> 705<th>Description</th> 706</tr> 707</thead> 708<tbody> 709<tr class="odd"> 710<td></td> 711<td><a href="`str`">str</a></td> 712<td>Session string that can be passed to <code>login_with_session()</code>.</td> 713</tr> 714</tbody> 715</table> 716</section> 717<section id="raises-2" class="level4 doc-section doc-section-raises"> 718<h4 class="doc-section doc-section-raises anchored" data-anchor-id="raises-2">Raises</h4> 719<table class="caption-top table"> 720<thead> 721<tr class="header"> 722<th>Name</th> 723<th>Type</th> 724<th>Description</th> 725</tr> 726</thead> 727<tbody> 728<tr class="odd"> 729<td></td> 730<td><a href="`ValueError`">ValueError</a></td> 731<td>If not authenticated.</td> 732</tr> 733</tbody> 734</table> 735</section> 736</section> 737<section id="atdata.atmosphere.AtmosphereClient.get_blob" class="level3"> 738<h3 class="anchored" data-anchor-id="atdata.atmosphere.AtmosphereClient.get_blob">get_blob</h3> 739<div class="sourceCode" id="cb6"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>atmosphere.AtmosphereClient.get_blob(did, cid)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 740<p>Download a blob from a PDS.</p> 741<p>This resolves the PDS endpoint from the DID document and fetches the blob directly from the PDS.</p> 742<section id="parameters-2" class="level4 doc-section doc-section-parameters"> 743<h4 class="doc-section doc-section-parameters anchored" data-anchor-id="parameters-2">Parameters</h4> 744<table class="caption-top table"> 745<thead> 746<tr class="header"> 747<th>Name</th> 748<th>Type</th> 749<th>Description</th> 750<th>Default</th> 751</tr> 752</thead> 753<tbody> 754<tr class="odd"> 755<td>did</td> 756<td><a href="`str`">str</a></td> 757<td>The DID of the repository containing the blob.</td> 758<td><em>required</em></td> 759</tr> 760<tr class="even"> 761<td>cid</td> 762<td><a href="`str`">str</a></td> 763<td>The CID of the blob.</td> 764<td><em>required</em></td> 765</tr> 766</tbody> 767</table> 768</section> 769<section id="returns-2" class="level4 doc-section doc-section-returns"> 770<h4 class="doc-section doc-section-returns anchored" data-anchor-id="returns-2">Returns</h4> 771<table class="caption-top table"> 772<thead> 773<tr class="header"> 774<th>Name</th> 775<th>Type</th> 776<th>Description</th> 777</tr> 778</thead> 779<tbody> 780<tr class="odd"> 781<td></td> 782<td><a href="`bytes`">bytes</a></td> 783<td>The blob data as bytes.</td> 784</tr> 785</tbody> 786</table> 787</section> 788<section id="raises-3" class="level4 doc-section doc-section-raises"> 789<h4 class="doc-section doc-section-raises anchored" data-anchor-id="raises-3">Raises</h4> 790<table class="caption-top table"> 791<thead> 792<tr class="header"> 793<th>Name</th> 794<th>Type</th> 795<th>Description</th> 796</tr> 797</thead> 798<tbody> 799<tr class="odd"> 800<td></td> 801<td><a href="`ValueError`">ValueError</a></td> 802<td>If PDS endpoint cannot be resolved.</td> 803</tr> 804<tr class="even"> 805<td></td> 806<td><a href="`requests`">requests</a>.<a href="`requests.HTTPError`">HTTPError</a></td> 807<td>If blob fetch fails.</td> 808</tr> 809</tbody> 810</table> 811</section> 812</section> 813<section id="atdata.atmosphere.AtmosphereClient.get_blob_url" class="level3"> 814<h3 class="anchored" data-anchor-id="atdata.atmosphere.AtmosphereClient.get_blob_url">get_blob_url</h3> 815<div class="sourceCode" id="cb7"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>atmosphere.AtmosphereClient.get_blob_url(did, cid)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 816<p>Get the direct URL for fetching a blob.</p> 817<p>This is useful for passing to WebDataset or other HTTP clients.</p> 818<section id="parameters-3" class="level4 doc-section doc-section-parameters"> 819<h4 class="doc-section doc-section-parameters anchored" data-anchor-id="parameters-3">Parameters</h4> 820<table class="caption-top table"> 821<thead> 822<tr class="header"> 823<th>Name</th> 824<th>Type</th> 825<th>Description</th> 826<th>Default</th> 827</tr> 828</thead> 829<tbody> 830<tr class="odd"> 831<td>did</td> 832<td><a href="`str`">str</a></td> 833<td>The DID of the repository containing the blob.</td> 834<td><em>required</em></td> 835</tr> 836<tr class="even"> 837<td>cid</td> 838<td><a href="`str`">str</a></td> 839<td>The CID of the blob.</td> 840<td><em>required</em></td> 841</tr> 842</tbody> 843</table> 844</section> 845<section id="returns-3" class="level4 doc-section doc-section-returns"> 846<h4 class="doc-section doc-section-returns anchored" data-anchor-id="returns-3">Returns</h4> 847<table class="caption-top table"> 848<thead> 849<tr class="header"> 850<th>Name</th> 851<th>Type</th> 852<th>Description</th> 853</tr> 854</thead> 855<tbody> 856<tr class="odd"> 857<td></td> 858<td><a href="`str`">str</a></td> 859<td>The full URL for fetching the blob.</td> 860</tr> 861</tbody> 862</table> 863</section> 864<section id="raises-4" class="level4 doc-section doc-section-raises"> 865<h4 class="doc-section doc-section-raises anchored" data-anchor-id="raises-4">Raises</h4> 866<table class="caption-top table"> 867<thead> 868<tr class="header"> 869<th>Name</th> 870<th>Type</th> 871<th>Description</th> 872</tr> 873</thead> 874<tbody> 875<tr class="odd"> 876<td></td> 877<td><a href="`ValueError`">ValueError</a></td> 878<td>If PDS endpoint cannot be resolved.</td> 879</tr> 880</tbody> 881</table> 882</section> 883</section> 884<section id="atdata.atmosphere.AtmosphereClient.get_record" class="level3"> 885<h3 class="anchored" data-anchor-id="atdata.atmosphere.AtmosphereClient.get_record">get_record</h3> 886<div class="sourceCode" id="cb8"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>atmosphere.AtmosphereClient.get_record(uri)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 887<p>Fetch a record by AT URI.</p> 888<section id="parameters-4" class="level4 doc-section doc-section-parameters"> 889<h4 class="doc-section doc-section-parameters anchored" data-anchor-id="parameters-4">Parameters</h4> 890<table class="caption-top table"> 891<thead> 892<tr class="header"> 893<th>Name</th> 894<th>Type</th> 895<th>Description</th> 896<th>Default</th> 897</tr> 898</thead> 899<tbody> 900<tr class="odd"> 901<td>uri</td> 902<td><a href="`str`">str</a> | <a href="`atdata.atmosphere._types.AtUri`">AtUri</a></td> 903<td>The AT URI of the record.</td> 904<td><em>required</em></td> 905</tr> 906</tbody> 907</table> 908</section> 909<section id="returns-4" class="level4 doc-section doc-section-returns"> 910<h4 class="doc-section doc-section-returns anchored" data-anchor-id="returns-4">Returns</h4> 911<table class="caption-top table"> 912<thead> 913<tr class="header"> 914<th>Name</th> 915<th>Type</th> 916<th>Description</th> 917</tr> 918</thead> 919<tbody> 920<tr class="odd"> 921<td></td> 922<td><a href="`dict`">dict</a></td> 923<td>The record data as a dictionary.</td> 924</tr> 925</tbody> 926</table> 927</section> 928<section id="raises-5" class="level4 doc-section doc-section-raises"> 929<h4 class="doc-section doc-section-raises anchored" data-anchor-id="raises-5">Raises</h4> 930<table class="caption-top table"> 931<thead> 932<tr class="header"> 933<th>Name</th> 934<th>Type</th> 935<th>Description</th> 936</tr> 937</thead> 938<tbody> 939<tr class="odd"> 940<td></td> 941<td><a href="`atproto`">atproto</a>.<a href="`atproto.exceptions`">exceptions</a>.<a href="`atproto.exceptions.AtProtocolError`">AtProtocolError</a></td> 942<td>If record not found.</td> 943</tr> 944</tbody> 945</table> 946</section> 947</section> 948<section id="atdata.atmosphere.AtmosphereClient.list_datasets" class="level3"> 949<h3 class="anchored" data-anchor-id="atdata.atmosphere.AtmosphereClient.list_datasets">list_datasets</h3> 950<div class="sourceCode" id="cb9"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>atmosphere.AtmosphereClient.list_datasets(repo<span class="op">=</span><span class="va">None</span>, limit<span class="op">=</span><span class="dv">100</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 951<p>List dataset records.</p> 952<section id="parameters-5" class="level4 doc-section doc-section-parameters"> 953<h4 class="doc-section doc-section-parameters anchored" data-anchor-id="parameters-5">Parameters</h4> 954<table class="caption-top table"> 955<thead> 956<tr class="header"> 957<th>Name</th> 958<th>Type</th> 959<th>Description</th> 960<th>Default</th> 961</tr> 962</thead> 963<tbody> 964<tr class="odd"> 965<td>repo</td> 966<td><a href="`typing.Optional`">Optional</a>[<a href="`str`">str</a>]</td> 967<td>The DID to query. Defaults to authenticated user.</td> 968<td><code>None</code></td> 969</tr> 970<tr class="even"> 971<td>limit</td> 972<td><a href="`int`">int</a></td> 973<td>Maximum number to return.</td> 974<td><code>100</code></td> 975</tr> 976</tbody> 977</table> 978</section> 979<section id="returns-5" class="level4 doc-section doc-section-returns"> 980<h4 class="doc-section doc-section-returns anchored" data-anchor-id="returns-5">Returns</h4> 981<table class="caption-top table"> 982<thead> 983<tr class="header"> 984<th>Name</th> 985<th>Type</th> 986<th>Description</th> 987</tr> 988</thead> 989<tbody> 990<tr class="odd"> 991<td></td> 992<td><a href="`list`">list</a>[<a href="`dict`">dict</a>]</td> 993<td>List of dataset records.</td> 994</tr> 995</tbody> 996</table> 997</section> 998</section> 999<section id="atdata.atmosphere.AtmosphereClient.list_lenses" class="level3"> 1000<h3 class="anchored" data-anchor-id="atdata.atmosphere.AtmosphereClient.list_lenses">list_lenses</h3> 1001<div class="sourceCode" id="cb10"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>atmosphere.AtmosphereClient.list_lenses(repo<span class="op">=</span><span class="va">None</span>, limit<span class="op">=</span><span class="dv">100</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 1002<p>List lens records.</p> 1003<section id="parameters-6" class="level4 doc-section doc-section-parameters"> 1004<h4 class="doc-section doc-section-parameters anchored" data-anchor-id="parameters-6">Parameters</h4> 1005<table class="caption-top table"> 1006<thead> 1007<tr class="header"> 1008<th>Name</th> 1009<th>Type</th> 1010<th>Description</th> 1011<th>Default</th> 1012</tr> 1013</thead> 1014<tbody> 1015<tr class="odd"> 1016<td>repo</td> 1017<td><a href="`typing.Optional`">Optional</a>[<a href="`str`">str</a>]</td> 1018<td>The DID to query. Defaults to authenticated user.</td> 1019<td><code>None</code></td> 1020</tr> 1021<tr class="even"> 1022<td>limit</td> 1023<td><a href="`int`">int</a></td> 1024<td>Maximum number to return.</td> 1025<td><code>100</code></td> 1026</tr> 1027</tbody> 1028</table> 1029</section> 1030<section id="returns-6" class="level4 doc-section doc-section-returns"> 1031<h4 class="doc-section doc-section-returns anchored" data-anchor-id="returns-6">Returns</h4> 1032<table class="caption-top table"> 1033<thead> 1034<tr class="header"> 1035<th>Name</th> 1036<th>Type</th> 1037<th>Description</th> 1038</tr> 1039</thead> 1040<tbody> 1041<tr class="odd"> 1042<td></td> 1043<td><a href="`list`">list</a>[<a href="`dict`">dict</a>]</td> 1044<td>List of lens records.</td> 1045</tr> 1046</tbody> 1047</table> 1048</section> 1049</section> 1050<section id="atdata.atmosphere.AtmosphereClient.list_records" class="level3"> 1051<h3 class="anchored" data-anchor-id="atdata.atmosphere.AtmosphereClient.list_records">list_records</h3> 1052<div class="sourceCode" id="cb11"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>atmosphere.AtmosphereClient.list_records(</span> 1053<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a> collection,</span> 1054<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a> <span class="op">*</span>,</span> 1055<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a> repo<span class="op">=</span><span class="va">None</span>,</span> 1056<span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a> limit<span class="op">=</span><span class="dv">100</span>,</span> 1057<span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a> cursor<span class="op">=</span><span class="va">None</span>,</span> 1058<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 1059<p>List records in a collection.</p> 1060<section id="parameters-7" class="level4 doc-section doc-section-parameters"> 1061<h4 class="doc-section doc-section-parameters anchored" data-anchor-id="parameters-7">Parameters</h4> 1062<table class="caption-top table"> 1063<thead> 1064<tr class="header"> 1065<th>Name</th> 1066<th>Type</th> 1067<th>Description</th> 1068<th>Default</th> 1069</tr> 1070</thead> 1071<tbody> 1072<tr class="odd"> 1073<td>collection</td> 1074<td><a href="`str`">str</a></td> 1075<td>The NSID of the record collection.</td> 1076<td><em>required</em></td> 1077</tr> 1078<tr class="even"> 1079<td>repo</td> 1080<td><a href="`typing.Optional`">Optional</a>[<a href="`str`">str</a>]</td> 1081<td>The DID of the repository to query. Defaults to the authenticated user’s repository.</td> 1082<td><code>None</code></td> 1083</tr> 1084<tr class="odd"> 1085<td>limit</td> 1086<td><a href="`int`">int</a></td> 1087<td>Maximum number of records to return (default 100).</td> 1088<td><code>100</code></td> 1089</tr> 1090<tr class="even"> 1091<td>cursor</td> 1092<td><a href="`typing.Optional`">Optional</a>[<a href="`str`">str</a>]</td> 1093<td>Pagination cursor from a previous call.</td> 1094<td><code>None</code></td> 1095</tr> 1096</tbody> 1097</table> 1098</section> 1099<section id="returns-7" class="level4 doc-section doc-section-returns"> 1100<h4 class="doc-section doc-section-returns anchored" data-anchor-id="returns-7">Returns</h4> 1101<table class="caption-top table"> 1102<thead> 1103<tr class="header"> 1104<th>Name</th> 1105<th>Type</th> 1106<th>Description</th> 1107</tr> 1108</thead> 1109<tbody> 1110<tr class="odd"> 1111<td></td> 1112<td><a href="`list`">list</a>[<a href="`dict`">dict</a>]</td> 1113<td>A tuple of (records, next_cursor). The cursor is None if there</td> 1114</tr> 1115<tr class="even"> 1116<td></td> 1117<td><a href="`typing.Optional`">Optional</a>[<a href="`str`">str</a>]</td> 1118<td>are no more records.</td> 1119</tr> 1120</tbody> 1121</table> 1122</section> 1123<section id="raises-6" class="level4 doc-section doc-section-raises"> 1124<h4 class="doc-section doc-section-raises anchored" data-anchor-id="raises-6">Raises</h4> 1125<table class="caption-top table"> 1126<thead> 1127<tr class="header"> 1128<th>Name</th> 1129<th>Type</th> 1130<th>Description</th> 1131</tr> 1132</thead> 1133<tbody> 1134<tr class="odd"> 1135<td></td> 1136<td><a href="`ValueError`">ValueError</a></td> 1137<td>If repo is None and not authenticated.</td> 1138</tr> 1139</tbody> 1140</table> 1141</section> 1142</section> 1143<section id="atdata.atmosphere.AtmosphereClient.list_schemas" class="level3"> 1144<h3 class="anchored" data-anchor-id="atdata.atmosphere.AtmosphereClient.list_schemas">list_schemas</h3> 1145<div class="sourceCode" id="cb12"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>atmosphere.AtmosphereClient.list_schemas(repo<span class="op">=</span><span class="va">None</span>, limit<span class="op">=</span><span class="dv">100</span>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 1146<p>List schema records.</p> 1147<section id="parameters-8" class="level4 doc-section doc-section-parameters"> 1148<h4 class="doc-section doc-section-parameters anchored" data-anchor-id="parameters-8">Parameters</h4> 1149<table class="caption-top table"> 1150<thead> 1151<tr class="header"> 1152<th>Name</th> 1153<th>Type</th> 1154<th>Description</th> 1155<th>Default</th> 1156</tr> 1157</thead> 1158<tbody> 1159<tr class="odd"> 1160<td>repo</td> 1161<td><a href="`typing.Optional`">Optional</a>[<a href="`str`">str</a>]</td> 1162<td>The DID to query. Defaults to authenticated user.</td> 1163<td><code>None</code></td> 1164</tr> 1165<tr class="even"> 1166<td>limit</td> 1167<td><a href="`int`">int</a></td> 1168<td>Maximum number to return.</td> 1169<td><code>100</code></td> 1170</tr> 1171</tbody> 1172</table> 1173</section> 1174<section id="returns-8" class="level4 doc-section doc-section-returns"> 1175<h4 class="doc-section doc-section-returns anchored" data-anchor-id="returns-8">Returns</h4> 1176<table class="caption-top table"> 1177<thead> 1178<tr class="header"> 1179<th>Name</th> 1180<th>Type</th> 1181<th>Description</th> 1182</tr> 1183</thead> 1184<tbody> 1185<tr class="odd"> 1186<td></td> 1187<td><a href="`list`">list</a>[<a href="`dict`">dict</a>]</td> 1188<td>List of schema records.</td> 1189</tr> 1190</tbody> 1191</table> 1192</section> 1193</section> 1194<section id="atdata.atmosphere.AtmosphereClient.login" class="level3"> 1195<h3 class="anchored" data-anchor-id="atdata.atmosphere.AtmosphereClient.login">login</h3> 1196<div class="sourceCode" id="cb13"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>atmosphere.AtmosphereClient.login(handle, password)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 1197<p>Authenticate with the ATProto PDS.</p> 1198<section id="parameters-9" class="level4 doc-section doc-section-parameters"> 1199<h4 class="doc-section doc-section-parameters anchored" data-anchor-id="parameters-9">Parameters</h4> 1200<table class="caption-top table"> 1201<thead> 1202<tr class="header"> 1203<th>Name</th> 1204<th>Type</th> 1205<th>Description</th> 1206<th>Default</th> 1207</tr> 1208</thead> 1209<tbody> 1210<tr class="odd"> 1211<td>handle</td> 1212<td><a href="`str`">str</a></td> 1213<td>Your Bluesky handle (e.g., ‘alice.bsky.social’).</td> 1214<td><em>required</em></td> 1215</tr> 1216<tr class="even"> 1217<td>password</td> 1218<td><a href="`str`">str</a></td> 1219<td>App-specific password (not your main password).</td> 1220<td><em>required</em></td> 1221</tr> 1222</tbody> 1223</table> 1224</section> 1225<section id="raises-7" class="level4 doc-section doc-section-raises"> 1226<h4 class="doc-section doc-section-raises anchored" data-anchor-id="raises-7">Raises</h4> 1227<table class="caption-top table"> 1228<thead> 1229<tr class="header"> 1230<th>Name</th> 1231<th>Type</th> 1232<th>Description</th> 1233</tr> 1234</thead> 1235<tbody> 1236<tr class="odd"> 1237<td></td> 1238<td><a href="`atproto`">atproto</a>.<a href="`atproto.exceptions`">exceptions</a>.<a href="`atproto.exceptions.AtProtocolError`">AtProtocolError</a></td> 1239<td>If authentication fails.</td> 1240</tr> 1241</tbody> 1242</table> 1243</section> 1244</section> 1245<section id="atdata.atmosphere.AtmosphereClient.login_with_session" class="level3"> 1246<h3 class="anchored" data-anchor-id="atdata.atmosphere.AtmosphereClient.login_with_session">login_with_session</h3> 1247<div class="sourceCode" id="cb14"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a>atmosphere.AtmosphereClient.login_with_session(session_string)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 1248<p>Authenticate using an exported session string.</p> 1249<p>This allows reusing a session without re-authenticating, which helps avoid rate limits on session creation.</p> 1250<section id="parameters-10" class="level4 doc-section doc-section-parameters"> 1251<h4 class="doc-section doc-section-parameters anchored" data-anchor-id="parameters-10">Parameters</h4> 1252<table class="caption-top table"> 1253<thead> 1254<tr class="header"> 1255<th>Name</th> 1256<th>Type</th> 1257<th>Description</th> 1258<th>Default</th> 1259</tr> 1260</thead> 1261<tbody> 1262<tr class="odd"> 1263<td>session_string</td> 1264<td><a href="`str`">str</a></td> 1265<td>Session string from <code>export_session()</code>.</td> 1266<td><em>required</em></td> 1267</tr> 1268</tbody> 1269</table> 1270</section> 1271</section> 1272<section id="atdata.atmosphere.AtmosphereClient.put_record" class="level3"> 1273<h3 class="anchored" data-anchor-id="atdata.atmosphere.AtmosphereClient.put_record">put_record</h3> 1274<div class="sourceCode" id="cb15"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>atmosphere.AtmosphereClient.put_record(</span> 1275<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a> collection,</span> 1276<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a> rkey,</span> 1277<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a> record,</span> 1278<span id="cb15-5"><a href="#cb15-5" aria-hidden="true" tabindex="-1"></a> <span class="op">*</span>,</span> 1279<span id="cb15-6"><a href="#cb15-6" aria-hidden="true" tabindex="-1"></a> validate<span class="op">=</span><span class="va">False</span>,</span> 1280<span id="cb15-7"><a href="#cb15-7" aria-hidden="true" tabindex="-1"></a> swap_commit<span class="op">=</span><span class="va">None</span>,</span> 1281<span id="cb15-8"><a href="#cb15-8" aria-hidden="true" tabindex="-1"></a>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 1282<p>Create or update a record at a specific key.</p> 1283<section id="parameters-11" class="level4 doc-section doc-section-parameters"> 1284<h4 class="doc-section doc-section-parameters anchored" data-anchor-id="parameters-11">Parameters</h4> 1285<table class="caption-top table"> 1286<thead> 1287<tr class="header"> 1288<th>Name</th> 1289<th>Type</th> 1290<th>Description</th> 1291<th>Default</th> 1292</tr> 1293</thead> 1294<tbody> 1295<tr class="odd"> 1296<td>collection</td> 1297<td><a href="`str`">str</a></td> 1298<td>The NSID of the record collection.</td> 1299<td><em>required</em></td> 1300</tr> 1301<tr class="even"> 1302<td>rkey</td> 1303<td><a href="`str`">str</a></td> 1304<td>The record key.</td> 1305<td><em>required</em></td> 1306</tr> 1307<tr class="odd"> 1308<td>record</td> 1309<td><a href="`dict`">dict</a></td> 1310<td>The record data. Must include a ‘$type’ field.</td> 1311<td><em>required</em></td> 1312</tr> 1313<tr class="even"> 1314<td>validate</td> 1315<td><a href="`bool`">bool</a></td> 1316<td>Whether to validate against the Lexicon schema.</td> 1317<td><code>False</code></td> 1318</tr> 1319<tr class="odd"> 1320<td>swap_commit</td> 1321<td><a href="`typing.Optional`">Optional</a>[<a href="`str`">str</a>]</td> 1322<td>Optional CID for compare-and-swap update.</td> 1323<td><code>None</code></td> 1324</tr> 1325</tbody> 1326</table> 1327</section> 1328<section id="returns-9" class="level4 doc-section doc-section-returns"> 1329<h4 class="doc-section doc-section-returns anchored" data-anchor-id="returns-9">Returns</h4> 1330<table class="caption-top table"> 1331<thead> 1332<tr class="header"> 1333<th>Name</th> 1334<th>Type</th> 1335<th>Description</th> 1336</tr> 1337</thead> 1338<tbody> 1339<tr class="odd"> 1340<td></td> 1341<td><a href="`atdata.atmosphere._types.AtUri`">AtUri</a></td> 1342<td>The AT URI of the record.</td> 1343</tr> 1344</tbody> 1345</table> 1346</section> 1347<section id="raises-8" class="level4 doc-section doc-section-raises"> 1348<h4 class="doc-section doc-section-raises anchored" data-anchor-id="raises-8">Raises</h4> 1349<table class="caption-top table"> 1350<thead> 1351<tr class="header"> 1352<th>Name</th> 1353<th>Type</th> 1354<th>Description</th> 1355</tr> 1356</thead> 1357<tbody> 1358<tr class="odd"> 1359<td></td> 1360<td><a href="`ValueError`">ValueError</a></td> 1361<td>If not authenticated.</td> 1362</tr> 1363<tr class="even"> 1364<td></td> 1365<td><a href="`atproto`">atproto</a>.<a href="`atproto.exceptions`">exceptions</a>.<a href="`atproto.exceptions.AtProtocolError`">AtProtocolError</a></td> 1366<td>If operation fails.</td> 1367</tr> 1368</tbody> 1369</table> 1370</section> 1371</section> 1372<section id="atdata.atmosphere.AtmosphereClient.upload_blob" class="level3"> 1373<h3 class="anchored" data-anchor-id="atdata.atmosphere.AtmosphereClient.upload_blob">upload_blob</h3> 1374<div class="sourceCode" id="cb16"><pre class="sourceCode python code-with-copy"><code class="sourceCode python"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a>atmosphere.AtmosphereClient.upload_blob(</span> 1375<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a> data,</span> 1376<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a> mime_type<span class="op">=</span><span class="st">'application/octet-stream'</span>,</span> 1377<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a>)</span></code><button title="Copy to Clipboard" class="code-copy-button"><i class="bi"></i></button></pre></div> 1378<p>Upload binary data as a blob to the PDS.</p> 1379<section id="parameters-12" class="level4 doc-section doc-section-parameters"> 1380<h4 class="doc-section doc-section-parameters anchored" data-anchor-id="parameters-12">Parameters</h4> 1381<table class="caption-top table"> 1382<thead> 1383<tr class="header"> 1384<th>Name</th> 1385<th>Type</th> 1386<th>Description</th> 1387<th>Default</th> 1388</tr> 1389</thead> 1390<tbody> 1391<tr class="odd"> 1392<td>data</td> 1393<td><a href="`bytes`">bytes</a></td> 1394<td>Binary data to upload.</td> 1395<td><em>required</em></td> 1396</tr> 1397<tr class="even"> 1398<td>mime_type</td> 1399<td><a href="`str`">str</a></td> 1400<td>MIME type of the data (for reference, not enforced by PDS).</td> 1401<td><code>'application/octet-stream'</code></td> 1402</tr> 1403</tbody> 1404</table> 1405</section> 1406<section id="returns-10" class="level4 doc-section doc-section-returns"> 1407<h4 class="doc-section doc-section-returns anchored" data-anchor-id="returns-10">Returns</h4> 1408<table class="caption-top table"> 1409<thead> 1410<tr class="header"> 1411<th>Name</th> 1412<th>Type</th> 1413<th>Description</th> 1414</tr> 1415</thead> 1416<tbody> 1417<tr class="odd"> 1418<td></td> 1419<td><a href="`dict`">dict</a></td> 1420<td>A blob reference dict with keys: ‘$type’, ‘ref’, ‘mimeType’, ‘size’.</td> 1421</tr> 1422<tr class="even"> 1423<td></td> 1424<td><a href="`dict`">dict</a></td> 1425<td>This can be embedded directly in record fields.</td> 1426</tr> 1427</tbody> 1428</table> 1429</section> 1430<section id="raises-9" class="level4 doc-section doc-section-raises"> 1431<h4 class="doc-section doc-section-raises anchored" data-anchor-id="raises-9">Raises</h4> 1432<table class="caption-top table"> 1433<thead> 1434<tr class="header"> 1435<th>Name</th> 1436<th>Type</th> 1437<th>Description</th> 1438</tr> 1439</thead> 1440<tbody> 1441<tr class="odd"> 1442<td></td> 1443<td><a href="`ValueError`">ValueError</a></td> 1444<td>If not authenticated.</td> 1445</tr> 1446<tr class="even"> 1447<td></td> 1448<td><a href="`atproto`">atproto</a>.<a href="`atproto.exceptions`">exceptions</a>.<a href="`atproto.exceptions.AtProtocolError`">AtProtocolError</a></td> 1449<td>If upload fails.</td> 1450</tr> 1451</tbody> 1452</table> 1453 1454 1455</section> 1456</section> 1457</section> 1458</section> 1459 1460</main> <!-- /main --> 1461<script id="quarto-html-after-body" type="application/javascript"> 1462 window.document.addEventListener("DOMContentLoaded", function (event) { 1463 // Ensure there is a toggle, if there isn't float one in the top right 1464 if (window.document.querySelector('.quarto-color-scheme-toggle') === null) { 1465 const a = window.document.createElement('a'); 1466 a.classList.add('top-right'); 1467 a.classList.add('quarto-color-scheme-toggle'); 1468 a.href = ""; 1469 a.onclick = function() { try { window.quartoToggleColorScheme(); } catch {} return false; }; 1470 const i = window.document.createElement("i"); 1471 i.classList.add('bi'); 1472 a.appendChild(i); 1473 window.document.body.appendChild(a); 1474 } 1475 setColorSchemeToggle(hasAlternateSentinel()) 1476 const icon = ""; 1477 const anchorJS = new window.AnchorJS(); 1478 anchorJS.options = { 1479 placement: 'right', 1480 icon: icon 1481 }; 1482 anchorJS.add('.anchored'); 1483 const isCodeAnnotation = (el) => { 1484 for (const clz of el.classList) { 1485 if (clz.startsWith('code-annotation-')) { 1486 return true; 1487 } 1488 } 1489 return false; 1490 } 1491 const onCopySuccess = function(e) { 1492 // button target 1493 const button = e.trigger; 1494 // don't keep focus 1495 button.blur(); 1496 // flash "checked" 1497 button.classList.add('code-copy-button-checked'); 1498 var currentTitle = button.getAttribute("title"); 1499 button.setAttribute("title", "Copied!"); 1500 let tooltip; 1501 if (window.bootstrap) { 1502 button.setAttribute("data-bs-toggle", "tooltip"); 1503 button.setAttribute("data-bs-placement", "left"); 1504 button.setAttribute("data-bs-title", "Copied!"); 1505 tooltip = new bootstrap.Tooltip(button, 1506 { trigger: "manual", 1507 customClass: "code-copy-button-tooltip", 1508 offset: [0, -8]}); 1509 tooltip.show(); 1510 } 1511 setTimeout(function() { 1512 if (tooltip) { 1513 tooltip.hide(); 1514 button.removeAttribute("data-bs-title"); 1515 button.removeAttribute("data-bs-toggle"); 1516 button.removeAttribute("data-bs-placement"); 1517 } 1518 button.setAttribute("title", currentTitle); 1519 button.classList.remove('code-copy-button-checked'); 1520 }, 1000); 1521 // clear code selection 1522 e.clearSelection(); 1523 } 1524 const getTextToCopy = function(trigger) { 1525 const codeEl = trigger.previousElementSibling.cloneNode(true); 1526 for (const childEl of codeEl.children) { 1527 if (isCodeAnnotation(childEl)) { 1528 childEl.remove(); 1529 } 1530 } 1531 return codeEl.innerText; 1532 } 1533 const clipboard = new window.ClipboardJS('.code-copy-button:not([data-in-quarto-modal])', { 1534 text: getTextToCopy 1535 }); 1536 clipboard.on('success', onCopySuccess); 1537 if (window.document.getElementById('quarto-embedded-source-code-modal')) { 1538 const clipboardModal = new window.ClipboardJS('.code-copy-button[data-in-quarto-modal]', { 1539 text: getTextToCopy, 1540 container: window.document.getElementById('quarto-embedded-source-code-modal') 1541 }); 1542 clipboardModal.on('success', onCopySuccess); 1543 } 1544 var localhostRegex = new RegExp(/^(?:http|https):\/\/localhost\:?[0-9]*\//); 1545 var mailtoRegex = new RegExp(/^mailto:/); 1546 var filterRegex = new RegExp("https:\/\/github\.com\/your-org\/atdata"); 1547 var isInternal = (href) => { 1548 return filterRegex.test(href) || localhostRegex.test(href) || mailtoRegex.test(href); 1549 } 1550 // Inspect non-navigation links and adorn them if external 1551 var links = window.document.querySelectorAll('a[href]:not(.nav-link):not(.navbar-brand):not(.toc-action):not(.sidebar-link):not(.sidebar-item-toggle):not(.pagination-link):not(.no-external):not([aria-hidden]):not(.dropdown-item):not(.quarto-navigation-tool):not(.about-link)'); 1552 for (var i=0; i<links.length; i++) { 1553 const link = links[i]; 1554 if (!isInternal(link.href)) { 1555 // undo the damage that might have been done by quarto-nav.js in the case of 1556 // links that we want to consider external 1557 if (link.dataset.originalHref !== undefined) { 1558 link.href = link.dataset.originalHref; 1559 } 1560 } 1561 } 1562 function tippyHover(el, contentFn, onTriggerFn, onUntriggerFn) { 1563 const config = { 1564 allowHTML: true, 1565 maxWidth: 500, 1566 delay: 100, 1567 arrow: false, 1568 appendTo: function(el) { 1569 return el.parentElement; 1570 }, 1571 interactive: true, 1572 interactiveBorder: 10, 1573 theme: 'quarto', 1574 placement: 'bottom-start', 1575 }; 1576 if (contentFn) { 1577 config.content = contentFn; 1578 } 1579 if (onTriggerFn) { 1580 config.onTrigger = onTriggerFn; 1581 } 1582 if (onUntriggerFn) { 1583 config.onUntrigger = onUntriggerFn; 1584 } 1585 window.tippy(el, config); 1586 } 1587 const noterefs = window.document.querySelectorAll('a[role="doc-noteref"]'); 1588 for (var i=0; i<noterefs.length; i++) { 1589 const ref = noterefs[i]; 1590 tippyHover(ref, function() { 1591 // use id or data attribute instead here 1592 let href = ref.getAttribute('data-footnote-href') || ref.getAttribute('href'); 1593 try { href = new URL(href).hash; } catch {} 1594 const id = href.replace(/^#\/?/, ""); 1595 const note = window.document.getElementById(id); 1596 if (note) { 1597 return note.innerHTML; 1598 } else { 1599 return ""; 1600 } 1601 }); 1602 } 1603 const xrefs = window.document.querySelectorAll('a.quarto-xref'); 1604 const processXRef = (id, note) => { 1605 // Strip column container classes 1606 const stripColumnClz = (el) => { 1607 el.classList.remove("page-full", "page-columns"); 1608 if (el.children) { 1609 for (const child of el.children) { 1610 stripColumnClz(child); 1611 } 1612 } 1613 } 1614 stripColumnClz(note) 1615 if (id === null || id.startsWith('sec-')) { 1616 // Special case sections, only their first couple elements 1617 const container = document.createElement("div"); 1618 if (note.children && note.children.length > 2) { 1619 container.appendChild(note.children[0].cloneNode(true)); 1620 for (let i = 1; i < note.children.length; i++) { 1621 const child = note.children[i]; 1622 if (child.tagName === "P" && child.innerText === "") { 1623 continue; 1624 } else { 1625 container.appendChild(child.cloneNode(true)); 1626 break; 1627 } 1628 } 1629 if (window.Quarto?.typesetMath) { 1630 window.Quarto.typesetMath(container); 1631 } 1632 return container.innerHTML 1633 } else { 1634 if (window.Quarto?.typesetMath) { 1635 window.Quarto.typesetMath(note); 1636 } 1637 return note.innerHTML; 1638 } 1639 } else { 1640 // Remove any anchor links if they are present 1641 const anchorLink = note.querySelector('a.anchorjs-link'); 1642 if (anchorLink) { 1643 anchorLink.remove(); 1644 } 1645 if (window.Quarto?.typesetMath) { 1646 window.Quarto.typesetMath(note); 1647 } 1648 if (note.classList.contains("callout")) { 1649 return note.outerHTML; 1650 } else { 1651 return note.innerHTML; 1652 } 1653 } 1654 } 1655 for (var i=0; i<xrefs.length; i++) { 1656 const xref = xrefs[i]; 1657 tippyHover(xref, undefined, function(instance) { 1658 instance.disable(); 1659 let url = xref.getAttribute('href'); 1660 let hash = undefined; 1661 if (url.startsWith('#')) { 1662 hash = url; 1663 } else { 1664 try { hash = new URL(url).hash; } catch {} 1665 } 1666 if (hash) { 1667 const id = hash.replace(/^#\/?/, ""); 1668 const note = window.document.getElementById(id); 1669 if (note !== null) { 1670 try { 1671 const html = processXRef(id, note.cloneNode(true)); 1672 instance.setContent(html); 1673 } finally { 1674 instance.enable(); 1675 instance.show(); 1676 } 1677 } else { 1678 // See if we can fetch this 1679 fetch(url.split('#')[0]) 1680 .then(res => res.text()) 1681 .then(html => { 1682 const parser = new DOMParser(); 1683 const htmlDoc = parser.parseFromString(html, "text/html"); 1684 const note = htmlDoc.getElementById(id); 1685 if (note !== null) { 1686 const html = processXRef(id, note); 1687 instance.setContent(html); 1688 } 1689 }).finally(() => { 1690 instance.enable(); 1691 instance.show(); 1692 }); 1693 } 1694 } else { 1695 // See if we can fetch a full url (with no hash to target) 1696 // This is a special case and we should probably do some content thinning / targeting 1697 fetch(url) 1698 .then(res => res.text()) 1699 .then(html => { 1700 const parser = new DOMParser(); 1701 const htmlDoc = parser.parseFromString(html, "text/html"); 1702 const note = htmlDoc.querySelector('main.content'); 1703 if (note !== null) { 1704 // This should only happen for chapter cross references 1705 // (since there is no id in the URL) 1706 // remove the first header 1707 if (note.children.length > 0 && note.children[0].tagName === "HEADER") { 1708 note.children[0].remove(); 1709 } 1710 const html = processXRef(null, note); 1711 instance.setContent(html); 1712 } 1713 }).finally(() => { 1714 instance.enable(); 1715 instance.show(); 1716 }); 1717 } 1718 }, function(instance) { 1719 }); 1720 } 1721 let selectedAnnoteEl; 1722 const selectorForAnnotation = ( cell, annotation) => { 1723 let cellAttr = 'data-code-cell="' + cell + '"'; 1724 let lineAttr = 'data-code-annotation="' + annotation + '"'; 1725 const selector = 'span[' + cellAttr + '][' + lineAttr + ']'; 1726 return selector; 1727 } 1728 const selectCodeLines = (annoteEl) => { 1729 const doc = window.document; 1730 const targetCell = annoteEl.getAttribute("data-target-cell"); 1731 const targetAnnotation = annoteEl.getAttribute("data-target-annotation"); 1732 const annoteSpan = window.document.querySelector(selectorForAnnotation(targetCell, targetAnnotation)); 1733 const lines = annoteSpan.getAttribute("data-code-lines").split(","); 1734 const lineIds = lines.map((line) => { 1735 return targetCell + "-" + line; 1736 }) 1737 let top = null; 1738 let height = null; 1739 let parent = null; 1740 if (lineIds.length > 0) { 1741 //compute the position of the single el (top and bottom and make a div) 1742 const el = window.document.getElementById(lineIds[0]); 1743 top = el.offsetTop; 1744 height = el.offsetHeight; 1745 parent = el.parentElement.parentElement; 1746 if (lineIds.length > 1) { 1747 const lastEl = window.document.getElementById(lineIds[lineIds.length - 1]); 1748 const bottom = lastEl.offsetTop + lastEl.offsetHeight; 1749 height = bottom - top; 1750 } 1751 if (top !== null && height !== null && parent !== null) { 1752 // cook up a div (if necessary) and position it 1753 let div = window.document.getElementById("code-annotation-line-highlight"); 1754 if (div === null) { 1755 div = window.document.createElement("div"); 1756 div.setAttribute("id", "code-annotation-line-highlight"); 1757 div.style.position = 'absolute'; 1758 parent.appendChild(div); 1759 } 1760 div.style.top = top - 2 + "px"; 1761 div.style.height = height + 4 + "px"; 1762 div.style.left = 0; 1763 let gutterDiv = window.document.getElementById("code-annotation-line-highlight-gutter"); 1764 if (gutterDiv === null) { 1765 gutterDiv = window.document.createElement("div"); 1766 gutterDiv.setAttribute("id", "code-annotation-line-highlight-gutter"); 1767 gutterDiv.style.position = 'absolute'; 1768 const codeCell = window.document.getElementById(targetCell); 1769 const gutter = codeCell.querySelector('.code-annotation-gutter'); 1770 gutter.appendChild(gutterDiv); 1771 } 1772 gutterDiv.style.top = top - 2 + "px"; 1773 gutterDiv.style.height = height + 4 + "px"; 1774 } 1775 selectedAnnoteEl = annoteEl; 1776 } 1777 }; 1778 const unselectCodeLines = () => { 1779 const elementsIds = ["code-annotation-line-highlight", "code-annotation-line-highlight-gutter"]; 1780 elementsIds.forEach((elId) => { 1781 const div = window.document.getElementById(elId); 1782 if (div) { 1783 div.remove(); 1784 } 1785 }); 1786 selectedAnnoteEl = undefined; 1787 }; 1788 // Handle positioning of the toggle 1789 window.addEventListener( 1790 "resize", 1791 throttle(() => { 1792 elRect = undefined; 1793 if (selectedAnnoteEl) { 1794 selectCodeLines(selectedAnnoteEl); 1795 } 1796 }, 10) 1797 ); 1798 function throttle(fn, ms) { 1799 let throttle = false; 1800 let timer; 1801 return (...args) => { 1802 if(!throttle) { // first call gets through 1803 fn.apply(this, args); 1804 throttle = true; 1805 } else { // all the others get throttled 1806 if(timer) clearTimeout(timer); // cancel #2 1807 timer = setTimeout(() => { 1808 fn.apply(this, args); 1809 timer = throttle = false; 1810 }, ms); 1811 } 1812 }; 1813 } 1814 // Attach click handler to the DT 1815 const annoteDls = window.document.querySelectorAll('dt[data-target-cell]'); 1816 for (const annoteDlNode of annoteDls) { 1817 annoteDlNode.addEventListener('click', (event) => { 1818 const clickedEl = event.target; 1819 if (clickedEl !== selectedAnnoteEl) { 1820 unselectCodeLines(); 1821 const activeEl = window.document.querySelector('dt[data-target-cell].code-annotation-active'); 1822 if (activeEl) { 1823 activeEl.classList.remove('code-annotation-active'); 1824 } 1825 selectCodeLines(clickedEl); 1826 clickedEl.classList.add('code-annotation-active'); 1827 } else { 1828 // Unselect the line 1829 unselectCodeLines(); 1830 clickedEl.classList.remove('code-annotation-active'); 1831 } 1832 }); 1833 } 1834 const findCites = (el) => { 1835 const parentEl = el.parentElement; 1836 if (parentEl) { 1837 const cites = parentEl.dataset.cites; 1838 if (cites) { 1839 return { 1840 el, 1841 cites: cites.split(' ') 1842 }; 1843 } else { 1844 return findCites(el.parentElement) 1845 } 1846 } else { 1847 return undefined; 1848 } 1849 }; 1850 var bibliorefs = window.document.querySelectorAll('a[role="doc-biblioref"]'); 1851 for (var i=0; i<bibliorefs.length; i++) { 1852 const ref = bibliorefs[i]; 1853 const citeInfo = findCites(ref); 1854 if (citeInfo) { 1855 tippyHover(citeInfo.el, function() { 1856 var popup = window.document.createElement('div'); 1857 citeInfo.cites.forEach(function(cite) { 1858 var citeDiv = window.document.createElement('div'); 1859 citeDiv.classList.add('hanging-indent'); 1860 citeDiv.classList.add('csl-entry'); 1861 var biblioDiv = window.document.getElementById('ref-' + cite); 1862 if (biblioDiv) { 1863 citeDiv.innerHTML = biblioDiv.innerHTML; 1864 } 1865 popup.appendChild(citeDiv); 1866 }); 1867 return popup.innerHTML; 1868 }); 1869 } 1870 } 1871 }); 1872 </script> 1873</div> <!-- /content --> 1874<footer class="footer"> 1875 <div class="nav-footer"> 1876 <div class="nav-footer-left"> 1877<p>Built with <a href="https://quarto.org/">Quarto</a></p> 1878</div> 1879 <div class="nav-footer-center"> 1880 &nbsp; 1881 <div class="toc-actions d-sm-block d-md-none"><ul><li><a href="https://github.com/your-org/atdata/edit/main/api/AtmosphereClient.qmd" class="toc-action"><i class="bi bi-github"></i>Edit this page</a></li><li><a href="https://github.com/your-org/atdata/issues/new" class="toc-action"><i class="bi empty"></i>Report an issue</a></li></ul></div></div> 1882 <div class="nav-footer-right"> 1883<p>MIT License</p> 1884</div> 1885 </div> 1886</footer> 1887 1888 1889 1890 1891</body></html>