mostlyright-data 0.31.1__tar.gz → 0.31.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/PKG-INFO +1 -1
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/transport.py +227 -1
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_public.py +17 -1
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/.gitignore +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/README.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/pyproject.toml +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/scripts/hatch_build.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/SKILL.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/agents/openai.yaml +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/1-open-the-page-and-the-link-to-it-in-the-first-message.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/2-brief-two-to-four-questions-each-with-a-recommended-answer.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/3-probe-read-a-source-before-committing-to-it.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/4-decide-say-what-you-chose-what-you-refused-and-ask-one-question.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/5-draft-one-recipe-document-one-call.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/6-build-one-run-sized-to-acquire-every-measured-source-whole.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/7-interrogate-ask-the-run-what-it-actually-delivered.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/8-fix-revise-the-document-and-register-it-again.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/9-present-only-what-survived-inspection-with-caveats.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/agent-protocol.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/autonomous-delivery.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/before-the-first-tool-call.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/boundaries.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/cloud-authentication-preflight.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/commands.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/cross-repository-protocol-reference.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/enriching-with-small-models.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/installation-parity.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/live-run.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/making-a-table-incremental.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/narrating-the-run.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/not-hosted-yet.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/one-install.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/patterns.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/prediction-labels.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/preparing-table-search.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/promote.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/readers.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/receipts.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/recipe-test.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/recording-a-stream-venue.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/recovering-an-import-failure.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/reference-pages.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/required-protocol.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/source-credentials.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/sources.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/the-one-thing-to-say-about-the-skill-itself.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/transforms.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/user-communication-contract.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/writing-a-decision-record.md +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/scripts/write_research_notebook.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/__init__.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/agent_protocol.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/canonical.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/formats.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/hosted_crawler_protocol.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/key_seam.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/page_coverage.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/part_check_evidence.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/session_probes.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/skill_assets.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/table_manifest.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/__init__.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/acquire.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/acquire_cancel.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/activity.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/approvals.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/backoff.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/categories.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/commands.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/dataset-categories-v1.json +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/download.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/enrichment.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/fast_features.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/matching_benchmark.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/narrative.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/parity.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/probe.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/progress_rate.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/progress_vocabulary.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/propose.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/recipe.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/recipe_brief.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/recipe_explain.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/recipe_forecast.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/recipe_lint.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/recipe_test.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/refresh_rehearsal.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/release_check.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/research.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/router.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/run_diagnose.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/run_prefix.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/runs.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/session.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/stream.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/stream_venue.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/studio_capabilities.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/support.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/table_search_contract.json +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/user_agent.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_artifacts.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_catalog.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_connected.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_connections.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_dataset_covers.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_datasets.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_handoff.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_matching.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_narrative.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_query.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_reader.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_runs.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_search.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_search_contract.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_secrets.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_stream.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_tables.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/vocabulary.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/__init__.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/attendance.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/clarification.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/cloud_auth.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/commands/__init__.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/commands/auth.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/commands/clarify.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/commands/login.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/commands/whoami.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/credential_native.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/credential_store.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/credentials.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/login.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/path_kind.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/plain_file.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/remediation.py +0 -0
- {mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/render.py +0 -0
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/transport.py
RENAMED
|
@@ -10,10 +10,20 @@ to relax any of it.
|
|
|
10
10
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
|
+
import hashlib
|
|
14
|
+
import http.client
|
|
13
15
|
import ipaddress
|
|
16
|
+
import math
|
|
17
|
+
import re
|
|
14
18
|
import ssl
|
|
19
|
+
import threading
|
|
20
|
+
import time
|
|
15
21
|
from collections.abc import Callable, Iterator, Mapping
|
|
16
22
|
from contextlib import contextmanager
|
|
23
|
+
from email.message import Message
|
|
24
|
+
from email.utils import parsedate_to_datetime
|
|
25
|
+
from http.cookiejar import Cookie, CookieJar, DefaultCookiePolicy
|
|
26
|
+
from http.cookies import CookieError, SimpleCookie
|
|
17
27
|
from typing import Any, Protocol
|
|
18
28
|
from urllib.error import HTTPError
|
|
19
29
|
from urllib.parse import urlsplit
|
|
@@ -119,8 +129,9 @@ class UrlLibTransport:
|
|
|
119
129
|
|
|
120
130
|
def __init__(self, *, timeout: float | Callable[[], float] = REQUEST_TIMEOUT_SECONDS) -> None:
|
|
121
131
|
self._timeout = timeout if callable(timeout) else float(timeout)
|
|
132
|
+
self._context = ssl.create_default_context()
|
|
122
133
|
self._opener = build_opener(
|
|
123
|
-
ProxyHandler({}), HTTPSHandler(context=
|
|
134
|
+
ProxyHandler({}), HTTPSHandler(context=self._context), _NoRedirect()
|
|
124
135
|
)
|
|
125
136
|
|
|
126
137
|
def _clock(self) -> float:
|
|
@@ -171,6 +182,221 @@ class UrlLibTransport:
|
|
|
171
182
|
response.close()
|
|
172
183
|
|
|
173
184
|
|
|
185
|
+
class _RoutingCookiePolicy(DefaultCookiePolicy):
|
|
186
|
+
"""Only Cloud Run's observed host-only routing cookie is retained."""
|
|
187
|
+
|
|
188
|
+
def set_ok(self, cookie: Cookie, request: Request) -> bool:
|
|
189
|
+
if (
|
|
190
|
+
cookie.name != "GAESA"
|
|
191
|
+
or cookie.domain_specified
|
|
192
|
+
or not cookie.path_specified
|
|
193
|
+
or cookie.path != "/"
|
|
194
|
+
or len(cookie.value or "") > 4096
|
|
195
|
+
):
|
|
196
|
+
return False
|
|
197
|
+
# Cloud Run emits this without Secure. The transport accepts only
|
|
198
|
+
# verified HTTPS, and the stored form must never permit an HTTP send.
|
|
199
|
+
cookie.secure = True
|
|
200
|
+
return super().set_ok(cookie, request)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
class _RoutingCookieResponse:
|
|
204
|
+
def __init__(self, header: str) -> None:
|
|
205
|
+
self.headers = Message()
|
|
206
|
+
self.headers["Set-Cookie"] = header
|
|
207
|
+
|
|
208
|
+
def info(self) -> Message:
|
|
209
|
+
return self.headers
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def _remember_routing_cookie(
|
|
213
|
+
jar: CookieJar, response: http.client.HTTPResponse, request: Request
|
|
214
|
+
) -> None:
|
|
215
|
+
candidates = [
|
|
216
|
+
value
|
|
217
|
+
for key, value in response.getheaders()
|
|
218
|
+
if key.lower() == "set-cookie" and value.partition("=")[0].strip() == "GAESA"
|
|
219
|
+
]
|
|
220
|
+
if len(candidates) != 1:
|
|
221
|
+
return
|
|
222
|
+
header = candidates[0]
|
|
223
|
+
if (
|
|
224
|
+
len(header) > 8192
|
|
225
|
+
or "\r" in header
|
|
226
|
+
or "\n" in header
|
|
227
|
+
or len(re.findall(r"(?:^|[;,])\s*GAESA\s*=", header)) != 1
|
|
228
|
+
):
|
|
229
|
+
return
|
|
230
|
+
parsed = SimpleCookie()
|
|
231
|
+
try:
|
|
232
|
+
parsed.load(header)
|
|
233
|
+
if set(parsed) != {"GAESA"}:
|
|
234
|
+
return
|
|
235
|
+
routing = parsed["GAESA"]
|
|
236
|
+
if not re.fullmatch(r"[\x21\x23-\x2b\x2d-\x3a\x3c-\x5b\x5d-\x7e]*", routing.value):
|
|
237
|
+
return
|
|
238
|
+
if routing["max-age"]:
|
|
239
|
+
age = routing["max-age"]
|
|
240
|
+
if (
|
|
241
|
+
not re.fullmatch(r"-?\d+", age)
|
|
242
|
+
or len(age.lstrip("-")) > 10
|
|
243
|
+
or abs(int(age)) > 2_147_483_647
|
|
244
|
+
):
|
|
245
|
+
return
|
|
246
|
+
if routing["expires"]:
|
|
247
|
+
parsedate_to_datetime(routing["expires"])
|
|
248
|
+
except (CookieError, ValueError, OverflowError):
|
|
249
|
+
return
|
|
250
|
+
try:
|
|
251
|
+
jar.extract_cookies(_RoutingCookieResponse(header), request)
|
|
252
|
+
except (ValueError, OverflowError):
|
|
253
|
+
# Optional routing metadata must never invalidate a complete answer.
|
|
254
|
+
return
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
class ReusableHttpsTransport(UrlLibTransport):
|
|
258
|
+
"""One serialized, verified HTTPS connection for repeated query requests.
|
|
259
|
+
|
|
260
|
+
urllib deliberately sends Connection: close. A query client reuses its
|
|
261
|
+
own connection instead, never a global credential-bearing pool. Changing
|
|
262
|
+
origin closes the old socket. Responses are bounded and fully framed;
|
|
263
|
+
any failure discards the socket and is raised without replaying a POST.
|
|
264
|
+
Only the host-only root GAESA routing cookie is retained in memory, bound
|
|
265
|
+
to this client's exact origin and authorization context, never login cookies.
|
|
266
|
+
Streams retain the original urllib/proxy-free/redirect-free behavior.
|
|
267
|
+
"""
|
|
268
|
+
|
|
269
|
+
def __init__(self, *, timeout: float | Callable[[], float] = REQUEST_TIMEOUT_SECONDS) -> None:
|
|
270
|
+
super().__init__(timeout=timeout)
|
|
271
|
+
self._lock = threading.Lock()
|
|
272
|
+
self._connection: http.client.HTTPSConnection | None = None
|
|
273
|
+
self._connection_origin: tuple[str, str, int] | None = None
|
|
274
|
+
self._routing = CookieJar(policy=_RoutingCookiePolicy())
|
|
275
|
+
self._routing_context: tuple[tuple[str, str, int], bytes] | None = None
|
|
276
|
+
|
|
277
|
+
def _discard(self) -> None:
|
|
278
|
+
connection, self._connection = self._connection, None
|
|
279
|
+
self._connection_origin = None
|
|
280
|
+
if connection is not None:
|
|
281
|
+
connection.close()
|
|
282
|
+
|
|
283
|
+
def close(self) -> None:
|
|
284
|
+
with self._lock:
|
|
285
|
+
self._discard()
|
|
286
|
+
self._routing.clear()
|
|
287
|
+
self._routing_context = None
|
|
288
|
+
|
|
289
|
+
def __enter__(self) -> ReusableHttpsTransport:
|
|
290
|
+
return self
|
|
291
|
+
|
|
292
|
+
def __exit__(self, *_args: Any) -> None:
|
|
293
|
+
self.close()
|
|
294
|
+
|
|
295
|
+
def __del__(self) -> None:
|
|
296
|
+
connection = getattr(self, "_connection", None)
|
|
297
|
+
if connection is not None:
|
|
298
|
+
connection.close()
|
|
299
|
+
|
|
300
|
+
def request(
|
|
301
|
+
self, method: str, url: str, headers: Mapping[str, str], body: bytes | None, maximum: int
|
|
302
|
+
) -> tuple[int, bytes, Mapping[str, str]]:
|
|
303
|
+
if type(maximum) is not int or maximum < 0:
|
|
304
|
+
raise ThinLaneError("THIN_REQUEST_INVALID", "the response ceiling must be nonnegative")
|
|
305
|
+
parts = urlsplit(url)
|
|
306
|
+
service_origin(
|
|
307
|
+
f"{parts.scheme}://{parts.netloc}", "request origin", allow_loopback_http=False
|
|
308
|
+
)
|
|
309
|
+
if parts.scheme != "https" or parts.fragment or parts.hostname is None:
|
|
310
|
+
raise ThinLaneError(
|
|
311
|
+
"THIN_REQUEST_INVALID", "a reusable request requires a valid HTTPS URL"
|
|
312
|
+
)
|
|
313
|
+
origin = (parts.scheme, parts.hostname.lower(), parts.port or 443)
|
|
314
|
+
if any(
|
|
315
|
+
name.lower() == "host" and value.lower() != parts.netloc.lower()
|
|
316
|
+
for name, value in headers.items()
|
|
317
|
+
):
|
|
318
|
+
raise ThinLaneError(
|
|
319
|
+
"THIN_REQUEST_INVALID", "the Host header differs from the request origin"
|
|
320
|
+
)
|
|
321
|
+
budget = self._clock()
|
|
322
|
+
if not math.isfinite(budget) or budget <= 0:
|
|
323
|
+
raise TimeoutError("the request deadline has elapsed")
|
|
324
|
+
deadline = time.monotonic() + budget
|
|
325
|
+
if not self._lock.acquire(timeout=budget):
|
|
326
|
+
raise TimeoutError("the request deadline elapsed waiting for its connection")
|
|
327
|
+
|
|
328
|
+
def remaining() -> float:
|
|
329
|
+
value = deadline - time.monotonic()
|
|
330
|
+
if value <= 0:
|
|
331
|
+
raise TimeoutError("the request deadline has elapsed")
|
|
332
|
+
return value
|
|
333
|
+
|
|
334
|
+
try:
|
|
335
|
+
context_headers = sorted(
|
|
336
|
+
(name.lower(), value)
|
|
337
|
+
for name, value in headers.items()
|
|
338
|
+
if name.lower() in {"authorization", "proxy-authorization", "cookie", "x-api-key"}
|
|
339
|
+
)
|
|
340
|
+
context = (origin, hashlib.sha256(repr(context_headers).encode()).digest())
|
|
341
|
+
if context != self._routing_context:
|
|
342
|
+
self._routing.clear()
|
|
343
|
+
self._routing_context = context
|
|
344
|
+
caller_cookie = any(name.lower() == "cookie" for name in headers)
|
|
345
|
+
cookie_request = Request(url, headers=dict(with_user_agent(headers)), method=method)
|
|
346
|
+
if not caller_cookie:
|
|
347
|
+
self._routing.add_cookie_header(cookie_request)
|
|
348
|
+
if self._connection_origin != origin:
|
|
349
|
+
self._discard()
|
|
350
|
+
if self._connection is None:
|
|
351
|
+
self._connection = http.client.HTTPSConnection(
|
|
352
|
+
origin[1], origin[2], timeout=remaining(), context=self._context
|
|
353
|
+
)
|
|
354
|
+
self._connection_origin = origin
|
|
355
|
+
connection = self._connection
|
|
356
|
+
connection.timeout = remaining()
|
|
357
|
+
if connection.sock is not None:
|
|
358
|
+
connection.sock.settimeout(remaining())
|
|
359
|
+
path = parts.path or "/"
|
|
360
|
+
if parts.query:
|
|
361
|
+
path += "?" + parts.query
|
|
362
|
+
connection.request(method, path, body=body, headers=dict(cookie_request.header_items()))
|
|
363
|
+
if connection.sock is not None:
|
|
364
|
+
connection.sock.settimeout(remaining())
|
|
365
|
+
response = connection.getresponse()
|
|
366
|
+
expected = response.length
|
|
367
|
+
chunks: list[bytes] = []
|
|
368
|
+
length = 0
|
|
369
|
+
while length <= maximum:
|
|
370
|
+
if connection.sock is not None:
|
|
371
|
+
connection.sock.settimeout(remaining())
|
|
372
|
+
chunk = response.read1(min(64 * 1024, maximum + 1 - length))
|
|
373
|
+
if not chunk:
|
|
374
|
+
break
|
|
375
|
+
chunks.append(chunk)
|
|
376
|
+
length += len(chunk)
|
|
377
|
+
raw = b"".join(chunks)
|
|
378
|
+
if length > maximum:
|
|
379
|
+
raise ThinLaneError(
|
|
380
|
+
"THIN_RESPONSE_TOO_LARGE",
|
|
381
|
+
"the response exceeded the byte ceiling for its route",
|
|
382
|
+
)
|
|
383
|
+
if expected is not None and length != expected:
|
|
384
|
+
raise http.client.IncompleteRead(raw, expected - length)
|
|
385
|
+
if not caller_cookie:
|
|
386
|
+
_remember_routing_cookie(self._routing, response, cookie_request)
|
|
387
|
+
status = int(response.status)
|
|
388
|
+
response_headers = {key.lower(): value for key, value in response.headers.items()}
|
|
389
|
+
response.close()
|
|
390
|
+
if response.will_close or connection.sock is None or status < 200:
|
|
391
|
+
self._discard()
|
|
392
|
+
return status, raw, response_headers
|
|
393
|
+
except BaseException:
|
|
394
|
+
self._discard()
|
|
395
|
+
raise
|
|
396
|
+
finally:
|
|
397
|
+
self._lock.release()
|
|
398
|
+
|
|
399
|
+
|
|
174
400
|
def service_origin(value: str, label: str, *, allow_loopback_http: bool) -> str:
|
|
175
401
|
"""Return ``value`` when it is a bare HTTPS origin, and refuse it otherwise.
|
|
176
402
|
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_public.py
RENAMED
|
@@ -46,6 +46,7 @@ from mostlyright.data_harness.thin.session import (
|
|
|
46
46
|
)
|
|
47
47
|
from mostlyright.data_harness.thin.transport import (
|
|
48
48
|
MAX_JSON_RESPONSE_BYTES,
|
|
49
|
+
ReusableHttpsTransport,
|
|
49
50
|
ThinLaneError,
|
|
50
51
|
Transport,
|
|
51
52
|
UrlLibTransport,
|
|
@@ -896,10 +897,25 @@ class PublicQueryClient(CloudClient):
|
|
|
896
897
|
def __init__(self, credentials, *, transport=None) -> None:
|
|
897
898
|
# Let Cloud's gateway deadline return its own refusal and request id first.
|
|
898
899
|
super().__init__(credentials, transport=transport)
|
|
900
|
+
self._owned_query_transport = (
|
|
901
|
+
ReusableHttpsTransport(timeout=150.0) if transport is None else None
|
|
902
|
+
)
|
|
899
903
|
self._query_client = CloudClient(
|
|
900
|
-
credentials,
|
|
904
|
+
credentials,
|
|
905
|
+
transport=transport if transport is not None else self._owned_query_transport,
|
|
901
906
|
)
|
|
902
907
|
|
|
908
|
+
def close(self) -> None:
|
|
909
|
+
"""Close this client's owned query connection; injected transports stay caller-owned."""
|
|
910
|
+
if self._owned_query_transport is not None:
|
|
911
|
+
self._owned_query_transport.close()
|
|
912
|
+
|
|
913
|
+
def __enter__(self) -> PublicQueryClient:
|
|
914
|
+
return self
|
|
915
|
+
|
|
916
|
+
def __exit__(self, *_args: Any) -> None:
|
|
917
|
+
self.close()
|
|
918
|
+
|
|
903
919
|
def query_table(self, table_id: str, body: Mapping[str, Any]) -> dict[str, Any]:
|
|
904
920
|
answer = self._query_client.call(
|
|
905
921
|
"POST",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/boundaries.md
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/commands.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/live-run.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/one-install.md
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/patterns.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/promote.md
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/readers.md
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/receipts.md
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/recipe-test.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/sources.md
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/skills/mr-data-build/references/transforms.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/agent_protocol.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/canonical.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/key_seam.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/page_coverage.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/session_probes.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/skill_assets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/table_manifest.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/acquire.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/activity.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/approvals.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/backoff.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/categories.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/commands.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/download.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/enrichment.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/narrative.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/parity.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/probe.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/propose.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/recipe.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/recipe_lint.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/recipe_test.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/research.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/router.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/run_prefix.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/runs.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/session.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/stream.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/support.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/user_agent.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_catalog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_datasets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_handoff.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_matching.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_query.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_reader.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_runs.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_search.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_secrets.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_stream.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/v4_tables.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/thin/vocabulary.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/__init__.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/attendance.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/clarification.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/cloud_auth.py
RENAMED
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/commands/auth.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/credentials.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/login.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/path_kind.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/plain_file.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/remediation.py
RENAMED
|
File without changes
|
{mostlyright_data-0.31.1 → mostlyright_data-0.31.3}/src/mostlyright/data_harness/ux/render.py
RENAMED
|
File without changes
|